Commit 7a2a2e85 authored by 袁兴强's avatar 袁兴强

merge master

parents 623207aa e950a553
...@@ -12,6 +12,8 @@ jobs: ...@@ -12,6 +12,8 @@ jobs:
id: go id: go
- name: checkout - name: checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Intsall Golangci-lint - name: Intsall Golangci-lint
run: | run: |
...@@ -28,6 +30,7 @@ jobs: ...@@ -28,6 +30,7 @@ jobs:
- name: Lint - name: Lint
run: | run: |
make largefile-check
make checkgofmt && make fmt_go make checkgofmt && make fmt_go
make linter make linter
......
...@@ -49,9 +49,9 @@ autotest_tick: autotest ## run with ticket mining ...@@ -49,9 +49,9 @@ autotest_tick: autotest ## run with ticket mining
update: ## version 可以是git tag打的具体版本号,也可以是commit hash, 什么都不填的情况下默认从master分支拉取最新版本 update: ## version 可以是git tag打的具体版本号,也可以是commit hash, 什么都不填的情况下默认从master分支拉取最新版本
@if [ -n "$(version)" ]; then \ @if [ -n "$(version)" ]; then \
go get github.com/33cn/chain33@${version} ; \ go get -v github.com/33cn/chain33@${version} ; \
else \ else \
go get github.com/33cn/chain33@master ;fi go get -v github.com/33cn/chain33@master ;fi
@go mod tidy @go mod tidy
dep: dep:
@go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.18.0 @go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.18.0
...@@ -132,6 +132,9 @@ metrics:## build docker-compose for chain33 metrics ...@@ -132,6 +132,9 @@ metrics:## build docker-compose for chain33 metrics
fork-test: ## build fork-test for chain33 run fork-test: ## build fork-test for chain33 run
@cd build && cp chain33* Dockerfile system-fork-test.sh docker-compose* ci/ && cd ci/ && ./docker-compose-pre.sh forktest $(proj) $(dapp) && cd ../.. @cd build && cp chain33* Dockerfile system-fork-test.sh docker-compose* ci/ && cd ci/ && ./docker-compose-pre.sh forktest $(proj) $(dapp) && cd ../..
largefile-check:
git gc
./findlargefile.sh
clean: ## Remove previous build clean: ## Remove previous build
@rm -rf $(shell find . -name 'datadir' -not -path "./vendor/*") @rm -rf $(shell find . -name 'datadir' -not -path "./vendor/*")
......
go env -w CGO_ENABLED=0
go build -o chain33.exe go build -o chain33.exe
go build -o chain33-cli.exe github.com/33cn/plugin/cli go build -o chain33-cli.exe github.com/33cn/plugin/cli
...@@ -53,6 +53,7 @@ driver="leveldb" ...@@ -53,6 +53,7 @@ driver="leveldb"
dbPath="paradatadir/addrbook" dbPath="paradatadir/addrbook"
dbCache=4 dbCache=4
grpcLogFile="grpc33.log" grpcLogFile="grpc33.log"
waitPid=true
[p2p.sub.dht] [p2p.sub.dht]
DHTDataPath="paradatadir/p2pstore" DHTDataPath="paradatadir/p2pstore"
...@@ -93,7 +94,8 @@ coinDevFund=12 ...@@ -93,7 +94,8 @@ coinDevFund=12
coinBaseReward=3 coinBaseReward=3
#委托账户最少解绑定时间(按小时) #委托账户最少解绑定时间(按小时)
unBindTime=24 unBindTime=24
#支持挖矿奖励的1e8小数模式,比如18coin 需要配置成1800000000 以支持小数位后的配置
#decimalMode=true
[consensus.sub.para] [consensus.sub.para]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802” #主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
......
#!/bin/bash
#set -x
# Shows you the largest objects in your repo's pack file.
# Written for osx.
#
# @see https://stubbisms.wordpress.com/2009/07/10/git-script-to-show-largest-pack-objects-and-trim-your-waist-line/
# @author Antony Stubbs
# set the internal field separator to line break, so that we can iterate easily over the verify-pack output
IFS=$'\n'
# list all objects including their size, sort by size, take top 10
objects=$(git verify-pack -v .git/objects/pack/pack-*.idx | grep -v chain | sort -k3nr | head -n 15)
echo "All sizes are in kB's. The pack column is the size of the object, compressed, inside the pack file."
# 46034 13074 650902c0f310f2f64e9ae5dfda35656ce8dadae3 chain33
# 42998 12325 5e8c0c3e6bc33034fd804d4c68b589c1eb66804b chain33-cli
# 30440 9801 d2d4a3aa838d85738e27ee474c785331bfe8e81c plugin/consensus/raft/tools/scripts/chain33.tgz
# 21292 10288 1e21797c3af8a4385c9169570b9b1c4072d7b3b6 plugin/dapp/exchange/test/cmd/main
# 4834 1113 9ec4f3d49403e8b9dd46885031a92e23af3828b9 vendor/golang.org/x/text/collate/tables.go
# 3468 1767 825659f96c308cd79ed2b32860d45d510dff6cce vendor/github.com/33cn/chain33/doc/golang/Go的50度灰:Golang新开发者要注意的陷阱和常见错误 .pdf
# 2556 863 9df156a7f0c9570431161873e3f605c7e4bb7ba9 vendor/github.com/haltingstate/secp256k1-go/secp256k1-go2/z_consts.go
# 2432 2159 0304d27f62317d2216c3288047a1a2a8bf37d94a vendor/github.com/33cn/chain33/doc/PBFT/pbft.pdf
history="650902c0f310f2f64e9ae5dfda35656ce8dadae3 5e8c0c3e6bc33034fd804d4c68b589c1eb66804b d2d4a3aa838d85738e27ee474c785331bfe8e81c \
1e21797c3af8a4385c9169570b9b1c4072d7b3b6 9ec4f3d49403e8b9dd46885031a92e23af3828b9 825659f96c308cd79ed2b32860d45d510dff6cce \
9df156a7f0c9570431161873e3f605c7e4bb7ba9 0304d27f62317d2216c3288047a1a2a8bf37d94a 0304d27f62317d2216c3288047a1a2a8bf37d94a"
oversize="false"
output="size,pack,SHA,location"
allObjects=$(git rev-list --all --objects)
for y in $objects; do
# extract the size in bytes
size=$(($(echo "$y" | cut -f 5 -d ' ') / 1024))
# extract the compressed size in bytes
compressedSize=$(($(echo "$y" | cut -f 6 -d ' ') / 1024))
# extract the SHA
sha=$(echo "$y" | cut -f 1 -d ' ')
if [[ ! $history =~ $sha ]]; then
if [ $size -ge 2000 ]; then
echo "over size file = $sha"
oversize="true"
fi
fi
# find the objects location in the repository tree
other=$(echo "${allObjects}" | grep "$sha")
#lineBreak=`echo -e "\n"`
output="${output}\n${size},${compressedSize},${other}"
done
echo -e "$output" | column -t -s ', '
if [ "$oversize" == "true" ]; then
echo "there are files over 2M size committed!!!"
exit 1
fi
...@@ -3,7 +3,7 @@ module github.com/33cn/plugin ...@@ -3,7 +3,7 @@ module github.com/33cn/plugin
go 1.12 go 1.12
require ( require (
github.com/33cn/chain33 v0.0.0-20200729032621-0fbd543868cf github.com/33cn/chain33 v1.65.1-0.20201022110501-fde367b8c955
github.com/BurntSushi/toml v0.3.1 github.com/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7 github.com/NebulousLabs/Sia v1.3.7
github.com/NebulousLabs/errors v0.0.0-20181203160057-9f787ce8f69e // indirect github.com/NebulousLabs/errors v0.0.0-20181203160057-9f787ce8f69e // indirect
...@@ -24,26 +24,23 @@ require ( ...@@ -24,26 +24,23 @@ require (
github.com/hashicorp/golang-lru v0.5.4 github.com/hashicorp/golang-lru v0.5.4
github.com/holiman/uint256 v1.1.1 github.com/holiman/uint256 v1.1.1
github.com/huin/goupnp v1.0.0 github.com/huin/goupnp v1.0.0
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 github.com/jackpal/go-nat-pmp v1.0.2
github.com/miguelmota/go-solidity-sha3 v0.1.0 github.com/miguelmota/go-solidity-sha3 v0.1.0
github.com/mr-tron/base58 v1.1.3 github.com/mr-tron/base58 v1.2.0
github.com/pborman/uuid v1.2.0 github.com/pborman/uuid v1.2.0
github.com/perlin-network/life v0.0.0-20191203030451-05c0e0f7eaea github.com/perlin-network/life v0.0.0-20191203030451-05c0e0f7eaea
github.com/phoreproject/bls v0.0.0-20200525203911-a88a5ae26844 github.com/phoreproject/bls v0.0.0-20200525203911-a88a5ae26844
github.com/pkg/errors v0.8.1 github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v0.9.2 // indirect github.com/prometheus/client_golang v0.9.2 // indirect
github.com/prometheus/common v0.4.1 github.com/prometheus/common v0.4.1
github.com/prometheus/procfs v0.0.3 // indirect github.com/prometheus/procfs v0.0.3 // indirect
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d
github.com/rs/cors v1.6.0 github.com/rs/cors v1.6.0
github.com/spf13/cobra v0.0.5 github.com/spf13/cobra v0.0.5
github.com/stretchr/testify v1.4.0 github.com/stretchr/testify v1.6.1
github.com/tjfoc/gmsm v1.3.1 github.com/tjfoc/gmsm v1.3.2
github.com/valyala/fasthttp v1.5.0 github.com/valyala/fasthttp v1.5.0
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
go.uber.org/atomic v1.4.0 // indirect
go.uber.org/multierr v1.2.0 // indirect
go.uber.org/zap v1.10.0 // indirect
golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9
golang.org/x/net v0.0.0-20200301022130-244492dfa37a golang.org/x/net v0.0.0-20200301022130-244492dfa37a
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1
......
This diff is collapsed.
...@@ -26,7 +26,7 @@ const ( ...@@ -26,7 +26,7 @@ const (
maxRcvTxCount = 100 //channel buffer, max 100 nodes, 1 height tx or 1 txgroup per node maxRcvTxCount = 100 //channel buffer, max 100 nodes, 1 height tx or 1 txgroup per node
leaderSyncInt = 15 //15s heartbeat sync interval leaderSyncInt = 15 //15s heartbeat sync interval
defLeaderSwitchInt = 100 //每隔100个共识高度切换一次leader,大约6小时(按50个空块间隔计算) defLeaderSwitchInt = 100 //每隔100个共识高度切换一次leader,大约6小时(按50个空块间隔计算)
delaySubP2pTopic = 30 //30s to sub p2p topic delaySubP2pTopic = 10 //30s to sub p2p topic
paraBlsSignTopic = "PARA-BLS-SIGN-TOPIC" paraBlsSignTopic = "PARA-BLS-SIGN-TOPIC"
) )
......
package paillier
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"math/big"
"github.com/33cn/chain33/common"
)
func CiphertextAdd(ciphertext1, ciphertext2 string) (string, error) {
cipherbytes1, err := common.FromHex(ciphertext1)
if err != nil {
return "", fmt.Errorf("CiphertextAdd.FromHex. ciphertext1:%s, error:%v", ciphertext1, err)
}
cipherbytes2, err := common.FromHex(ciphertext2)
if err != nil {
return "", fmt.Errorf("CiphertextAdd.FromHex. ciphertext2:%s, error:%v", ciphertext2, err)
}
res, err := CiphertextAddBytes(cipherbytes1, cipherbytes2)
if err != nil {
return "", fmt.Errorf("CiphertextAdd.CiphertextAddBytes. error:%v", err)
}
return hex.EncodeToString(res), nil
}
func CiphertextAddBytes(cipherbytes1, cipherbytes2 []byte) ([]byte, error) {
nlen1 := bytesToInt(cipherbytes1[0:2])
if nlen1 >= len(cipherbytes1)-2 {
return nil, fmt.Errorf("CiphertextAddBytes. error param length")
}
nBytes1 := make([]byte, nlen1)
copy(nBytes1, cipherbytes1[2:2+nlen1])
nlen2 := bytesToInt(cipherbytes2[0:2])
if nlen2 >= len(cipherbytes2)-2 {
return nil, fmt.Errorf("CiphertextAddBytes. error param length")
}
nBytes2 := make([]byte, nlen2)
copy(nBytes2, cipherbytes2[2:2+nlen2])
if !bytes.Equal(nBytes1, nBytes2) {
return nil, fmt.Errorf("CiphertextAddBytes. error: param error nBytes1!=nBytes2")
}
data1 := make([]byte, len(cipherbytes1)-nlen1-2)
copy(data1, cipherbytes1[2+nlen1:])
data2 := make([]byte, len(cipherbytes2)-nlen2-2)
copy(data2, cipherbytes2[2+nlen2:])
cipher1 := new(big.Int).SetBytes(data1)
cipher2 := new(big.Int).SetBytes(data2)
n1 := new(big.Int).SetBytes(nBytes1)
nsquare := new(big.Int).Mul(n1, n1)
res := big.NewInt(0)
res.Mul(cipher1, cipher2).Mod(res, nsquare)
data := make([]byte, nlen1+2+len(res.Bytes()))
copy(data[:nlen1+2], cipherbytes1[:nlen1+2])
copy(data[nlen1+2:], res.Bytes())
return data, nil
}
func bytesToInt(cipherbytes []byte) int {
bytebuff := bytes.NewBuffer(cipherbytes)
var data int16
binary.Read(bytebuff, binary.BigEndian, &data)
return int(data)
}
package paillier
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestCiphertextAdd(t *testing.T) {
c1 := "010070061bde0fc57d38e0ce9c82c088f793a93a20f830ed94a5f7e01f5af0decccf0ee7f70a711dc78b69b40f7e411f7f6ff34a5de4ad32fa5dc9d09b09dbbcf8e49bb1c9be19b215577167458b969bb40634f71dba00bdfdd12f1c878effd9e08475b8301a214bc7dfc95c2f341aa8fbd985a5da05af046336c23cf356570772530017c9a8bb96140977698d50c3258e8d31c040bb887c56d3d6e583db7a4ff2ea28aa93885312dfa50bf86a15618288b2c2701e6d75743fec9f3ca35b7e20ad902ad6985fe0b3c389b9582b3c62d9bea90230d1512a07c66a5404bf804693b6bb677a4ff038ae4a762f89f6a877d7621f7461431a7d4cadaf1687057ca4a9d1570e4ceeab32c86856d89731d50edf6f0886ccf348cc4565227f1df6b813569c49b3170e9efd722e4f4e957add9a115a2122a9f5c00780a1b8020d44b8b865d16113eadcfd15d1b755aed7c983b3d4b9390eda68d22d165a32d4055eee95adee79d7d28d2ee6d593d4eff217cd3e3d70bb9c32a6608af78afb7d5cb7ee0422500273b934209b950cd07842ab7e10c0dfc790d212c9085058d39c667b7dfff0963478118451ec64af30aff518384cc47758b2aa4331c8b5f36d6d1b9c3a6ee7ba77d28ea6ca844960e24ab6384e36127745f1285f3b71cea6c5c6a41c51ca7edbfae07766a3fb7bd9ef6b8f999460741a5b44eeb0b98937b57f4582294e18fd70d402dee2e557fa7df5cfb13240458f77b62a32169940ab5a1fce95b52583ecb13e21c22749f7620caaa6fd998e4f9bd0e617c925b83bed5ed2215ec8a404357a782b70d2c6ece6fa7a4fb30d18a01b81b2f3a8e38cc12f32becfdf195e02879b710f2feda5b0c2e86ba6df2a0fa25c60cef58224ee466787034cc5d0872a28cf8d6bad106125660b0b4bfe86eacb829dbb073420ff3af3ac76e5718c199fcf53258397a9e4fed0d98f360d16248693aced1ecbc5ca5211f48df011d14d372ee07f9b7c24bc219f3cdc403ebeb5b452643ddd1f4276779fab76a19c8b195a1213a235f7facf67a26b8a7804cb326f58200d756d62d40edb650498c198a524c091f0"
c2 := "010070061bde0fc57d38e0ce9c82c088f793a93a20f830ed94a5f7e01f5af0decccf0ee7f70a711dc78b69b40f7e411f7f6ff34a5de4ad32fa5dc9d09b09dbbcf8e49bb1c9be19b215577167458b969bb40634f71dba00bdfdd12f1c878effd9e08475b8301a214bc7dfc95c2f341aa8fbd985a5da05af046336c23cf356570772530017c9a8bb96140977698d50c3258e8d31c040bb887c56d3d6e583db7a4ff2ea28aa93885312dfa50bf86a15618288b2c2701e6d75743fec9f3ca35b7e20ad902ad6985fe0b3c389b9582b3c62d9bea90230d1512a07c66a5404bf804693b6bb677a4ff038ae4a762f89f6a877d7621f7461431a7d4cadaf1687057ca4a9d157195acafe73f5eed77b314dd640999ee20de461600ce3d3620cef84abc256774a514db5b65721cd93d1601e0fa8f53630dbe8567493018588e9619783e1526eb9bc56cc7b37c99025a9bdc10465bfb01605232292e50ac3b56b2ffefe48f0615651649d1db4ebff57d955e434f0c564b2a6842d3af04be1bfc5e968abe390f15bc89b9a4ed7a00b82beea07cf8e03c82bdd6a40b6c6334e51a432024caf9247db25058eb0cbce567ed49c56730058480e5854f3888e988053c403045239098ba6977aa0adb7f6dec785d31bacee8276a87d7a8f2114bb6662a117e3e37846c5b713e599801fbae5185cf21360760721376efe0736b7f4fa049d0c9f3086324be3a0f44d6cae5450d87d79a7bcaa0a2aa259b738ed85a59fead48d985597f6d77022ecdf37685df4182267d4fbdb24747f208a9e1b3126251b320066d8499ab5298395dab0340a78325b39d383d34a31a27f223114a9774498a314e3ba3cf4b87150e1f959f29556e67ae136a6290922e8cd3890c3b93bb68f38990ac3a4700cbe075795f7603755a28f3226e31c29a2eab2bff2423dc6177a6d8eaa950fbe2320b9bee89b8bbc3149b7ee177224e59726f28bcb796ccb09ac6b3feb3256ca033eb177aeea997be798f0e1b63b284dc8361ff870de717263cb86838a0c6cd5a82e12d162bd04f9c85267d4abd3a6828639fd0584a023388cc220d404d4646d0318"
c3 := "010070061bde0fc57d38e0ce9c82c088f793a93a20f830ed94a5f7e01f5af0decccf0ee7f70a711dc78b69b40f7e411f7f6ff34a5de4ad32fa5dc9d09b09dbbcf8e49bb1c9be19b215577167458b969bb40634f71dba00bdfdd12f1c878effd9e08475b8301a214bc7dfc95c2f341aa8fbd985a5da05af046336c23cf356570772530017c9a8bb96140977698d50c3258e8d31c040bb887c56d3d6e583db7a4ff2ea28aa93885312dfa50bf86a15618288b2c2701e6d75743fec9f3ca35b7e20ad902ad6985fe0b3c389b9582b3c62d9bea90230d1512a07c66a5404bf804693b6bb677a4ff038ae4a762f89f6a877d7621f7461431a7d4cadaf1687057ca4a9d1571d74c0a358b73242b65cf84139071503ffa45c824d84cb0336510de9a1ad1a7c56142efa23f8b69b4094c940adb42df385fc11bf2704a2608b1a65c5d17f2a051114832ab141290c16201b59eae28639ece329eb5b8003b4f1025e57066115d7d378581268359e0ca94117451ca3aa6b0d597cf8f621b66bf20fc488b18848aa47e31d5939d59b8058def7df416f6734b3821bacd1fc8f4f1d422fc2c17c9bd903e80fabea7eb0f6237f771d0be65941cfca8ed6ec0e412bc940fc09cb0033abe4e668fee7f07a9cba77da04815747271eb32a5a9278ca0f57d7e05cffa6bdb5902984586259fab80be0460e9af3391f2a3212a1e4f350e060f988781e6ab2254e76c972e5611151fa501607d1d342667253d21e9ca113f2b87d823a55e70d4f5899e0ba8121477dded3d3b858438c4d0486a0c9846eb05b737a734ba37cdfdaaca8a4a38f2bd1c1ed0b4583b96c2fd2d1675991b4a151470811b4f4bfbad46ddbaa0e1fa28a81a3801e8c211137db822fb5a07344dc719b13e50562bd1e3a391a7747709db2445543f7412fd9c3011141d9ad4f05182593e6e75033764395fa8be80039cb47ed5d750f62836312e7b23152f69a65e41a9782d841b3c48719403e98bd8e72c824083275a29a53d681dc25b7df6c60cb0c4c74feab1d7b1edc76c09a1fe4da1acf9979d3c200233b082f66710725867ef6418e866cd93d26c7fd"
data, err := CiphertextAdd(c1, c2)
assert.Nil(t, err)
assert.Equal(t, c3, data)
}
...@@ -2,21 +2,254 @@ ...@@ -2,21 +2,254 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Package sm2 带证书交易的签名
package sm2 package sm2
import ( import (
"bytes"
"crypto/elliptic"
"errors"
"fmt"
"math/big"
"github.com/33cn/chain33/types"
pkt "github.com/33cn/plugin/plugin/dapp/cert/types"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/system/crypto/sm2" "github.com/tjfoc/gmsm/sm2"
)
//const
const (
SM2PrivateKeyLength = 32
SM2PublicKeyLength = 65
SM2PublicKeyCompressed = 33
) )
type sm2Driver struct { //Driver 驱动
sm2.Driver type Driver struct{}
//GenKey 生成私钥
func (d Driver) GenKey() (crypto.PrivKey, error) {
privKeyBytes := [SM2PrivateKeyLength]byte{}
copy(privKeyBytes[:], crypto.CRandBytes(SM2PrivateKeyLength))
priv, _ := privKeyFromBytes(sm2.P256Sm2(), privKeyBytes[:])
copy(privKeyBytes[:], SerializePrivateKey(priv))
return PrivKeySM2(privKeyBytes), nil
}
//PrivKeyFromBytes 字节转为私钥
func (d Driver) PrivKeyFromBytes(b []byte) (privKey crypto.PrivKey, err error) {
if len(b) != SM2PrivateKeyLength {
return nil, errors.New("invalid priv key byte")
}
privKeyBytes := new([SM2PrivateKeyLength]byte)
copy(privKeyBytes[:], b[:SM2PrivateKeyLength])
priv, _ := privKeyFromBytes(sm2.P256Sm2(), privKeyBytes[:])
copy(privKeyBytes[:], SerializePrivateKey(priv))
return PrivKeySM2(*privKeyBytes), nil
}
//PubKeyFromBytes 字节转为公钥
func (d Driver) PubKeyFromBytes(b []byte) (pubKey crypto.PubKey, err error) {
if len(b) != SM2PublicKeyLength && len(b) != SM2PublicKeyCompressed {
return nil, errors.New("invalid pub key byte")
}
pubKeyBytes := new([SM2PublicKeyLength]byte)
copy(pubKeyBytes[:], b[:])
return PubKeySM2(*pubKeyBytes), nil
}
//SignatureFromBytes 字节转为签名
func (d Driver) SignatureFromBytes(b []byte) (sig crypto.Signature, err error) {
var certSignature pkt.CertSignature
err = types.Decode(b, &certSignature)
if err != nil {
return SignatureSM2(b), nil
}
return &SignatureS{
Signature: SignatureSM2(certSignature.Signature),
uid: certSignature.Uid,
}, nil
}
//PrivKeySM2 私钥
type PrivKeySM2 [SM2PrivateKeyLength]byte
//Bytes 字节格式
func (privKey PrivKeySM2) Bytes() []byte {
s := make([]byte, SM2PrivateKeyLength)
copy(s, privKey[:])
return s
}
//Sign 签名
func (privKey PrivKeySM2) Sign(msg []byte) crypto.Signature {
priv, _ := privKeyFromBytes(sm2.P256Sm2(), privKey[:])
r, s, err := sm2.Sm2Sign(priv, msg, nil)
if err != nil {
return nil
}
//sm2不需要LowS转换
//s = ToLowS(pub, s)
return SignatureSM2(Serialize(r, s))
}
//PubKey 私钥生成公钥
func (privKey PrivKeySM2) PubKey() crypto.PubKey {
_, pub := privKeyFromBytes(sm2.P256Sm2(), privKey[:])
var pubSM2 PubKeySM2
copy(pubSM2[:], sm2.Compress(pub))
return pubSM2
}
//Equals 公钥
func (privKey PrivKeySM2) Equals(other crypto.PrivKey) bool {
if otherSecp, ok := other.(PrivKeySM2); ok {
return bytes.Equal(privKey[:], otherSecp[:])
}
return false
}
func (privKey PrivKeySM2) String() string {
return fmt.Sprintf("PrivKeySM2{*****}")
}
//PubKeySM2 公钥
type PubKeySM2 [SM2PublicKeyLength]byte
//Bytes 字节格式
func (pubKey PubKeySM2) Bytes() []byte {
length := SM2PublicKeyLength
if pubKey.isCompressed() {
length = SM2PublicKeyCompressed
}
s := make([]byte, length)
copy(s, pubKey[0:length])
return s
}
func (pubKey PubKeySM2) isCompressed() bool {
return pubKey[0] != pubkeyUncompressed
}
//VerifyBytes 验证字节
func (pubKey PubKeySM2) VerifyBytes(msg []byte, sig crypto.Signature) bool {
var uid []byte
if wrap, ok := sig.(*SignatureS); ok {
sig = wrap.Signature
uid = wrap.uid
}
sigSM2, ok := sig.(SignatureSM2)
if !ok {
fmt.Printf("convert failed\n")
return false
}
var pub *sm2.PublicKey
if pubKey.isCompressed() {
pub = sm2.Decompress(pubKey[0:SM2PublicKeyCompressed])
} else {
var err error
pub, err = parsePubKey(pubKey[:], sm2.P256Sm2())
if err != nil {
fmt.Printf("parse pubkey failed\n")
return false
}
}
r, s, err := Deserialize(sigSM2)
if err != nil {
fmt.Printf("unmarshal sign failed")
return false
}
//国密签名算法和ecdsa不一样,-s验签不通过,所以不需要LowS检查
//fmt.Printf("verify:%x, r:%d, s:%d\n", crypto.Sm3Hash(msg), r, s)
//lowS := IsLowS(s)
//if !lowS {
// fmt.Printf("lowS check failed")
// return false
//}
return sm2.Sm2Verify(pub, msg, uid, r, s)
}
func (pubKey PubKeySM2) String() string {
return fmt.Sprintf("PubKeySM2{%X}", pubKey[:])
}
//KeyString Must return the full bytes in hex.
// Used for map keying, etc.
func (pubKey PubKeySM2) KeyString() string {
return fmt.Sprintf("%X", pubKey[:])
}
//Equals 相等
func (pubKey PubKeySM2) Equals(other crypto.PubKey) bool {
if otherSecp, ok := other.(PubKeySM2); ok {
return bytes.Equal(pubKey[:], otherSecp[:])
}
return false
}
//SignatureSM2 签名
type SignatureSM2 []byte
//SignatureS 签名
type SignatureS struct {
crypto.Signature
uid []byte
}
//Bytes 字节格式
func (sig SignatureSM2) Bytes() []byte {
s := make([]byte, len(sig))
copy(s, sig[:])
return s
}
//IsZero 是否为0
func (sig SignatureSM2) IsZero() bool { return len(sig) == 0 }
func (sig SignatureSM2) String() string {
fingerprint := make([]byte, len(sig[:]))
copy(fingerprint, sig[:])
return fmt.Sprintf("/%X.../", fingerprint)
} }
const name = "auth_sm2" //Equals 相等
const id = 258 func (sig SignatureSM2) Equals(other crypto.Signature) bool {
if otherEd, ok := other.(SignatureSM2); ok {
return bytes.Equal(sig[:], otherEd[:])
}
return false
}
//const
const (
Name = "auth_sm2"
ID = 258
)
func init() { func init() {
crypto.Register(name, &sm2Driver{}, false) crypto.Register(Name, &Driver{}, false)
crypto.RegisterType(name, id) crypto.RegisterType(Name, ID)
}
func privKeyFromBytes(curve elliptic.Curve, pk []byte) (*sm2.PrivateKey, *sm2.PublicKey) {
x, y := curve.ScalarBaseMult(pk)
priv := &sm2.PrivateKey{
PublicKey: sm2.PublicKey{
Curve: curve,
X: x,
Y: y,
},
D: new(big.Int).SetBytes(pk),
}
return priv, &priv.PublicKey
} }
// Copyright Fuzamei Corp. 2018 All Rights Reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package sm2
import (
"crypto/elliptic"
"errors"
"fmt"
"math/big"
"github.com/btcsuite/btcd/btcec"
"github.com/tjfoc/gmsm/sm2"
)
const (
pubkeyUncompressed byte = 0x4 // x coord + y coord
)
func canonicalizeInt(val *big.Int) []byte {
b := val.Bytes()
if len(b) == 0 {
b = []byte{0x00}
}
if b[0]&0x80 != 0 {
paddedBytes := make([]byte, len(b)+1)
copy(paddedBytes[1:], b)
b = paddedBytes
}
return b
}
//Serialize 序列化
func Serialize(r, s *big.Int) []byte {
rb := canonicalizeInt(r)
sb := canonicalizeInt(s)
length := 6 + len(rb) + len(sb)
b := make([]byte, length)
b[0] = 0x30
b[1] = byte(length - 2)
b[2] = 0x02
b[3] = byte(len(rb))
offset := copy(b[4:], rb) + 4
b[offset] = 0x02
b[offset+1] = byte(len(sb))
copy(b[offset+2:], sb)
return b
}
//Deserialize 反序列化
func Deserialize(sigStr []byte) (*big.Int, *big.Int, error) {
sig, err := btcec.ParseDERSignature(sigStr, sm2.P256Sm2())
if err != nil {
return nil, nil, err
}
return sig.R, sig.S, nil
}
func parsePubKey(pubKeyStr []byte, curve elliptic.Curve) (key *sm2.PublicKey, err error) {
pubkey := sm2.PublicKey{}
pubkey.Curve = curve
if len(pubKeyStr) == 0 {
return nil, errors.New("pubkey string is empty")
}
pubkey.X = new(big.Int).SetBytes(pubKeyStr[1:33])
pubkey.Y = new(big.Int).SetBytes(pubKeyStr[33:])
if pubkey.X.Cmp(pubkey.Curve.Params().P) >= 0 {
return nil, fmt.Errorf("pubkey X parameter is >= to P")
}
if pubkey.Y.Cmp(pubkey.Curve.Params().P) >= 0 {
return nil, fmt.Errorf("pubkey Y parameter is >= to P")
}
if !pubkey.Curve.IsOnCurve(pubkey.X, pubkey.Y) {
return nil, fmt.Errorf("pubkey isn't on secp256k1 curve")
}
return &pubkey, nil
}
//SerializePublicKey 公钥序列化
func SerializePublicKey(p *sm2.PublicKey, isCompress bool) []byte {
if isCompress {
return sm2.Compress(p)
}
b := make([]byte, 0, SM2PublicKeyLength)
b = append(b, pubkeyUncompressed)
b = paddedAppend(32, b, p.X.Bytes())
return paddedAppend(32, b, p.Y.Bytes())
}
//SerializePrivateKey 私钥序列化
func SerializePrivateKey(p *sm2.PrivateKey) []byte {
b := make([]byte, 0, SM2PrivateKeyLength)
return paddedAppend(SM2PrivateKeyLength, b, p.D.Bytes())
}
func paddedAppend(size uint, dst, src []byte) []byte {
for i := 0; i < int(size)-len(src); i++ {
dst = append(dst, 0)
}
return append(dst, src...)
}
...@@ -265,6 +265,12 @@ func (auth *Authority) Validate(signature *types.Signature) error { ...@@ -265,6 +265,12 @@ func (auth *Authority) Validate(signature *types.Signature) error {
return nil return nil
} }
// GetSnFromSig 解析证书序列号
func (auth *Authority) GetSnFromByte(signature *types.Signature) ([]byte, error) {
return auth.validator.GetCertSnFromSignature(signature.Signature)
}
// ToHistoryCertStore 历史数据转成store可存储的历史数据 // ToHistoryCertStore 历史数据转成store可存储的历史数据
func (certdata *HistoryCertData) ToHistoryCertStore(store *types.HistoryCertStore) { func (certdata *HistoryCertData) ToHistoryCertStore(store *types.HistoryCertStore) {
if store == nil { if store == nil {
......
...@@ -59,7 +59,7 @@ var SIGNTYPE = ct.AuthSM2 ...@@ -59,7 +59,7 @@ var SIGNTYPE = ct.AuthSM2
func signtx(tx *types.Transaction, priv crypto.PrivKey, cert []byte) { func signtx(tx *types.Transaction, priv crypto.PrivKey, cert []byte) {
tx.Sign(int32(SIGNTYPE), priv) tx.Sign(int32(SIGNTYPE), priv)
tx.Signature.Signature, _ = utils.EncodeCertToSignature(tx.Signature.Signature, cert) tx.Signature.Signature = utils.EncodeCertToSignature(tx.Signature.Signature, cert, nil)
} }
func signtxs(priv crypto.PrivKey, cert []byte) { func signtxs(priv crypto.PrivKey, cert []byte) {
......
...@@ -162,7 +162,7 @@ func (validator *ecdsaValidator) Validate(certByte []byte, pubKey []byte) error ...@@ -162,7 +162,7 @@ func (validator *ecdsaValidator) Validate(certByte []byte, pubKey []byte) error
return fmt.Errorf("Could not obtain certification chain, err %s", err) return fmt.Errorf("Could not obtain certification chain, err %s", err)
} }
err = validator.validateCertAgainstChain(cert, validationChain) err = validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
if err != nil { if err != nil {
return fmt.Errorf("Could not validate identity against certification chain, err %s", err) return fmt.Errorf("Could not validate identity against certification chain, err %s", err)
} }
...@@ -360,10 +360,10 @@ func (validator *ecdsaValidator) validateCAIdentity(cert *x509.Certificate) erro ...@@ -360,10 +360,10 @@ func (validator *ecdsaValidator) validateCAIdentity(cert *x509.Certificate) erro
return nil return nil
} }
return validator.validateCertAgainstChain(cert, validationChain) return validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
} }
func (validator *ecdsaValidator) validateCertAgainstChain(cert *x509.Certificate, validationChain []*x509.Certificate) error { func (validator *ecdsaValidator) validateCertAgainstChain(serialNumber *big.Int, validationChain []*x509.Certificate) error {
SKI, err := getSubjectKeyIdentifierFromCert(validationChain[1]) SKI, err := getSubjectKeyIdentifierFromCert(validationChain[1])
if err != nil { if err != nil {
return fmt.Errorf("Could not obtain Subject Key Identifier for signer cert, err %s", err) return fmt.Errorf("Could not obtain Subject Key Identifier for signer cert, err %s", err)
...@@ -377,7 +377,7 @@ func (validator *ecdsaValidator) validateCertAgainstChain(cert *x509.Certificate ...@@ -377,7 +377,7 @@ func (validator *ecdsaValidator) validateCertAgainstChain(cert *x509.Certificate
if bytes.Equal(aki, SKI) { if bytes.Equal(aki, SKI) {
for _, rc := range crl.TBSCertList.RevokedCertificates { for _, rc := range crl.TBSCertList.RevokedCertificates {
if rc.SerialNumber.Cmp(cert.SerialNumber) == 0 { if rc.SerialNumber.Cmp(serialNumber) == 0 {
err = validationChain[1].CheckCRLSignature(crl) err = validationChain[1].CheckCRLSignature(crl)
if err != nil { if err != nil {
authLogger.Warn("Invalid signature over the identified CRL, error %s", err) authLogger.Warn("Invalid signature over the identified CRL, error %s", err)
...@@ -405,16 +405,31 @@ func (validator *ecdsaValidator) getValidityOptsForCert(cert *x509.Certificate) ...@@ -405,16 +405,31 @@ func (validator *ecdsaValidator) getValidityOptsForCert(cert *x509.Certificate)
} }
func (validator *ecdsaValidator) GetCertFromSignature(signature []byte) ([]byte, error) { func (validator *ecdsaValidator) GetCertFromSignature(signature []byte) ([]byte, error) {
cert, _, err := utils.DecodeCertFromSignature(signature) certSign, err := utils.DecodeCertFromSignature(signature)
if err != nil { if err != nil {
authLogger.Error(fmt.Sprintf("unmashal certificate from signature failed. %s", err.Error())) authLogger.Error(fmt.Sprintf("unmashal certificate from signature failed. %s", err.Error()))
return nil, err return nil, err
} }
if len(cert) == 0 { if len(certSign.Cert) == 0 {
authLogger.Error("cert can not be null") authLogger.Error("cert can not be null")
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
return cert, nil return certSign.Cert, nil
}
func (validator *ecdsaValidator) GetCertSnFromSignature(signature []byte) ([]byte, error) {
certByte, err := validator.GetCertFromSignature(signature)
if err != nil {
authLogger.Error(fmt.Sprintf("GetCertSnFromSignature from signature failed. %s", err.Error()))
return nil, err
}
cert, err := validator.getCertFromPem(certByte)
if err != nil {
return nil, fmt.Errorf("ParseCertificate failed %s", err)
}
return cert.SerialNumber.Bytes(), nil
} }
...@@ -12,6 +12,7 @@ import ( ...@@ -12,6 +12,7 @@ import (
"encoding/pem" "encoding/pem"
"errors" "errors"
"fmt" "fmt"
"math/big"
"reflect" "reflect"
"time" "time"
...@@ -100,7 +101,7 @@ func (validator *gmValidator) Validate(certByte []byte, pubKey []byte) error { ...@@ -100,7 +101,7 @@ func (validator *gmValidator) Validate(certByte []byte, pubKey []byte) error {
return fmt.Errorf("Could not obtain certification chain, err %s", err) return fmt.Errorf("Could not obtain certification chain, err %s", err)
} }
err = validator.validateCertAgainstChain(cert, validationChain) err = validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
if err != nil { if err != nil {
return fmt.Errorf("Could not validate identity against certification chain, err %s", err) return fmt.Errorf("Could not validate identity against certification chain, err %s", err)
} }
...@@ -292,10 +293,10 @@ func (validator *gmValidator) validateCAIdentity(cert *sm2.Certificate) error { ...@@ -292,10 +293,10 @@ func (validator *gmValidator) validateCAIdentity(cert *sm2.Certificate) error {
return nil return nil
} }
return validator.validateCertAgainstChain(cert, validationChain) return validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
} }
func (validator *gmValidator) validateCertAgainstChain(cert *sm2.Certificate, validationChain []*sm2.Certificate) error { func (validator *gmValidator) validateCertAgainstChain(serialNumber *big.Int, validationChain []*sm2.Certificate) error {
SKI, err := getSubjectKeyIdentifierFromSm2Cert(validationChain[1]) SKI, err := getSubjectKeyIdentifierFromSm2Cert(validationChain[1])
if err != nil { if err != nil {
return fmt.Errorf("Could not obtain Subject Key Identifier for signer cert, err %s", err) return fmt.Errorf("Could not obtain Subject Key Identifier for signer cert, err %s", err)
...@@ -309,7 +310,7 @@ func (validator *gmValidator) validateCertAgainstChain(cert *sm2.Certificate, va ...@@ -309,7 +310,7 @@ func (validator *gmValidator) validateCertAgainstChain(cert *sm2.Certificate, va
if bytes.Equal(aki, SKI) { if bytes.Equal(aki, SKI) {
for _, rc := range crl.TBSCertList.RevokedCertificates { for _, rc := range crl.TBSCertList.RevokedCertificates {
if rc.SerialNumber.Cmp(cert.SerialNumber) == 0 { if rc.SerialNumber.Cmp(serialNumber) == 0 {
err = validationChain[1].CheckCRLSignature(crl) err = validationChain[1].CheckCRLSignature(crl)
if err != nil { if err != nil {
authLogger.Warn(fmt.Sprintf("Invalid signature over the identified CRL, error %s", err)) authLogger.Warn(fmt.Sprintf("Invalid signature over the identified CRL, error %s", err))
...@@ -339,16 +340,31 @@ func (validator *gmValidator) getValidityOptsForCert(cert *sm2.Certificate) sm2. ...@@ -339,16 +340,31 @@ func (validator *gmValidator) getValidityOptsForCert(cert *sm2.Certificate) sm2.
func (validator *gmValidator) GetCertFromSignature(signature []byte) ([]byte, error) { func (validator *gmValidator) GetCertFromSignature(signature []byte) ([]byte, error) {
// 从proto中解码signature // 从proto中解码signature
cert, _, err := utils.DecodeCertFromSignature(signature) cert, err := utils.DecodeCertFromSignature(signature)
if err != nil { if err != nil {
authLogger.Error(fmt.Sprintf("unmashal certificate from signature failed. %s", err.Error())) authLogger.Error(fmt.Sprintf("unmashal certificate from signature failed. %s", err.Error()))
return nil, err return nil, err
} }
if len(cert) == 0 { if len(cert.Cert) == 0 {
authLogger.Error("cert can not be null") authLogger.Error("cert can not be null")
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
return cert, nil return cert.Cert, nil
}
func (validator *gmValidator) GetCertSnFromSignature(signature []byte) ([]byte, error) {
certByte, err := validator.GetCertFromSignature(signature)
if err != nil {
authLogger.Error(fmt.Sprintf("GetCertSnFromSignature from signature failed. %s", err.Error()))
return nil, err
}
cert, err := validator.getCertFromPem(certByte)
if err != nil {
return nil, fmt.Errorf("ParseCertificate failed %s", err)
}
return cert.SerialNumber.Bytes(), nil
} }
...@@ -23,3 +23,7 @@ func (validator *noneValidator) Validate(certByte []byte, pubKey []byte) error { ...@@ -23,3 +23,7 @@ func (validator *noneValidator) Validate(certByte []byte, pubKey []byte) error {
func (validator *noneValidator) GetCertFromSignature(signature []byte) ([]byte, error) { func (validator *noneValidator) GetCertFromSignature(signature []byte) ([]byte, error) {
return []byte(""), nil return []byte(""), nil
} }
func (validator *noneValidator) GetCertSnFromSignature(signature []byte) ([]byte, error) {
return []byte(""), nil
}
...@@ -11,6 +11,8 @@ type Validator interface { ...@@ -11,6 +11,8 @@ type Validator interface {
Validate(cert []byte, pubKey []byte) error Validate(cert []byte, pubKey []byte) error
GetCertFromSignature(signature []byte) ([]byte, error) GetCertFromSignature(signature []byte) ([]byte, error)
GetCertSnFromSignature(signature []byte) ([]byte, error)
} }
// AuthConfig 校验器配置 // AuthConfig 校验器配置
......
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIB6zCCAZGgAwIBAgIQVq9SxucwdINw2WUMlNFpdjAKBggqgRzPVQGDdTBHMQsw MIIB7DCCAZGgAwIBAgIQETH0EMzvdWOEEg3FoAe/iDAKBggqgRzPVQGDdTBHMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwNjE4MDMxNDQ2WhcNMzAwNjE2MDMx YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwODE0MDkyNTIwWhcNMzAwODEyMDky
NDQ2WjBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE NTIwWjBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzELMAkGA1UEAxMCY2EwWTATBgcqhkjOPQIBBggqgRzP BxMNU2FuIEZyYW5jaXNjbzELMAkGA1UEAxMCY2EwWTATBgcqhkjOPQIBBggqgRzP
VQGCLQNCAARACzXYM8dLleVhjAwyljePO1Vltf2YL2xGKCLAB1/YITkM4q3GVE8D VQGCLQNCAAQlKmH6RVHN/nBE4qR+uF7lHmlc62jQA4kpoAwtJFRiFbczZx/KNDaD
LZxsydaG0zncKUswQA97HM6F1qarbFuvo18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYD 9+USLAo9ecxcdOKR4lIcuT7jvKX6tXQ7o18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYD
VR0lBAgwBgYEVR0lADAPBgNVHRMBAf8EBTADAQH/MCkGA1UdDgQiBCDpAuHxKpzW VR0lBAgwBgYEVR0lADAPBgNVHRMBAf8EBTADAQH/MCkGA1UdDgQiBCC8fKlLiayf
gxCIZxodcdzpHpzKFhlEJARmhKOPuN1yaTAKBggqgRzPVQGDdQNIADBFAiEAowXR +80blLEiRIzTyY7uYDUpP5K2RtOmfY0NKjAKBggqgRzPVQGDdQNJADBGAiEA8vh+
RYYCWcBT0gVSbHk7k+aJzG3uRdORTbbvmLgbG2QCIF3e0/m0aNRlvF6gPxBJ+JBR 3joELxPxq0n1h07XFGeEnmpxutVoIocuky2HkF4CIQDnWIavlpJOq3tU76cmn3ur
R0sbv9eyrSEFMwx/ZyGJ KQeyi9GM7Uoi25S1QIxu9A==
-----END CERTIFICATE----- -----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg86AAL0bRgFW6RhFX
no7CVphI1U2csfrjwPuYn3FXaF2gCgYIKoEcz1UBgi2hRANCAASR8Yb//+y/GMLy
D36FLLO80oxUPtD6AtVoh9UIuC1b0QzA4+zkUDUk3zwdZ1pMZZKGZ48vE6KtAcFB
uqU7L784
-----END PRIVATE KEY-----
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg4Ork9oT6d6CRxg0f
EbHlr5eQPUcHWniEgRhDCi2dA/GgCgYIKoEcz1UBgi2hRANCAAQqXuEWh+sW/YtP
FlHmxiFhYi0o3Tb8He9NAaJ6uKe+OF5/eXa+VmRrKKGeE+dG8LrMiJ5+AlIj+ryd
blX5UKZ8
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIB4zCCAYmgAwIBAgIQdKBE3pdDBMaadMbZ30K7aTAKBggqgRzPVQGDdTBHMQsw MIIB4zCCAYmgAwIBAgIQVs0txvOG+iVu/oISaV2KyzAKBggqgRzPVQGDdTBHMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwNjE4MDMxNDQ2WhcNMzAwNjE2MDMx YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwODE0MDkyNTIwWhcNMzAwODEyMDky
NDQ2WjBRMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE NTIwWjBRMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEAwwMVXNlckBDaGFpbjMzMFkwEwYHKoZI BxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEAwwMVXNlckBDaGFpbjMzMFkwEwYHKoZI
zj0CAQYIKoEcz1UBgi0DQgAEkfGG///svxjC8g9+hSyzvNKMVD7Q+gLVaIfVCLgt zj0CAQYIKoEcz1UBgi0DQgAEKl7hFofrFv2LTxZR5sYhYWItKN02/B3vTQGierin
W9EMwOPs5FA1JN88HWdaTGWShmePLxOirQHBQbqlOy+/OKNNMEswDgYDVR0PAQH/ vjhef3l2vlZkayihnhPnRvC6zIiefgJSI/q8nW5V+VCmfKNNMEswDgYDVR0PAQH/
BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAg6QLh8Sqc1oMQiGcaHXHc BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgvHypS4msn/vNG5SxIkSM
6R6cyhYZRCQEZoSjj7jdcmkwCgYIKoEcz1UBg3UDSAAwRQIgBSqSzSkoXopLR830 08mO7mA1KT+StkbTpn2NDSowCgYIKoEcz1UBg3UDSAAwRQIhAND6HO/EN/dTeokX
zMjWsMVlZERtUuW3+uYm+bCRjOgCIQDZf8dKxkBd155hiilDQ4RR4Xa8+ZGcPslm mIvczQBcxPHTAq3+QIa2NHIC8bYvAiAZ5N4C4rwRJCqTw8J6As69MFO10XixWHxH
Nm+S1txiqA== qrTJ9LnI3g==
-----END CERTIFICATE----- -----END CERTIFICATE-----
...@@ -13,11 +13,10 @@ import ( ...@@ -13,11 +13,10 @@ import (
"encoding/pem" "encoding/pem"
"math/big" "math/big"
"encoding/asn1" "github.com/33cn/chain33/types"
"fmt" "fmt"
"github.com/33cn/chain33/common/crypto"
sm2_util "github.com/33cn/chain33/system/crypto/sm2" sm2_util "github.com/33cn/chain33/system/crypto/sm2"
ecdsa_util "github.com/33cn/plugin/plugin/crypto/ecdsa" ecdsa_util "github.com/33cn/plugin/plugin/crypto/ecdsa"
ty "github.com/33cn/plugin/plugin/dapp/cert/types" ty "github.com/33cn/plugin/plugin/dapp/cert/types"
...@@ -65,22 +64,23 @@ func GetPublicKeySKIFromCert(cert []byte, signType int) (string, error) { ...@@ -65,22 +64,23 @@ func GetPublicKeySKIFromCert(cert []byte, signType int) (string, error) {
} }
// EncodeCertToSignature 证书编码进签名 // EncodeCertToSignature 证书编码进签名
func EncodeCertToSignature(signByte []byte, cert []byte) ([]byte, error) { func EncodeCertToSignature(signByte []byte, cert []byte, uid []byte) []byte {
certSign := crypto.CertSignature{} var certSign ty.CertSignature
certSign.Signature = append(certSign.Signature, signByte...) certSign.Signature = append(certSign.Signature, signByte...)
certSign.Cert = append(certSign.Cert, cert...) certSign.Cert = append(certSign.Cert, cert...)
return asn1.Marshal(certSign) certSign.Uid = append(certSign.Uid, uid...)
return types.Encode(&certSign)
} }
// DecodeCertFromSignature 从签名中解码证书 // DecodeCertFromSignature 从签名中解码证书
func DecodeCertFromSignature(signByte []byte) ([]byte, []byte, error) { func DecodeCertFromSignature(signByte []byte) (*ty.CertSignature, error) {
var certSignature crypto.CertSignature var certSign ty.CertSignature
_, err := asn1.Unmarshal(signByte, &certSignature) err := types.Decode(signByte, &certSign)
if err != nil { if err != nil {
return nil, nil, err return nil, err
} }
return certSignature.Cert, certSignature.Signature, nil return &certSign, nil
} }
// PrivKeyByteFromRaw pem结构转成byte类型私钥 // PrivKeyByteFromRaw pem结构转成byte类型私钥
......
...@@ -51,6 +51,7 @@ func newCert() drivers.Driver { ...@@ -51,6 +51,7 @@ func newCert() drivers.Driver {
c := &Cert{} c := &Cert{}
c.SetChild(c) c.SetChild(c)
c.SetIsFree(true) c.SetIsFree(true)
c.SetExecutorType(types.LoadExecutorType(driverName))
return c return c
} }
......
package executor
import (
"fmt"
"testing"
"time"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client"
apimock "github.com/33cn/chain33/client/mocks"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto"
dbm "github.com/33cn/chain33/common/db"
_ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/system/dapp"
pty "github.com/33cn/chain33/system/dapp/manage/types"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
_ "github.com/33cn/plugin/plugin/crypto/init"
"github.com/33cn/plugin/plugin/dapp/cert/authority"
"github.com/33cn/plugin/plugin/dapp/cert/authority/utils"
ct "github.com/33cn/plugin/plugin/dapp/cert/types"
pkt "github.com/33cn/plugin/plugin/dapp/collateralize/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
type execEnv struct {
blockTime int64
blockHeight int64
difficulty uint64
kvdb dbm.KVDB
api client.QueueProtocolAPI
db dbm.KV
execAddr string
cfg *types.Chain33Config
ldb dbm.DB
user *authority.User
}
var (
PrivKeyA = "0x6da92a632ab7deb67d38c0f6560bcfed28167998f6496db64c258d5e8393a81b" // 1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4
Nodes = [][]byte{
[]byte("1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"),
}
total = 100 * types.Coin
USERNAME = "User"
SIGNTYPE = ct.AuthSM2
transfer1 = &ct.CertAction{Value: &ct.CertAction_Normal{Normal: &ct.CertNormal{Key: "", Value: nil}}, Ty: ct.CertActionNormal}
tx1 = &types.Transaction{Execer: []byte("cert"), Payload: types.Encode(transfer1), Fee: 100000000, Expire: 0, To: dapp.ExecAddress("cert")}
transfer2 = &ct.CertAction{Value: &ct.CertAction_New{New: &ct.CertNew{Key: "", Value: nil}}, Ty: ct.CertActionNew}
tx2 = &types.Transaction{Execer: []byte("cert"), Payload: types.Encode(transfer2), Fee: 100000000, Expire: 0, To: dapp.ExecAddress("cert")}
transfer3 = &ct.CertAction{Value: &ct.CertAction_Update{Update: &ct.CertUpdate{Key: "", Value: nil}}, Ty: ct.CertActionUpdate}
tx3 = &types.Transaction{Execer: []byte("cert"), Payload: types.Encode(transfer3), Fee: 100000000, Expire: 0, To: dapp.ExecAddress("cert")}
)
func manageKeySet(key string, value string, db dbm.KV) {
var item types.ConfigItem
item.Key = key
item.Addr = value
item.Ty = pty.ConfigItemArrayConfig
emptyValue := &types.ArrayConfig{Value: make([]string, 0)}
arr := types.ConfigItem_Arr{Arr: emptyValue}
item.Value = &arr
item.GetArr().Value = append(item.GetArr().Value, value)
manageKey := types.ManageKey(key)
valueSave := types.Encode(&item)
db.Set([]byte(manageKey), valueSave)
}
func initEnv() (*execEnv, error) {
cfg := types.NewChain33Config(types.ReadFile("./test/chain33.toml"))
cfg.SetTitleOnlyForTest("chain33")
sub := cfg.GetSubConfig()
var subcfg ct.Authority
if sub.Exec["cert"] != nil {
types.MustDecode(sub.Exec["cert"], &subcfg)
}
Init(ct.CertX, cfg, sub.Exec["cert"])
userLoader := &authority.UserLoader{}
err := userLoader.Init(subcfg.CryptoPath, subcfg.SignType)
if err != nil {
fmt.Printf("Init user loader falied -> %v", err)
return nil, err
}
user, err := userLoader.Get(USERNAME)
if err != nil {
fmt.Printf("Get user failed")
return nil, err
}
_, ldb, kvdb := util.CreateTestDB()
accountA := types.Account{
Balance: total,
Frozen: 0,
Addr: string(Nodes[0]),
}
api := new(apimock.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(cfg, nil)
execAddr := dapp.ExecAddress(ct.CertX)
stateDB, _ := dbm.NewGoMemDB("1", "2", 100)
accA := account.NewCoinsAccount(cfg)
accA.SetDB(stateDB)
accA.SaveExecAccount(execAddr, &accountA)
manageKeySet(ct.AdminKey, accountA.Addr, stateDB)
return &execEnv{
blockTime: time.Now().Unix(),
blockHeight: cfg.GetDappFork(ct.CertX, "Enable"),
difficulty: 1539918074,
kvdb: kvdb,
api: api,
db: stateDB,
execAddr: execAddr,
cfg: cfg,
ldb: ldb,
user: user,
}, nil
}
func signCertTx(tx *types.Transaction, priv crypto.PrivKey, cert []byte) {
tx.Sign(int32(SIGNTYPE), priv)
tx.Signature.Signature = utils.EncodeCertToSignature(tx.Signature.Signature, cert, nil)
}
func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) {
signType := types.SECP256K1
c, err := crypto.New(types.GetSignName(pkt.CollateralizeX, signType))
if err != nil {
return tx, err
}
bytes, err := common.FromHex(hexPrivKey[:])
if err != nil {
return tx, err
}
privKey, err := c.PrivKeyFromBytes(bytes)
if err != nil {
return tx, err
}
tx.Sign(int32(signType), privKey)
return tx, nil
}
func TestCert(t *testing.T) {
env, err := initEnv()
if err != nil {
panic(err)
}
signCertTx(tx1, env.user.Key, env.user.Cert)
// tx1
exec := newCert()
exec.SetAPI(env.api)
exec.SetStateDB(env.db)
assert.Equal(t, exec.GetCoinsAccount().LoadExecAccount(string(Nodes[0]), env.execAddr).GetBalance(), total)
exec.SetLocalDB(env.kvdb)
exec.SetEnv(env.blockHeight, env.blockTime, env.difficulty)
exec.SetEnv(env.blockHeight+1, env.blockTime+1, env.difficulty)
receipt, err := exec.Exec(tx1, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
t.Log(receipt)
for _, kv := range receipt.KV {
env.db.Set(kv.Key, kv.Value)
}
receiptData := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err := exec.ExecLocal(tx1, receiptData, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
util.SaveKVList(env.ldb, set.KV)
addr := address.PubKeyToAddr(env.user.Key.PubKey().Bytes())
res, err := exec.Query("CertValidSNByAddr", types.Encode(&ct.ReqQueryValidCertSN{Addr: addr}))
assert.Nil(t, err)
assert.NotNil(t, res)
// tx2
signTx(tx2, PrivKeyA)
exec.SetEnv(env.blockHeight+1, env.blockTime+1, env.difficulty)
receipt, err = exec.Exec(tx2, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
t.Log(receipt)
for _, kv := range receipt.KV {
env.db.Set(kv.Key, kv.Value)
}
receiptData = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(tx2, receiptData, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
util.SaveKVList(env.ldb, set.KV)
// tx3
signTx(tx3, PrivKeyA)
exec.SetEnv(env.blockHeight+1, env.blockTime+1, env.difficulty)
receipt, err = exec.Exec(tx3, int(1))
assert.Nil(t, err)
assert.NotNil(t, receipt)
t.Log(receipt)
for _, kv := range receipt.KV {
env.db.Set(kv.Key, kv.Value)
}
receiptData = &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err = exec.ExecLocal(tx3, receiptData, int(1))
assert.Nil(t, err)
assert.NotNil(t, set)
util.SaveKVList(env.ldb, set.KV)
}
package executor
import (
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/cert/authority"
ct "github.com/33cn/plugin/plugin/dapp/cert/types"
)
func CertUserStoreKey(addr string) (key []byte) {
key = append(key, []byte("mavl-"+ct.CertX+"-"+addr)...)
return key
}
func isAdminAddr(addr string, db dbm.KV) bool {
manageKey := types.ManageKey(ct.AdminKey)
data, err := db.Get([]byte(manageKey))
if err != nil {
clog.Error("getSuperAddr", "error", err)
return false
}
var item types.ConfigItem
err = types.Decode(data, &item)
if err != nil {
clog.Error("isSuperAddr", "Decode", data)
return false
}
for _, op := range item.GetArr().Value {
if op == addr {
return true
}
}
return false
}
func (c *Cert) Exec_New(payload *ct.CertNew, tx *types.Transaction, index int) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kv []*types.KeyValue
var receipt *types.Receipt
if !isAdminAddr(tx.From(), c.GetStateDB()) {
clog.Error("Exec_New", "error", "Exec_New need admin address")
return nil, ct.ErrPermissionDeny
}
receipt = &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}
return receipt, nil
}
func (c *Cert) Exec_Update(payload *ct.CertUpdate, tx *types.Transaction, index int) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kv []*types.KeyValue
var receipt *types.Receipt
if !isAdminAddr(tx.From(), c.GetStateDB()) {
clog.Error("Exec_Update", "error", "Exec_Update need admin address")
return nil, ct.ErrPermissionDeny
}
receipt = &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}
return receipt, nil
}
func (c *Cert) Exec_Normal(payload *ct.CertNormal, tx *types.Transaction, index int) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kv []*types.KeyValue
var receipt *types.Receipt
// 从proto中解码signature
sn, err := authority.Author.GetSnFromByte(tx.Signature)
if err != nil {
clog.Error("Exec_Normal get sn from signature failed", "error", err)
return nil, err
}
storekv := &types.KeyValue{Key: CertUserStoreKey(tx.From()), Value: sn}
c.GetStateDB().Set(storekv.Key, storekv.Value)
kv = append(kv, storekv)
receipt = &types.Receipt{Ty: types.ExecOk, KV: kv, Logs: logs}
return receipt, nil
}
func (c *Cert) Query_CertValidSNByAddr(req *ct.ReqQueryValidCertSN) (types.Message, error) {
sn, err := c.GetStateDB().Get(CertUserStoreKey(req.Addr))
if err != nil {
clog.Error("Query_CertValidSNByAddr", "error", err)
return nil, err
}
return &ct.RepQueryValidCertSN{Sn: sn}, nil
}
-----BEGIN CERTIFICATE-----
MIIB7DCCAZGgAwIBAgIQETH0EMzvdWOEEg3FoAe/iDAKBggqgRzPVQGDdTBHMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwODE0MDkyNTIwWhcNMzAwODEyMDky
NTIwWjBHMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzELMAkGA1UEAxMCY2EwWTATBgcqhkjOPQIBBggqgRzP
VQGCLQNCAAQlKmH6RVHN/nBE4qR+uF7lHmlc62jQA4kpoAwtJFRiFbczZx/KNDaD
9+USLAo9ecxcdOKR4lIcuT7jvKX6tXQ7o18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYD
VR0lBAgwBgYEVR0lADAPBgNVHRMBAf8EBTADAQH/MCkGA1UdDgQiBCC8fKlLiayf
+80blLEiRIzTyY7uYDUpP5K2RtOmfY0NKjAKBggqgRzPVQGDdQNJADBGAiEA8vh+
3joELxPxq0n1h07XFGeEnmpxutVoIocuky2HkF4CIQDnWIavlpJOq3tU76cmn3ur
KQeyi9GM7Uoi25S1QIxu9A==
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQg4Ork9oT6d6CRxg0f
EbHlr5eQPUcHWniEgRhDCi2dA/GgCgYIKoEcz1UBgi2hRANCAAQqXuEWh+sW/YtP
FlHmxiFhYi0o3Tb8He9NAaJ6uKe+OF5/eXa+VmRrKKGeE+dG8LrMiJ5+AlIj+ryd
blX5UKZ8
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIB4zCCAYmgAwIBAgIQVs0txvOG+iVu/oISaV2KyzAKBggqgRzPVQGDdTBHMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzELMAkGA1UEAxMCY2EwHhcNMjAwODE0MDkyNTIwWhcNMzAwODEyMDky
NTIwWjBRMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UE
BxMNU2FuIEZyYW5jaXNjbzEVMBMGA1UEAwwMVXNlckBDaGFpbjMzMFkwEwYHKoZI
zj0CAQYIKoEcz1UBgi0DQgAEKl7hFofrFv2LTxZR5sYhYWItKN02/B3vTQGierin
vjhef3l2vlZkayihnhPnRvC6zIiefgJSI/q8nW5V+VCmfKNNMEswDgYDVR0PAQH/
BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgvHypS4msn/vNG5SxIkSM
08mO7mA1KT+StkbTpn2NDSowCgYIKoEcz1UBg3UDSAAwRQIhAND6HO/EN/dTeokX
mIvczQBcxPHTAq3+QIa2NHIC8bYvAiAZ5N4C4rwRJCqTw8J6As69MFO10XixWHxH
qrTJ9LnI3g==
-----END CERTIFICATE-----
Title="chain33"
TestNet=true
FixTime=false
version="6.3.0"
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
loglevel = "debug"
logConsoleLevel = "info"
# 日志文件名,可带目录,所有生成的日志文件都放到此目录下
logFile = "logs/chain33.log"
# 单个日志文件的最大值(单位:兆)
maxFileSize = 300
# 最多保存的历史日志文件个数
maxBackups = 100
# 最多保存的历史日志消息(单位:天)
maxAge = 28
# 日志文件名是否使用本地事件(否则使用UTC时间)
localTime = true
# 历史日志文件是否压缩(压缩格式为gz)
compress = true
# 是否打印调用源文件和行号
callerFile = false
# 是否打印调用方法
callerFunction = false
[blockchain]
defCacheSize=128
maxFetchBlockNum=128
timeoutSeconds=5
batchBlockNum=128
driver="leveldb"
dbPath="datadir"
dbCache=64
isStrongConsistency=false
singleMode=true
batchsync=false
isRecordBlockSequence=true
isParaChain=false
enableTxQuickIndex=true
enableReExecLocal=true
[p2p]
# p2p类型
types=["dht", "gossip"]
# 是否启动P2P服务
enable=true
# 使用的数据库类型
driver="leveldb"
# 使用的数据库类型
dbPath="datadir/addrbook"
# 数据库缓存大小
dbCache=4
# GRPC请求日志文件
grpcLogFile="grpc33.log"
#waitPid 等待seed导入
waitPid=false
[p2p.sub.gossip]
seeds=[]
isSeed=false
serverStart=true
innerSeedEnable=true
useGithub=true
innerBounds=300
[p2p.sub.dht]
[rpc]
jrpcBindAddr="localhost:8801"
grpcBindAddr="localhost:8802"
whitelist=["127.0.0.1"]
jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"]
[mempool]
name="price"
poolCacheSize=10240
minTxFee=100000
maxTxNumPerAccount=100
maxTxFee=1000000000
isLevelFee=true
[mempool.sub.timeline]
poolCacheSize=10240
[mempool.sub.score]
poolCacheSize=10240
timeParam=1 #时间占价格比例
priceConstant=10 #手续费相对于时间的一个的常量,排队时手续费高1e3的分数~=快1h的分数
pricePower=1 #常量比例
[mempool.sub.price]
poolCacheSize=10240
[consensus]
name="solo"
minerstart=true
genesisBlockTime=1514533394
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
minerExecs=["ticket", "autonomy"]
[mver.consensus]
fundKeyAddr = "1BQXS6TxaYYG5mADaWij4AxhZZUTpw95a5"
powLimitBits="0x1f00ffff"
maxTxNumber = 1600 #160
[mver.consensus.ForkChainParamV1]
maxTxNumber = 1500
[mver.consensus.ForkTicketFundAddrV1]
fundKeyAddr = "1Ji3W12KGScCM7C2p8bg635sNkayDM8MGY"
[mver.consensus.ticket]
coinReward = 18
coinDevFund = 12
ticketPrice = 10000
retargetAdjustmentFactor = 4
futureBlockTime = 16
ticketFrozenTime = 5 #5s only for test
ticketWithdrawTime = 10 #10s only for test
ticketMinerWaitTime = 2 #2s only for test
targetTimespan=2304
targetTimePerBlock=16
[mver.consensus.ticket.ForkChainParamV1]
futureBlockTime = 15
ticketFrozenTime = 43200
ticketWithdrawTime = 172800
ticketMinerWaitTime = 7200
targetTimespan=2160
targetTimePerBlock=15
[mver.consensus.ticket.ForkChainParamV2]
coinReward = 5
coinDevFund = 3
targetTimespan=720
targetTimePerBlock=5
ticketPrice = 3000
[consensus.sub.ticket]
genesisBlockTime=1514533394
[[consensus.sub.ticket.genesis]]
minerAddr="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
returnAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
count=10000
[[consensus.sub.ticket.genesis]]
minerAddr="1PUiGcbsccfxW3zuvHXZBJfznziph5miAo"
returnAddr="1EbDHAXpoiewjPLX9uqoz38HsKqMXayZrF"
count=10000
[[consensus.sub.ticket.genesis]]
minerAddr="1EDnnePAZN48aC2hiTDzhkczfF39g1pZZX"
returnAddr="1KcCVZLSQYRUwE5EXTsAoQs9LuJW6xwfQa"
count=10000
[store]
name="kvmvccmavl"
driver="leveldb"
dbPath="datadir/mavltree"
dbCache=128
# store数据库版本
storedbVersion="2.0.0"
[store.sub.mavl]
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneHeight=10000
# 是否使能mavl数据载入内存
enableMemTree=true
# 是否使能mavl叶子节点数据载入内存
enableMemVal=true
# 缓存close ticket数目,该缓存越大同步速度越快,最大设置到1500000
tkCloseCacheLen=100000
[store.sub.kvmvccmavl]
enableMVCCIter=true
enableMavlPrefix=false
enableMVCC=false
enableMavlPrune=false
pruneMavlHeight=10000
enableMVCCPrune=false
pruneMVCCHeight=10000
# 是否使能mavl数据载入内存
enableMemTree=true
# 是否使能mavl叶子节点数据载入内存
enableMemVal=true
# 缓存close ticket数目,该缓存越大同步速度越快,最大设置到1500000
tkCloseCacheLen=100000
# 该参数针对平行链,主链无需开启此功能
enableEmptyBlockHandle=false
[wallet]
minFee=100000
driver="leveldb"
dbPath="wallet"
dbCache=16
signType="secp256k1"
[wallet.sub.ticket]
minerdisable=false
minerwhitelist=["*"]
[wallet.sub.multisig]
rescanMultisigAddr=false
[exec]
isFree=false
minExecFee=100000
maxExecFee=1000000000
enableStat=false
enableMVCC=false
alias=["token1:token","token2:token","token3:token"]
[exec.sub.token]
saveTokenTxList=true
tokenApprs = [
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK",
"1LY8GFia5EiyoTodMLfkB5PHNNpXRqxhyB",
"1GCzJDS6HbgTQ2emade7mEJGGWFfA15pS9",
"1JYB8sxi4He5pZWHCd3Zi2nypQ4JMB6AxN",
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
"16ui7XJ1VLM7YXcNhWwWsWS6CRC3ZA2sJ1",
]
[exec.sub.cert]
# 是否启用证书验证和签名
enable=true
# 加密文件路径
cryptoPath="test/authdir/crypto"
# 带证书签名类型,支持"auth_ecdsa", "auth_sm2"
signType="auth_sm2"
[exec.sub.relay]
genesis="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
[exec.sub.manage]
superManager=[
"1Bsg9j6gW83sShoee1fZAt9TkUjcrCgA9S",
"12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv",
"1Q8hGLfoGe63efeWa8fJ4Pnukhkngt6poK",
"16ui7XJ1VLM7YXcNhWwWsWS6CRC3ZA2sJ1",
]
[exec.sub.paracross]
nodeGroupFrozenCoins=0
#平行链共识停止后主链等待的高度
paraConsensusStopBlocks=30000
[exec.sub.autonomy]
total="16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp"
useBalance=false
#系统中所有的fork,默认用chain33的测试网络的
#但是我们可以替换
[fork.system]
ForkChainParamV1= 0
ForkCheckTxDup=0
ForkBlockHash= 1
ForkMinerTime= 0
ForkTransferExec=0
ForkExecKey=0
ForkTxGroup=0
ForkResetTx0=0
ForkWithdraw=0
ForkExecRollback=0
ForkCheckBlockTime=0
ForkTxHeight=0
ForkTxGroupPara=0
ForkChainParamV2=0
ForkMultiSignAddress=0
ForkStateDBSet=0
ForkLocalDBAccess=0
ForkBlockCheck=0
ForkBase58AddressCheck=0
#平行链上使能平行链执行器如user.p.x.coins执行器的注册,缺省为0,对已有的平行链需要设置一个fork高度
ForkEnableParaRegExec=0
ForkCacheDriver=0
ForkTicketFundAddrV1=-1 #fork6.3
#主链和平行链都使用同一个fork高度
ForkRootHash= 4500000
[fork.sub.cert]
Enable=0
[metrics]
#是否使能发送metrics数据的发送
enableMetrics=false
#数据保存模式
dataEmitMode="influxdb"
[metrics.sub.influxdb]
#以纳秒为单位的发送间隔
duration=1000000000
url="http://influxdb:8086"
database="chain33metrics"
username=""
password=""
namespace=""
\ No newline at end of file
...@@ -37,4 +37,18 @@ message Authority { ...@@ -37,4 +37,18 @@ message Authority {
bool enable = 1; bool enable = 1;
string cryptoPath = 2; string cryptoPath = 2;
string signType = 3; string signType = 3;
}
message CertSignature {
bytes signature = 1;
bytes cert = 2;
bytes uid = 3;
}
message ReqQueryValidCertSN {
string addr = 1;
}
message RepQueryValidCertSN {
bytes sn = 1;
} }
\ No newline at end of file
...@@ -383,6 +383,139 @@ func (m *Authority) GetSignType() string { ...@@ -383,6 +383,139 @@ func (m *Authority) GetSignType() string {
return "" return ""
} }
type CertSignature struct {
Signature []byte `protobuf:"bytes,1,opt,name=signature,proto3" json:"signature,omitempty"`
Cert []byte `protobuf:"bytes,2,opt,name=cert,proto3" json:"cert,omitempty"`
Uid []byte `protobuf:"bytes,3,opt,name=uid,proto3" json:"uid,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CertSignature) Reset() { *m = CertSignature{} }
func (m *CertSignature) String() string { return proto.CompactTextString(m) }
func (*CertSignature) ProtoMessage() {}
func (*CertSignature) Descriptor() ([]byte, []int) {
return fileDescriptor_a142e29cbef9b1cf, []int{6}
}
func (m *CertSignature) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CertSignature.Unmarshal(m, b)
}
func (m *CertSignature) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CertSignature.Marshal(b, m, deterministic)
}
func (m *CertSignature) XXX_Merge(src proto.Message) {
xxx_messageInfo_CertSignature.Merge(m, src)
}
func (m *CertSignature) XXX_Size() int {
return xxx_messageInfo_CertSignature.Size(m)
}
func (m *CertSignature) XXX_DiscardUnknown() {
xxx_messageInfo_CertSignature.DiscardUnknown(m)
}
var xxx_messageInfo_CertSignature proto.InternalMessageInfo
func (m *CertSignature) GetSignature() []byte {
if m != nil {
return m.Signature
}
return nil
}
func (m *CertSignature) GetCert() []byte {
if m != nil {
return m.Cert
}
return nil
}
func (m *CertSignature) GetUid() []byte {
if m != nil {
return m.Uid
}
return nil
}
type ReqQueryValidCertSN struct {
Addr string `protobuf:"bytes,1,opt,name=addr,proto3" json:"addr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReqQueryValidCertSN) Reset() { *m = ReqQueryValidCertSN{} }
func (m *ReqQueryValidCertSN) String() string { return proto.CompactTextString(m) }
func (*ReqQueryValidCertSN) ProtoMessage() {}
func (*ReqQueryValidCertSN) Descriptor() ([]byte, []int) {
return fileDescriptor_a142e29cbef9b1cf, []int{7}
}
func (m *ReqQueryValidCertSN) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReqQueryValidCertSN.Unmarshal(m, b)
}
func (m *ReqQueryValidCertSN) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReqQueryValidCertSN.Marshal(b, m, deterministic)
}
func (m *ReqQueryValidCertSN) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReqQueryValidCertSN.Merge(m, src)
}
func (m *ReqQueryValidCertSN) XXX_Size() int {
return xxx_messageInfo_ReqQueryValidCertSN.Size(m)
}
func (m *ReqQueryValidCertSN) XXX_DiscardUnknown() {
xxx_messageInfo_ReqQueryValidCertSN.DiscardUnknown(m)
}
var xxx_messageInfo_ReqQueryValidCertSN proto.InternalMessageInfo
func (m *ReqQueryValidCertSN) GetAddr() string {
if m != nil {
return m.Addr
}
return ""
}
type RepQueryValidCertSN struct {
Sn []byte `protobuf:"bytes,1,opt,name=sn,proto3" json:"sn,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *RepQueryValidCertSN) Reset() { *m = RepQueryValidCertSN{} }
func (m *RepQueryValidCertSN) String() string { return proto.CompactTextString(m) }
func (*RepQueryValidCertSN) ProtoMessage() {}
func (*RepQueryValidCertSN) Descriptor() ([]byte, []int) {
return fileDescriptor_a142e29cbef9b1cf, []int{8}
}
func (m *RepQueryValidCertSN) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_RepQueryValidCertSN.Unmarshal(m, b)
}
func (m *RepQueryValidCertSN) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_RepQueryValidCertSN.Marshal(b, m, deterministic)
}
func (m *RepQueryValidCertSN) XXX_Merge(src proto.Message) {
xxx_messageInfo_RepQueryValidCertSN.Merge(m, src)
}
func (m *RepQueryValidCertSN) XXX_Size() int {
return xxx_messageInfo_RepQueryValidCertSN.Size(m)
}
func (m *RepQueryValidCertSN) XXX_DiscardUnknown() {
xxx_messageInfo_RepQueryValidCertSN.DiscardUnknown(m)
}
var xxx_messageInfo_RepQueryValidCertSN proto.InternalMessageInfo
func (m *RepQueryValidCertSN) GetSn() []byte {
if m != nil {
return m.Sn
}
return nil
}
func init() { func init() {
proto.RegisterType((*Cert)(nil), "types.Cert") proto.RegisterType((*Cert)(nil), "types.Cert")
proto.RegisterType((*CertAction)(nil), "types.CertAction") proto.RegisterType((*CertAction)(nil), "types.CertAction")
...@@ -390,6 +523,9 @@ func init() { ...@@ -390,6 +523,9 @@ func init() {
proto.RegisterType((*CertUpdate)(nil), "types.CertUpdate") proto.RegisterType((*CertUpdate)(nil), "types.CertUpdate")
proto.RegisterType((*CertNormal)(nil), "types.CertNormal") proto.RegisterType((*CertNormal)(nil), "types.CertNormal")
proto.RegisterType((*Authority)(nil), "types.Authority") proto.RegisterType((*Authority)(nil), "types.Authority")
proto.RegisterType((*CertSignature)(nil), "types.CertSignature")
proto.RegisterType((*ReqQueryValidCertSN)(nil), "types.ReqQueryValidCertSN")
proto.RegisterType((*RepQueryValidCertSN)(nil), "types.RepQueryValidCertSN")
} }
func init() { func init() {
...@@ -397,24 +533,29 @@ func init() { ...@@ -397,24 +533,29 @@ func init() {
} }
var fileDescriptor_a142e29cbef9b1cf = []byte{ var fileDescriptor_a142e29cbef9b1cf = []byte{
// 300 bytes of a gzipped FileDescriptorProto // 380 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0xcd, 0x4a, 0xf3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x52, 0x5d, 0x4b, 0xeb, 0x40,
0x14, 0xed, 0x24, 0xfd, 0xbd, 0xfd, 0x28, 0x9f, 0x83, 0x48, 0x70, 0x21, 0x25, 0xab, 0x82, 0x10, 0x10, 0x6d, 0x92, 0x7e, 0x65, 0xda, 0x5b, 0xee, 0xdd, 0x2b, 0x12, 0x44, 0xa4, 0x04, 0x84, 0x8a,
0xb0, 0xfa, 0x02, 0xd5, 0x4d, 0xdd, 0x14, 0x19, 0xea, 0x5a, 0xa6, 0xe9, 0xd5, 0x06, 0xd3, 0x4c, 0x50, 0xb0, 0xfa, 0x07, 0xaa, 0x2f, 0xf5, 0xa5, 0xe8, 0xb6, 0xfa, 0x2a, 0xdb, 0x66, 0x6c, 0x83,
0x98, 0xde, 0x58, 0xe6, 0x79, 0x7c, 0x51, 0x99, 0x1f, 0x25, 0x82, 0x0b, 0xdd, 0xe5, 0xdc, 0x73, 0xe9, 0x26, 0x6e, 0x36, 0x96, 0xfd, 0x3d, 0xfe, 0x51, 0xd9, 0xcd, 0x56, 0x23, 0xfa, 0xa0, 0x6f,
0x4e, 0xee, 0x39, 0xdc, 0x01, 0xc8, 0x51, 0x53, 0x56, 0x6b, 0x45, 0x8a, 0xf7, 0xc8, 0xd4, 0x78, 0x33, 0x3b, 0xe7, 0xec, 0x39, 0x87, 0x19, 0x80, 0x25, 0x0a, 0x39, 0xcc, 0x44, 0x2a, 0x53, 0xd2,
0x48, 0x9f, 0xa1, 0x7b, 0x87, 0x9a, 0xf8, 0x19, 0xf4, 0x2d, 0x79, 0xbf, 0x4d, 0xd8, 0x94, 0xcd, 0x90, 0x2a, 0xc3, 0x3c, 0x7c, 0x84, 0xfa, 0x15, 0x0a, 0x49, 0xf6, 0xa1, 0xa9, 0x87, 0xd7, 0x51,
0xfe, 0x89, 0x80, 0xf8, 0x05, 0x40, 0xae, 0x51, 0x12, 0xae, 0x8b, 0x3d, 0x26, 0xd1, 0x94, 0xcd, 0xe0, 0xf4, 0x9d, 0x41, 0x97, 0xda, 0x8e, 0x1c, 0x01, 0x2c, 0x05, 0x32, 0x89, 0xf3, 0x78, 0x83,
0x62, 0xd1, 0x9a, 0xf0, 0xff, 0x10, 0xbf, 0xa2, 0x49, 0xe2, 0x29, 0x9b, 0x8d, 0x84, 0xfd, 0xe4, 0x81, 0xdb, 0x77, 0x06, 0x1e, 0xad, 0xbc, 0x90, 0xbf, 0xe0, 0x3d, 0xa1, 0x0a, 0xbc, 0xbe, 0x33,
0xa7, 0xd0, 0x7b, 0x93, 0x65, 0x83, 0x49, 0xd7, 0xfd, 0xc8, 0x83, 0xf4, 0x9d, 0x01, 0xd8, 0x45, 0xf0, 0xa9, 0x2e, 0xc9, 0x1e, 0x34, 0x5e, 0x58, 0x52, 0x60, 0x50, 0x37, 0x1f, 0x95, 0x4d, 0xf8,
0x8b, 0x9c, 0x0a, 0x55, 0xf1, 0x14, 0xe2, 0x0a, 0x8f, 0x6e, 0xd7, 0x78, 0x3e, 0xc9, 0x5c, 0x96, 0xea, 0x00, 0x68, 0xa1, 0xf1, 0x52, 0xc6, 0x29, 0x27, 0x21, 0x78, 0x1c, 0xb7, 0x46, 0xab, 0x33,
0xcc, 0xf2, 0x2b, 0x3c, 0x2e, 0x3b, 0xc2, 0x92, 0xfc, 0x12, 0xfa, 0x4d, 0xbd, 0x95, 0xe4, 0xd7, 0xea, 0x0d, 0x8d, 0x97, 0xa1, 0x9e, 0x4f, 0x71, 0x3b, 0xa9, 0x51, 0x3d, 0x24, 0xa7, 0xd0, 0x2c,
0x8e, 0xe7, 0x27, 0x2d, 0xd9, 0xa3, 0x23, 0x96, 0x1d, 0x11, 0x24, 0x56, 0x5c, 0x29, 0xbd, 0x97, 0xb2, 0x88, 0xc9, 0x52, 0xb6, 0x33, 0xfa, 0x57, 0x81, 0xdd, 0x99, 0xc1, 0xa4, 0x46, 0x2d, 0x44,
0xa5, 0x8b, 0xf2, 0x5d, 0xbc, 0x72, 0x84, 0x15, 0x7b, 0x09, 0x9f, 0x40, 0x44, 0xc6, 0xe5, 0xeb, 0x83, 0x79, 0x2a, 0x36, 0x2c, 0x31, 0x56, 0x3e, 0x83, 0xa7, 0x66, 0xa0, 0xc1, 0x25, 0x84, 0xf4,
0x89, 0x88, 0xcc, 0xed, 0x20, 0x44, 0x4e, 0xaf, 0x60, 0x10, 0x42, 0x7c, 0x16, 0x63, 0x3f, 0x14, 0xc0, 0x95, 0xca, 0xf8, 0x6b, 0x50, 0x57, 0xaa, 0xcb, 0x96, 0xb5, 0x1c, 0x9e, 0x41, 0xcb, 0x9a,
0x8b, 0xda, 0xc5, 0x6e, 0x7c, 0x2f, 0x1f, 0xe8, 0xaf, 0x2e, 0x9f, 0xec, 0xd7, 0xae, 0x27, 0x18, 0xd8, 0x05, 0x73, 0xbe, 0x09, 0xe6, 0x56, 0x83, 0x5d, 0x94, 0xb9, 0x4a, 0x43, 0xbf, 0x65, 0x95,
0x2d, 0x1a, 0xda, 0x29, 0x5d, 0x90, 0xb1, 0x17, 0xc3, 0x4a, 0x6e, 0x4a, 0x74, 0xbe, 0xa1, 0x08, 0xce, 0x7e, 0xcc, 0x7a, 0x00, 0x7f, 0x5c, 0xc8, 0x75, 0x2a, 0x62, 0xa9, 0xf4, 0xc6, 0x90, 0xb3,
0xc8, 0x5f, 0xcc, 0xd4, 0xa4, 0x1e, 0x24, 0xed, 0x9c, 0x7f, 0x24, 0x5a, 0x13, 0x7e, 0x0e, 0xc3, 0x45, 0x82, 0x86, 0xd7, 0xa6, 0xb6, 0x2b, 0x37, 0xa6, 0x32, 0x99, 0xde, 0x30, 0xb9, 0x36, 0x7c,
0x43, 0xf1, 0x52, 0xad, 0x4d, 0x8d, 0xe1, 0x6c, 0x5f, 0x78, 0xd3, 0x77, 0x6f, 0xe3, 0xfa, 0x23, 0x9f, 0x56, 0x5e, 0xc8, 0x01, 0xb4, 0xf3, 0x78, 0xc5, 0xe7, 0x2a, 0x43, 0xbb, 0xb6, 0xf7, 0x3e,
0x00, 0x00, 0xff, 0xff, 0x1d, 0xbc, 0xa5, 0x33, 0x29, 0x02, 0x00, 0x00, 0x9c, 0xc1, 0x1f, 0x6d, 0x6b, 0x16, 0xaf, 0x38, 0x93, 0x85, 0x40, 0x72, 0x08, 0x7e, 0xbe, 0x6b,
0xec, 0x65, 0x7c, 0x3c, 0x10, 0x02, 0x75, 0x7d, 0x26, 0xd6, 0xa4, 0xa9, 0x75, 0x96, 0x22, 0x8e,
0xcc, 0xcf, 0x5d, 0xaa, 0xcb, 0xf0, 0x04, 0xfe, 0x53, 0x7c, 0xbe, 0x2d, 0x50, 0xa8, 0x7b, 0x96,
0xc4, 0x91, 0x51, 0x98, 0x6a, 0x32, 0x8b, 0x22, 0x61, 0x53, 0x9b, 0x3a, 0x3c, 0xd6, 0xd0, 0xec,
0x0b, 0xb4, 0x07, 0x6e, 0xce, 0xad, 0xbc, 0x9b, 0xf3, 0x45, 0xd3, 0x9c, 0xf0, 0xf9, 0x5b, 0x00,
0x00, 0x00, 0xff, 0xff, 0x7e, 0x07, 0x28, 0x2a, 0xd0, 0x02, 0x00, 0x00,
} }
...@@ -14,4 +14,6 @@ var ( ...@@ -14,4 +14,6 @@ var (
"Update": CertActionUpdate, "Update": CertActionUpdate,
"Normal": CertActionNormal, "Normal": CertActionNormal,
} }
AdminKey = "Auth-cert-admin"
) )
...@@ -15,4 +15,6 @@ var ( ...@@ -15,4 +15,6 @@ var (
ErrUnknowAuthSignType = errors.New("ErrUnknowAuthSignType") ErrUnknowAuthSignType = errors.New("ErrUnknowAuthSignType")
// ErrInitializeAuthority 初始化校验器失败 // ErrInitializeAuthority 初始化校验器失败
ErrInitializeAuthority = errors.New("ErrInitializeAuthority") ErrInitializeAuthority = errors.New("ErrInitializeAuthority")
// ErrPermissionDeny 权限校验失败
ErrPermissionDeny = errors.New("ErrPermissionDeny")
) )
...@@ -534,8 +534,8 @@ paracross_testBind() { ...@@ -534,8 +534,8 @@ paracross_testBind() {
chain33_SignAndSendTxWait "$rawtx" "${priv1q9}" "${para_ip}" chain33_SignAndSendTxWait "$rawtx" "${priv1q9}" "${para_ip}"
echo "2. get bind" echo "2. get bind"
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"data":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List.SuperNode| [has("1KSBd17H7Z"),true])' "$FUNCNAME" '(.result.List)' chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"superNode":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List| [has("1KSBd17H7Z"),true])' "$FUNCNAME" '(.result.List)'
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"data":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List.Miners| [has("1Q9sQw"),true])' "$FUNCNAME" '(.result.List)' chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"superNode":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List| [has("1Q9sQw"),true])' "$FUNCNAME" '(.result.List)'
} }
paracross_testUnBind() { paracross_testUnBind() {
...@@ -554,8 +554,8 @@ paracross_testUnBind() { ...@@ -554,8 +554,8 @@ paracross_testUnBind() {
# superNode=$(jq -r ".result.List.SuperNode" <<<"$resp") # superNode=$(jq -r ".result.List.SuperNode" <<<"$resp")
# miners=$(jq -r ".result.List.Miners" <<<"$resp") # miners=$(jq -r ".result.List.Miners" <<<"$resp")
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"data":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List.SuperNode| [has("1KSBd17H7Z"),true])' "$FUNCNAME" '(.result.List)' chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"superNode":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List| [has("1KSBd17H7Z"),true])' "$FUNCNAME" '(.result.List)'
chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"data":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List.Miners| [has("1Q9sQw"),false])' "$FUNCNAME" '(.result.List)' chain33_Http '{"method":"Chain33.Query","params":[{ "execer":"paracross", "funcName":"GetNodeBindMinerList","payload":{"superNode":"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}}]}' "${para_ip}" '(.error|not) and (.result.List| [has("1Q9sQw"),false])' "$FUNCNAME" '(.result.List)'
} }
paracross_testBindMiner() { paracross_testBindMiner() {
......
...@@ -581,19 +581,20 @@ func getNodeBindListCmd() *cobra.Command { ...@@ -581,19 +581,20 @@ func getNodeBindListCmd() *cobra.Command {
func addNodeBindCmdFlags(cmd *cobra.Command) { func addNodeBindCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("node", "n", "", "super node addr to bind miner") cmd.Flags().StringP("node", "n", "", "super node addr to bind miner")
cmd.MarkFlagRequired("node") cmd.Flags().StringP("miner", "m", "", "bind miner addr")
} }
func nodeBindInfo(cmd *cobra.Command, args []string) { func nodeBindInfo(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr") rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
addr, _ := cmd.Flags().GetString("node") node, _ := cmd.Flags().GetString("node")
miner, _ := cmd.Flags().GetString("miner")
var params rpctypes.Query4Jrpc var params rpctypes.Query4Jrpc
params.Execer = pt.ParaX params.Execer = pt.ParaX
params.FuncName = "GetNodeBindMinerList" params.FuncName = "GetNodeBindMinerList"
params.Payload = types.MustPBToJSON(&types.ReqString{Data: addr}) params.Payload = types.MustPBToJSON(&pt.ParaNodeBindOne{SuperNode: node, Miner: miner})
var res pt.RespParaNodeBindList var res pt.RespParaNodeBindList
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res) ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", params, &res)
......
...@@ -1298,14 +1298,18 @@ func (a *action) Miner(miner *pt.ParacrossMinerAction) (*types.Receipt, error) { ...@@ -1298,14 +1298,18 @@ func (a *action) Miner(miner *pt.ParacrossMinerAction) (*types.Receipt, error) {
if fundReward > 0 { if fundReward > 0 {
totalReward += fundReward totalReward += fundReward
} }
totalReward *= types.Coin
decimalMode := cfg.MIsEnable("mver.consensus.paracross.decimalMode", a.height)
if !decimalMode {
totalReward *= types.Coin
}
if totalReward > 0 { if totalReward > 0 {
issueReceipt, err := a.coinsAccount.ExecIssueCoins(a.execaddr, totalReward) issueReceipt, err := a.coinsAccount.ExecIssueCoins(a.execaddr, totalReward)
if err != nil { if err != nil {
clog.Error("paracross miner issue err", "height", miner.Status.Height, clog.Error("paracross miner issue err", "height", miner.Status.Height,
"execAddr", a.execaddr, "amount", totalReward/types.Coin) "execAddr", a.execaddr, "amount", totalReward)
return nil, err return nil, err
} }
minerReceipt = mergeReceipt(minerReceipt, issueReceipt) minerReceipt = mergeReceipt(minerReceipt, issueReceipt)
......
...@@ -192,6 +192,6 @@ func calcParaBindMinerAddr(node, bind string) []byte { ...@@ -192,6 +192,6 @@ func calcParaBindMinerAddr(node, bind string) []byte {
return []byte(fmt.Sprintf(paraBindMinderAddr+"%s-%s", node, bind)) return []byte(fmt.Sprintf(paraBindMinderAddr+"%s-%s", node, bind))
} }
func calcParaBindMinerNode(node string) []byte { func calcParaBindMinerNode() []byte {
return []byte(paraBindMinderNode + node) return []byte(paraBindMinderNode)
} }
...@@ -534,29 +534,63 @@ func (p *Paracross) Query_GetHeight(req *types.ReqString) (*pt.ParacrossConsensu ...@@ -534,29 +534,63 @@ func (p *Paracross) Query_GetHeight(req *types.ReqString) (*pt.ParacrossConsensu
return nil, types.ErrDecode return nil, types.ErrDecode
} }
func getMinerListResp(db dbm.KV, list *pt.ParaNodeBindList) (types.Message, error) {
var resp pt.RespParaNodeBindList
resp.List = list
for _, n := range list.Miners {
info, err := getBindAddrInfo(db, n.SuperNode, n.Miner)
if err != nil {
clog.Error("Query_GetNodeBindMinerList get addr", "err", err, "node", n.SuperNode, "addr", n.Miner)
return nil, errors.Cause(err)
}
resp.Details = append(resp.Details, info)
}
return &resp, nil
}
// Query_GetNodeBindMinerList query get super node bind miner list // Query_GetNodeBindMinerList query get super node bind miner list
func (p *Paracross) Query_GetNodeBindMinerList(in *types.ReqString) (types.Message, error) { func (p *Paracross) Query_GetNodeBindMinerList(in *pt.ParaNodeBindOne) (types.Message, error) {
if in == nil || len(in.Data) == 0 { if in == nil {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
list, err := getBindNodeInfo(p.GetStateDB(), in.Data) list, err := getBindNodeInfo(p.GetStateDB())
if err != nil { if err != nil {
clog.Error("Query_GetNodeBindMinerList get node", "err", err, "req", in.Data) clog.Error("Query_GetNodeBindMinerList get node", "err", err)
return nil, errors.Cause(err) return nil, errors.Cause(err)
} }
var resp pt.RespParaNodeBindList var newList pt.ParaNodeBindList
resp.List = list //按node query
if len(in.SuperNode) != 0 && len(in.Miner) == 0 {
for _, n := range list.Miners {
if n.SuperNode == in.SuperNode {
newList.Miners = append(newList.Miners, n)
}
}
return getMinerListResp(p.GetStateDB(), &newList)
}
for _, addr := range list.Miners { //按miner query
info, err := getBindAddrInfo(p.GetStateDB(), in.Data, addr) if len(in.SuperNode) == 0 && len(in.Miner) != 0 {
if err != nil { for _, n := range list.Miners {
clog.Error("Query_GetNodeBindMinerList get addr", "err", err, "node", in.Data, "addr", addr) if n.Miner == in.Miner {
return nil, errors.Cause(err) newList.Miners = append(newList.Miners, n)
}
} }
resp.Details = append(resp.Details, info) return getMinerListResp(p.GetStateDB(), &newList)
}
//按唯一绑定查询
if len(in.SuperNode) != 0 && len(in.Miner) != 0 {
for _, n := range list.Miners {
if n.SuperNode == in.SuperNode && n.Miner == in.Miner {
newList.Miners = append(newList.Miners, n)
}
}
return getMinerListResp(p.GetStateDB(), &newList)
} }
return &resp, nil //获取所有
return getMinerListResp(p.GetStateDB(), list)
} }
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types" pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/golang/protobuf/proto"
) )
const ( const (
...@@ -15,36 +16,28 @@ const ( ...@@ -15,36 +16,28 @@ const (
opUnBind = 2 opUnBind = 2
) )
//根据挖矿节点地址 获取委托挖矿地址 //根据挖矿共识节点地址 过滤整体共识节点映射列表, 获取委托挖矿地址
func (a *action) getBindAddrs(nodes []string, statusHeight int64) []*pt.ParaNodeBindList { func (a *action) getBindAddrs(nodes []string, statusHeight int64) (*pt.ParaNodeBindList, error) {
var lists []*pt.ParaNodeBindList nodesMap := make(map[string]bool)
for _, m := range nodes { for _, n := range nodes {
list, err := getBindNodeInfo(a.db, m) nodesMap[n] = true
if isNotFound(errors.Cause(err)) {
continue
}
if err != nil {
clog.Error("paracross getBindAddrs err", "height", statusHeight, "node", m)
continue
}
lists = append(lists, list)
} }
return lists var newLists pt.ParaNodeBindList
list, err := getBindNodeInfo(a.db)
} if err != nil {
clog.Error("paracross getBindAddrs err", "height", statusHeight)
func isBindAddrFound(bindAddrs []*pt.ParaNodeBindList) bool { return nil, err
if len(bindAddrs) <= 0 {
return false
} }
//这样检索是按照list的映射顺序,不是按照nodes的顺序(需要循环嵌套)
for _, addr := range bindAddrs { for _, m := range list.Miners {
if len(addr.Miners) > 0 { if nodesMap[m.SuperNode] {
return true newLists.Miners = append(newLists.Miners, m)
} }
} }
return false
return &newLists, nil
} }
func (a *action) rewardSuperNode(coinReward int64, miners []string, statusHeight int64) (*types.Receipt, int64, error) { func (a *action) rewardSuperNode(coinReward int64, miners []string, statusHeight int64) (*types.Receipt, int64, error) {
...@@ -70,21 +63,19 @@ func (a *action) rewardSuperNode(coinReward int64, miners []string, statusHeight ...@@ -70,21 +63,19 @@ func (a *action) rewardSuperNode(coinReward int64, miners []string, statusHeight
} }
//奖励委托挖矿账户 //奖励委托挖矿账户
func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindList, statusHeight int64) (*types.Receipt, int64, error) { func (a *action) rewardBindAddr(coinReward int64, bindList *pt.ParaNodeBindList, statusHeight int64) (*types.Receipt, int64, error) {
if coinReward <= 0 { if coinReward <= 0 {
return nil, 0, nil return nil, 0, nil
} }
//有可能一个bindAddr 在多个node绑定,这里会累计上去 //有可能一个bindAddr 在多个node绑定,这里会累计上去
var bindAddrList []*pt.ParaBindMinerInfo var bindAddrList []*pt.ParaBindMinerInfo
for _, node := range bindList { for _, node := range bindList.Miners {
for _, miner := range node.Miners { info, err := getBindAddrInfo(a.db, node.SuperNode, node.Miner)
info, err := getBindAddrInfo(a.db, node.SuperNode, miner) if err != nil {
if err != nil { return nil, 0, err
return nil, 0, err
}
bindAddrList = append(bindAddrList, info)
} }
bindAddrList = append(bindAddrList, info)
} }
var totalCoins int64 var totalCoins int64
...@@ -116,9 +107,17 @@ func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindLis ...@@ -116,9 +107,17 @@ func (a *action) rewardBindAddr(coinReward int64, bindList []*pt.ParaNodeBindLis
func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHeightStatus) (*types.Receipt, error) { func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHeightStatus) (*types.Receipt, error) {
//获取挖矿相关配置,这里需注意是共识的高度,而不是交易的高度 //获取挖矿相关配置,这里需注意是共识的高度,而不是交易的高度
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
coinReward := cfg.MGInt("mver.consensus.paracross.coinReward", nodeStatus.Height) * types.Coin coinReward := cfg.MGInt("mver.consensus.paracross.coinReward", nodeStatus.Height)
coinBaseReward := cfg.MGInt("mver.consensus.paracross.coinBaseReward", nodeStatus.Height) * types.Coin fundReward := cfg.MGInt("mver.consensus.paracross.coinDevFund", nodeStatus.Height)
fundReward := cfg.MGInt("mver.consensus.paracross.coinDevFund", nodeStatus.Height) * types.Coin coinBaseReward := cfg.MGInt("mver.consensus.paracross.coinBaseReward", nodeStatus.Height)
decimalMode := cfg.MIsEnable("mver.consensus.paracross.decimalMode", nodeStatus.Height)
if !decimalMode {
coinReward *= types.Coin
fundReward *= types.Coin
coinBaseReward *= types.Coin
}
fundAddr := cfg.MGStr("mver.consensus.fundKeyAddr", nodeStatus.Height) fundAddr := cfg.MGStr("mver.consensus.fundKeyAddr", nodeStatus.Height)
//防止coinBaseReward 设置出错场景, coinBaseReward 一定要比coinReward小 //防止coinBaseReward 设置出错场景, coinBaseReward 一定要比coinReward小
...@@ -127,18 +126,21 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe ...@@ -127,18 +126,21 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe
} }
//超级节点地址 //超级节点地址
minerAddrs := getMiners(stat.Details, nodeStatus.BlockHash) nodeAddrs := getSuperNodes(stat.Details, nodeStatus.BlockHash)
//委托地址 //委托地址
bindAddrs := a.getBindAddrs(minerAddrs, nodeStatus.Height) bindAddrs, err := a.getBindAddrs(nodeAddrs, nodeStatus.Height)
if err != nil {
return nil, err
}
//奖励超级节点 //奖励超级节点
minderRewards := coinReward minderRewards := coinReward
//如果有委托挖矿地址,则超级节点分baseReward部分,否则全部 //如果有委托挖矿地址,则超级节点分baseReward部分,否则全部
if isBindAddrFound(bindAddrs) { if len(bindAddrs.Miners) > 0 {
minderRewards = coinBaseReward minderRewards = coinBaseReward
} }
receipt := &types.Receipt{Ty: types.ExecOk} receipt := &types.Receipt{Ty: types.ExecOk}
r, change, err := a.rewardSuperNode(minderRewards, minerAddrs, nodeStatus.Height) r, change, err := a.rewardSuperNode(minderRewards, nodeAddrs, nodeStatus.Height)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -167,8 +169,8 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe ...@@ -167,8 +169,8 @@ func (a *action) reward(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHe
return receipt, nil return receipt, nil
} }
// getMiners 获取提交共识消息的矿工地址 // getSuperNodes 获取提交共识消息的矿工地址
func getMiners(detail *pt.ParacrossStatusDetails, blockHash []byte) []string { func getSuperNodes(detail *pt.ParacrossStatusDetails, blockHash []byte) []string {
addrs := make([]string, 0) addrs := make([]string, 0)
for i, hash := range detail.BlockHash { for i, hash := range detail.BlockHash {
if bytes.Equal(hash, blockHash) { if bytes.Equal(hash, blockHash) {
...@@ -210,8 +212,8 @@ func makeAddrBindReceipt(node, addr string, prev, current *pt.ParaBindMinerInfo) ...@@ -210,8 +212,8 @@ func makeAddrBindReceipt(node, addr string, prev, current *pt.ParaBindMinerInfo)
} }
} }
func makeNodeBindReceipt(addr string, prev, current *pt.ParaNodeBindList) *types.Receipt { func makeNodeBindReceipt(prev, current *pt.ParaNodeBindList) *types.Receipt {
key := calcParaBindMinerNode(addr) key := calcParaBindMinerNode()
log := &pt.ReceiptParaNodeBindListUpdate{ log := &pt.ReceiptParaNodeBindListUpdate{
Prev: prev, Prev: prev,
Current: current, Current: current,
...@@ -233,51 +235,56 @@ func makeNodeBindReceipt(addr string, prev, current *pt.ParaNodeBindList) *types ...@@ -233,51 +235,56 @@ func makeNodeBindReceipt(addr string, prev, current *pt.ParaNodeBindList) *types
//绑定到超级节点 //绑定到超级节点
func (a *action) bind2Node(node string) (*types.Receipt, error) { func (a *action) bind2Node(node string) (*types.Receipt, error) {
info, err := getBindNodeInfo(a.db, node) list, err := getBindNodeInfo(a.db)
if err != nil && !isNotFound(errors.Cause(err)) { if err != nil {
return nil, errors.Wrap(err, "bind2Node") return nil, errors.Wrap(err, "bind2Node")
} }
//found //由于kvmvcc内存架构,如果存储结构为nil,将回溯查找,这样在只有一个绑定时候,unbind后,有可能会回溯到更早状态,是错误的,title这里就是占位使用
if info != nil { if len(list.Title) <= 0 {
listCopy := *info list.Title = a.api.GetConfig().GetTitle()
info.Miners = append(info.Miners, a.fromaddr)
return makeNodeBindReceipt(node, &listCopy, info), nil
} }
//unfound
var list pt.ParaNodeBindList old := proto.Clone(list).(*pt.ParaNodeBindList)
list.SuperNode = node list.Miners = append(list.Miners, &pt.ParaNodeBindOne{SuperNode: node, Miner: a.fromaddr})
list.Miners = append(list.Miners, a.fromaddr)
return makeNodeBindReceipt(node, nil, &list), nil return makeNodeBindReceipt(old, list), nil
} }
//从超级节点解绑 //从超级节点解绑
func (a *action) unbind2Node(node string) (*types.Receipt, error) { func (a *action) unbind2Node(node string) (*types.Receipt, error) {
list, err := getBindNodeInfo(a.db, node) list, err := getBindNodeInfo(a.db)
if err != nil { if err != nil {
return nil, errors.Wrap(err, "unbind2Node") return nil, errors.Wrap(err, "unbind2Node")
} }
newList := &pt.ParaNodeBindList{SuperNode: list.SuperNode} newList := &pt.ParaNodeBindList{Title: a.api.GetConfig().GetTitle()}
old := proto.Clone(list).(*pt.ParaNodeBindList)
for _, m := range list.Miners { for _, m := range list.Miners {
if m != a.fromaddr { if m.SuperNode == node && m.Miner == a.fromaddr {
newList.Miners = append(newList.Miners, m) continue
} }
newList.Miners = append(newList.Miners, m)
} }
return makeNodeBindReceipt(node, list, newList), nil return makeNodeBindReceipt(old, newList), nil
} }
func getBindNodeInfo(db dbm.KV, node string) (*pt.ParaNodeBindList, error) { func getBindNodeInfo(db dbm.KV) (*pt.ParaNodeBindList, error) {
key := calcParaBindMinerNode(node) var list pt.ParaNodeBindList
key := calcParaBindMinerNode()
data, err := db.Get(key) data, err := db.Get(key)
if isNotFound(err) {
return &list, nil
}
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "get key failed node=%s", node) return nil, errors.Wrapf(err, "get key failed")
} }
var list pt.ParaNodeBindList
err = types.Decode(data, &list) err = types.Decode(data, &list)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "decode failed node=%s", node) return nil, errors.Wrapf(err, "decode failed")
} }
return &list, nil return &list, nil
} }
...@@ -380,6 +387,10 @@ func (a *action) unBindOp(cmd *pt.ParaBindMinerCmd) (*types.Receipt, error) { ...@@ -380,6 +387,10 @@ func (a *action) unBindOp(cmd *pt.ParaBindMinerCmd) (*types.Receipt, error) {
return nil, errors.Wrapf(types.ErrNotAllow, "unBindOp unbind time=%d less %d hours than bind time =%d", a.blocktime, unBindHours, acct.BlockTime) return nil, errors.Wrapf(types.ErrNotAllow, "unBindOp unbind time=%d less %d hours than bind time =%d", a.blocktime, unBindHours, acct.BlockTime)
} }
if acct.BindStatus != opBind {
return nil, errors.Wrapf(types.ErrNotAllow, "unBindOp,current addr is unbind status")
}
//unfrozen //unfrozen
receipt, err := a.coinsAccount.ExecActive(a.fromaddr, a.execaddr, acct.BindCoins*types.Coin) receipt, err := a.coinsAccount.ExecActive(a.fromaddr, a.execaddr, acct.BindCoins*types.Coin)
if err != nil { if err != nil {
......
# 平行链共识节点挖矿奖励规则
>平行链共识节点是参与平行链共识安全的节点,发送共识交易,同时享受平行链挖矿奖励
## 共识节点资格
1. 共识节点需要加入共识节点账户组才具有发送共识交易的资格,不然即使发送也不会被接受
1. 新的共识节点需要共识节点账户组成员超过2/3投票通过才可以加入共识节点账户组
## 共识节点挖矿奖励
1. 共识节点根据本地计算的区块哈希发送共识交易参与共识,共识达成后促使达成共识的节点享受挖矿奖励
1. 比如共识账户组有4个挖矿账户A,B,C,D,其中A,B,C,D都依次发送共识交易,基于超过2/3的规则,在C的共识交易收到后即达成共识,那么奖励将分给A,B,C,而D是在达成共识后发送的,不享受挖矿奖励
## 绑定共识节点挖矿(矿池的概念)
1. 如果账户不是共识节点,但是想参与挖矿奖励,可以锁定平行链基础coins到paracross合约,并绑定到共识节点参与挖矿
1. 绑定账户可以绑定到一个或多个共识节点参与挖矿
1. 挖矿奖励按锁定coins数量的权重来分配挖矿奖励
1. 如果绑定的共识节点在某高度没有得到挖矿奖励,对应的绑定账户也得不到相应奖励
1. 绑定账户可以通过bind命令的coins 数量的修改来增加或减少锁定coins数量,可以通过unbind命令解除对某个共识节点的绑定
## 奖励规则和金额
>奖励规则和金额可配置
```
[mver.consensus.paracross]
#超级节点挖矿奖励
coinReward=18
#发展基金奖励
coinDevFund=12
#如果超级节点上绑定了委托账户,则奖励超级节点coinBaseReward,其余部分(coinReward-coinBaseReward)按权重分给委托账户
coinBaseReward=3
#委托账户最少解绑定时间(按小时)
unBindTime=24
```
1. 每个区块产生的挖矿总奖励如配置项是coinDevFund+coinReward=30,共识达成后,发展基金账户分走12,剩余的18个coin平均分给达成共识的节点
1. 如果有绑定挖矿的账户绑定了共识节点进行挖矿,则共识节点平分基础的coinBaseReward,剩余部分(coinReward-coinBaseReward)按绑定挖矿锁定币的权重数量分给绑定挖矿的节点。
## 绑定挖矿命令
1. 生成 绑定/解绑定 挖矿 的交易(未签名)
```
{
"method" : "Chain33.CreateTransaction",
"params" : [
{
"execer" : "{user.p.para}.paracross",
"actionName" : "ParaBindMiner",
"payload" : {
       "bindAction":"1"
"bindCoins" : 5,
"targetNode" : "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4",
}
}
],
}
```
**参数说明:**
|参数|类型|说明|
|----|----|----|
|method|string|Chain33.CreateTransaction|
|execer|string|必须是平行链的执行器user.p.para.paracross,title:user.p.para.按需调整|
|actionName|string|ParaBindMiner|
|bindAction|string|绑定:1,解绑定:2|
|bindCoins|int|绑定挖矿冻结币的份额,需冻结平行链原生代币,解绑定不需要此配置|
|targetNode|string|绑定目标共识节点,需要是共识账户组的成员|
...@@ -83,14 +83,14 @@ func (suite *RewardTestSuite) TestRewardBindAddr() { ...@@ -83,14 +83,14 @@ func (suite *RewardTestSuite) TestRewardBindAddr() {
key = calcParaBindMinerAddr(node, addr2) key = calcParaBindMinerAddr(node, addr2)
suite.stateDB.Set(key, data) suite.stateDB.Set(key, data)
list := &pt.ParaNodeBindList{ node1 := &pt.ParaNodeBindOne{SuperNode: node, Miner: addr}
SuperNode: node, node2 := &pt.ParaNodeBindOne{SuperNode: node, Miner: addr2}
Miners: []string{addr, addr2},
}
lists := []*pt.ParaNodeBindList{list} list := &pt.ParaNodeBindList{}
list.Miners = append(list.Miners, node1)
list.Miners = append(list.Miners, node2)
recp, change, err := suite.action.rewardBindAddr(50000005, lists, 1) recp, change, err := suite.action.rewardBindAddr(50000005, list, 1)
suite.Nil(err) suite.Nil(err)
suite.Equal(int64(5), change) suite.Equal(int64(5), change)
suite.Equal(int32(types.ExecOk), recp.Ty) suite.Equal(int32(types.ExecOk), recp.Ty)
......
...@@ -180,9 +180,14 @@ message ReceiptParaBindMinerInfo{ ...@@ -180,9 +180,14 @@ message ReceiptParaBindMinerInfo{
ParaBindMinerInfo current = 3; ParaBindMinerInfo current = 3;
} }
message ParaNodeBindList{ message ParaNodeBindOne{
string superNode = 1; string superNode = 1;
repeated string miners = 2; string miner = 2;
}
message ParaNodeBindList{
string title = 1;
repeated ParaNodeBindOne miners = 2;
} }
message ReceiptParaNodeBindListUpdate{ message ReceiptParaNodeBindListUpdate{
......
This diff is collapsed.
...@@ -35,3 +35,8 @@ func (s *storage) Exec_EncryptShareStorage(payload *storagetypes.EncryptShareNot ...@@ -35,3 +35,8 @@ func (s *storage) Exec_EncryptShareStorage(payload *storagetypes.EncryptShareNot
action := newStorageAction(s, tx, index) action := newStorageAction(s, tx, index)
return action.EncryptShareStorage(payload) return action.EncryptShareStorage(payload)
} }
func (s *storage) Exec_EncryptAdd(payload *storagetypes.EncryptNotaryAdd, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newStorageAction(s, tx, index)
return action.EncryptAdd(payload)
}
...@@ -115,6 +115,27 @@ func (s *storage) ExecLocal_EncryptShareStorage(payload *ety.EncryptShareNotaryS ...@@ -115,6 +115,27 @@ func (s *storage) ExecLocal_EncryptShareStorage(payload *ety.EncryptShareNotaryS
return s.addAutoRollBack(tx, dbSet.KV), nil return s.addAutoRollBack(tx, dbSet.KV), nil
} }
func (s *storage) ExecLocal_EncryptAdd(payload *ety.EncryptNotaryAdd, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
cfg := s.GetAPI().GetConfig()
if cfg.IsDappFork(s.GetHeight(), ety.StorageX, ety.ForkStorageLocalDB) {
if receiptData.Ty == types.ExecOk {
for _, log := range receiptData.Logs {
switch log.Ty {
case ety.TyEncryptAddLog:
storage := &ety.Storage{}
if err := types.Decode(log.Log, storage); err != nil {
return nil, err
}
kv := &types.KeyValue{Key: getLocalDBKey(storage.GetEncryptStorage().Key), Value: types.Encode(storage)}
dbSet.KV = append(dbSet.KV, kv)
}
}
}
}
return s.addAutoRollBack(tx, dbSet.KV), nil
}
//设置自动回滚 //设置自动回滚
func (s *storage) addAutoRollBack(tx *types.Transaction, kv []*types.KeyValue) *types.LocalDBSet { func (s *storage) addAutoRollBack(tx *types.Transaction, kv []*types.KeyValue) *types.LocalDBSet {
......
...@@ -165,6 +165,28 @@ func TestStorage(t *testing.T) { ...@@ -165,6 +165,28 @@ func TestStorage(t *testing.T) {
assert.Equal(t, common.Sha256(contents[0]), reply.GetEncryptStorage().ContentHash) assert.Equal(t, common.Sha256(contents[0]), reply.GetEncryptStorage().ContentHash)
assert.Equal(t, crypted, reply.GetEncryptStorage().EncryptContent) assert.Equal(t, crypted, reply.GetEncryptStorage().EncryptContent)
assert.Equal(t, ivs[0], reply.GetEncryptStorage().Nonce) assert.Equal(t, ivs[0], reply.GetEncryptStorage().Nonce)
// 同态加密
c1, _ := common.FromHex("010076833cbc35c9b7a87eda9aab7aafec45bd7eb8c0e9306141e7d1e84ecd87a5cb9f80343551bd9b0d04669fd74d020fca8837d9b3b471e3e13c125a06663d820cabb36c243747a11ea2601a9cb32e61c697dcdc846c492d954fa8c3ca2be662e8c0142138b647ce5d9e7c4c4d2ace8ba3c5699fbec98beef24e3c740967ec0b72b1626ecd4a7ce54960ae9bc1e2ea5594b05778f4f772aa213a06421744ed8dd775fb8f212bcc7e0da5fe4949051e6aa09d47db7e8d5028ecc41cea2aed4e23aefd80714519662fae980e3a6ca3defc0dd5596cb7e90da29e1bdd84db82603aed78fb8f98687898cd675da74452052ff1761446bf2ee922fc8c56b7e1beb2d4b91042742837052b340e4afce1836badf4a56ef775bb6a94fd91686a44122543fdab3ee90488160068769fbce2e74ffd5e052bb4c651969c4755f6eb5d7ea0cee3e7fa58f4b38b1722535909bd0f325a0b8d0797c15300ab06095b305f46497bbd75c3682d379387f55f638cd10639db1f050090bfd5d291718cee9fc6894d04ba6ef0acb477184512984f435b13e9bffe630bbc8ceade6d269487bf219e25b3beecc46afb98fb8e1fec1a9ad0af0a16e70611f9a4337af05a2ff82d7c9dcebeea9d8e2070413e49e29ff564e6dcee5696e39dc590ff8f8f553834c66c5ae730d05441e3fcc59de0d6efb12fd8852e19f2e309e4ac4cbf0634655fcaab5a70b4eab49829190ea2862c2568e8b69ff0324055f92275de05f2de1d6a8a78333370da754708f7a827f5e9bbe2e58d58294cafef37898a5a5a4866678b6e07941a3bfcb3c3f2d150f830a12d8e0dd20d756099be48f10d51521b3ba0c49f2ab139724ae3962999d75b88bf572fbfd86b6eef3bad5a446b97949d95f9e742500f8609ecfe189d2b4d5a47ea997164f48b3872ec525f16ec23fa5700d10d3385019edfabfec780f15b639f6863332c69fe6b17895620821fe6aaf94caab29c0fec19ff1bebc59f5ed8f973a3b720257cce803541406ae8e75163cf0049f8fbf14d239e86089cdefba8bcbb03db284283a1ff572320aeb7d4a139d4429e00c8bb196539d7")
c2, _ := common.FromHex("010076833cbc35c9b7a87eda9aab7aafec45bd7eb8c0e9306141e7d1e84ecd87a5cb9f80343551bd9b0d04669fd74d020fca8837d9b3b471e3e13c125a06663d820cabb36c243747a11ea2601a9cb32e61c697dcdc846c492d954fa8c3ca2be662e8c0142138b647ce5d9e7c4c4d2ace8ba3c5699fbec98beef24e3c740967ec0b72b1626ecd4a7ce54960ae9bc1e2ea5594b05778f4f772aa213a06421744ed8dd775fb8f212bcc7e0da5fe4949051e6aa09d47db7e8d5028ecc41cea2aed4e23aefd80714519662fae980e3a6ca3defc0dd5596cb7e90da29e1bdd84db82603aed78fb8f98687898cd675da74452052ff1761446bf2ee922fc8c56b7e1beb2d4b9338ddba1f37e26ef7e0b9cb3bec18dc4b450d91a1a0901a3aca75000b58dd639635dce66553945a698b186c89443361ab4c1d3525de6bace217cd27fce0c8f6efc9e7c95269139487b5772182d8276ed6edfe0560537d18330aae4191af1dfae0a430b2021401bc17a111730f7114f514b7b84cb09bf717c67bb25c21a31b3a062f32dceb99103cdd622242148ec1799d04f4f3f4fc5af9e18cfaf356388b1413cc95b6f5bc0c293acf09ad0513e15d2ea525f120930e6072e0cf750e4e03bbf65b278ad92476f5e507bb51f01c3d2797931794cad156b5980fb5ec51fc82e99fde99e81dd85e9dba1d549aa8768c609e46171750b7bc636b709e47c92b076f1b7f71bff1fd690f8bfcdbf48559f777017b9ad300cbb3a1089f3eb6fed5632be9edecc33be09da7d43275640a097114f8f9e529289cce15d7b4ba613feda9e4d818743bf2741c5cd2aaaec7cc96ed835ee909ea0e9675f57bad4ad01688cc2a77e6181a0bca9a46d0ca160a1d94771e24db357e861e1f029104782445413c6d4861404df9ec3140b895083ebbb8a92bbc7decc8990353e9347a7933f85ef94ed325a331b3e6e6c752086adc7926abac3dfd8c8f3d7add64c80f327c1c4d74fde7a6c8981f79ede165f0584e5d6317d7272d9836098cd8ef82fbe85770962b709dfe1f2ae3454ac471e6ea24c6545f332a3eb4eecbc09e2276748d484a5216361")
c3, _ := common.FromHex("010076833cbc35c9b7a87eda9aab7aafec45bd7eb8c0e9306141e7d1e84ecd87a5cb9f80343551bd9b0d04669fd74d020fca8837d9b3b471e3e13c125a06663d820cabb36c243747a11ea2601a9cb32e61c697dcdc846c492d954fa8c3ca2be662e8c0142138b647ce5d9e7c4c4d2ace8ba3c5699fbec98beef24e3c740967ec0b72b1626ecd4a7ce54960ae9bc1e2ea5594b05778f4f772aa213a06421744ed8dd775fb8f212bcc7e0da5fe4949051e6aa09d47db7e8d5028ecc41cea2aed4e23aefd80714519662fae980e3a6ca3defc0dd5596cb7e90da29e1bdd84db82603aed78fb8f98687898cd675da74452052ff1761446bf2ee922fc8c56b7e1beb2d4b90a734625f41c1709ad56e8a801346d70f190e7080c805de1e380198a4ebaf86ca6e5b9dbdc6eacad7c545f78c718a6e0262bc61d68244f99255d0fc8126cfbc0449e935bf5ee81af5e600f7d5b23b4b2d1f48482e037642690035f0289d4d3c72662d63e958edf8d566c765bcbc44cedc618b31db5eebdc6fd5848d53161e3e01c6c73010c32391db709a71cedb4c45fb71ec85de48ace0cba009ef2c0a88386e62b9607faf36c9b219508281267c0df2a182a88ad8fd146101564f5a14c7fd5ed2d4ae547c8741a31c560501230edd5417c622a7aba8d7efb08c08d5b7c45508c766353f2d43bd092834461f0673196abc8ef56b9fd54bdf82c2a392ff8dedcef3d90d3e47370d31083c2d19cefe2ce83936fd881f4a38ef3e5aaf3b0d48842ded5e6a16fc2fb7b5379406c2889e1d9de1fe611645310ba5b5048e817f44c451b5ec557c0e3b8e64049a437b82f901866ba4c1994d3c3caf02f81582f7409d10480df2c353eb63db4ec57671b2ac6c28fce842c605bae902ac5bb649f08199307458b542849d663809c9980a7c939b4f1f6d2eddf3dfe02f70ee4cf8956bf7a6a29a307939cd17eebdbcc80fb830bd545351a12c275375feaf3f690c52cc76dc7521ce87f621163b551a70e06d5bd3274bdc144f61f4ff8f1cdb2fcf97c67df1935057fdadaa23bf675892b4db841a63d49cd788c34498c70fb4ea787f3f8c1")
tx, err = CreateTx("EncryptStorage", &oty.EncryptNotaryStorage{ContentHash: common.Sha256(c1), EncryptContent: c1, Nonce: ivs[0]}, PrivKeyA, cfg)
assert.Nil(t, err)
Exec_Block(t, stateDB, kvdb, env, tx)
txhash = common.ToHex(tx.Hash())
reply, err = QueryStorageByKey(stateDB, kvdb, txhash, cfg)
assert.Nil(t, err)
assert.Equal(t, common.Sha256(c1), reply.GetEncryptStorage().ContentHash)
assert.Equal(t, c1, reply.GetEncryptStorage().EncryptContent)
tx, err = CreateTx("EncryptAdd", &oty.EncryptNotaryAdd{Key: txhash, EncryptAdd: c2}, PrivKeyA, cfg)
assert.Nil(t, err)
Exec_Block(t, stateDB, kvdb, env, tx)
reply, err = QueryStorageByKey(stateDB, kvdb, txhash, cfg)
assert.Nil(t, err)
assert.Equal(t, c3, reply.GetEncryptStorage().EncryptContent)
} }
func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) { func signTx(tx *types.Transaction, hexPrivKey string) (*types.Transaction, error) {
......
...@@ -3,6 +3,8 @@ package executor ...@@ -3,6 +3,8 @@ package executor
import ( import (
"fmt" "fmt"
"github.com/33cn/plugin/plugin/crypto/paillier"
"github.com/33cn/chain33/client" "github.com/33cn/chain33/client"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
...@@ -190,6 +192,47 @@ func (s *StorageAction) EncryptShareStorage(payload *ety.EncryptShareNotaryStora ...@@ -190,6 +192,47 @@ func (s *StorageAction) EncryptShareStorage(payload *ety.EncryptShareNotaryStora
return receipt, nil return receipt, nil
} }
//EncryptAdd ...
func (s *StorageAction) EncryptAdd(payload *ety.EncryptNotaryAdd) (*types.Receipt, error) {
var logs []*types.ReceiptLog
var kvs []*types.KeyValue
cfg := s.api.GetConfig()
store, err := QueryStorage(s.db, s.localdb, payload.Key)
if err != nil {
return nil, fmt.Errorf("EncryptAdd.QueryStorage. err:%v", err)
}
cipherText := store.GetEncryptStorage().EncryptContent
res, err := paillier.CiphertextAddBytes(cipherText, payload.EncryptAdd)
if err != nil {
return nil, fmt.Errorf("EncryptAdd.CiphertextAddBytes. err:%v", err)
}
store.GetEncryptStorage().EncryptContent = res
newStore := &ety.EncryptNotaryStorage{
ContentHash: store.GetEncryptStorage().ContentHash,
EncryptContent: res,
Nonce: store.GetEncryptStorage().Nonce,
Key: store.GetEncryptStorage().Key,
Value: store.GetEncryptStorage().Value,
}
if cfg.IsDappFork(s.height, ety.StorageX, ety.ForkStorageLocalDB) {
stg := &ety.Storage{Value: &ety.Storage_EncryptStorage{EncryptStorage: newStore}, Ty: ety.TyEncryptStorageAction}
log := &types.ReceiptLog{Ty: ety.TyEncryptAddLog, Log: types.Encode(stg)}
logs = append(logs, log)
} else {
log := &types.ReceiptLog{Ty: ety.TyEncryptAddLog}
logs = append(logs, log)
kvs = append(kvs, &types.KeyValue{Key: Key(payload.Key), Value: types.Encode(newStore)})
}
receipt := &types.Receipt{Ty: types.ExecOk, KV: kvs, Logs: logs}
return receipt, nil
}
//QueryStorageByTxHash ... //QueryStorageByTxHash ...
func QueryStorageByTxHash(db dbm.KV, txhash string) (*ety.Storage, error) { func QueryStorageByTxHash(db dbm.KV, txhash string) (*ety.Storage, error) {
data, err := db.Get(Key(txhash)) data, err := db.Get(Key(txhash))
......
...@@ -8,8 +8,9 @@ message Storage { ...@@ -8,8 +8,9 @@ message Storage {
LinkNotaryStorage linkStorage = 3; LinkNotaryStorage linkStorage = 3;
EncryptNotaryStorage encryptStorage = 4; EncryptNotaryStorage encryptStorage = 4;
EncryptShareNotaryStorage encryptShareStorage = 5; EncryptShareNotaryStorage encryptShareStorage = 5;
EncryptNotaryAdd encryptAdd = 6;
} }
int32 ty = 6; int32 ty = 7;
} }
message StorageAction { message StorageAction {
...@@ -19,8 +20,9 @@ message StorageAction { ...@@ -19,8 +20,9 @@ message StorageAction {
LinkNotaryStorage linkStorage = 3; LinkNotaryStorage linkStorage = 3;
EncryptNotaryStorage encryptStorage = 4; EncryptNotaryStorage encryptStorage = 4;
EncryptShareNotaryStorage encryptShareStorage = 5; EncryptShareNotaryStorage encryptShareStorage = 5;
EncryptNotaryAdd encryptAdd = 6;
} }
int32 ty = 6; int32 ty = 7;
} }
// 内容存证模型 // 内容存证模型
message ContentOnlyNotaryStorage { message ContentOnlyNotaryStorage {
...@@ -85,6 +87,14 @@ message EncryptShareNotaryStorage { ...@@ -85,6 +87,14 @@ message EncryptShareNotaryStorage {
string value = 5; string value = 5;
} }
// 加密存证数据运算
message EncryptNotaryAdd {
//源操作数存证索引
string key = 1;
//待操作数据
bytes encryptAdd = 2;
}
service storage {} service storage {}
//根据txhash去状态数据库中查询存储内容 //根据txhash去状态数据库中查询存储内容
message QueryStorage { message QueryStorage {
......
...@@ -2,7 +2,6 @@ package rpc ...@@ -2,7 +2,6 @@ package rpc
import ( import (
rpctypes "github.com/33cn/chain33/rpc/types" rpctypes "github.com/33cn/chain33/rpc/types"
storagetypes "github.com/33cn/plugin/plugin/dapp/storage/types"
) )
/* /*
...@@ -30,5 +29,5 @@ func Init(name string, s rpctypes.RPCServer) { ...@@ -30,5 +29,5 @@ func Init(name string, s rpctypes.RPCServer) {
grpc := &Grpc{channelClient: cli} grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc) cli.Init(name, s, &Jrpc{cli: cli}, grpc)
//存在grpc service时注册grpc server,需要生成对应的pb.go文件 //存在grpc service时注册grpc server,需要生成对应的pb.go文件
storagetypes.RegisterStorageServer(s.GRPC(), grpc) //storagetypes.RegisterStorageServer(s.GRPC(), grpc)
} }
...@@ -20,12 +20,14 @@ const ( ...@@ -20,12 +20,14 @@ const (
TyLinkStorageAction TyLinkStorageAction
TyEncryptStorageAction TyEncryptStorageAction
TyEncryptShareStorageAction TyEncryptShareStorageAction
TyEncryptAddAction
NameContentStorageAction = "ContentStorage" NameContentStorageAction = "ContentStorage"
NameHashStorageAction = "HashStorage" NameHashStorageAction = "HashStorage"
NameLinkStorageAction = "LinkStorage" NameLinkStorageAction = "LinkStorage"
NameEncryptStorageAction = "EncryptStorage" NameEncryptStorageAction = "EncryptStorage"
NameEncryptShareStorageAction = "EncryptShareStorage" NameEncryptShareStorageAction = "EncryptShareStorage"
NameEncryptAddAction = "EncryptAdd"
FuncNameQueryStorage = "QueryStorage" FuncNameQueryStorage = "QueryStorage"
FuncNameBatchQueryStorage = "BatchQueryStorage" FuncNameBatchQueryStorage = "BatchQueryStorage"
...@@ -39,6 +41,7 @@ const ( ...@@ -39,6 +41,7 @@ const (
TyLinkStorageLog TyLinkStorageLog
TyEncryptStorageLog TyEncryptStorageLog
TyEncryptShareStorageLog TyEncryptShareStorageLog
TyEncryptAddLog
) )
//storage op //storage op
...@@ -61,6 +64,7 @@ var ( ...@@ -61,6 +64,7 @@ var (
NameLinkStorageAction: TyLinkStorageAction, NameLinkStorageAction: TyLinkStorageAction,
NameEncryptStorageAction: TyEncryptStorageAction, NameEncryptStorageAction: TyEncryptStorageAction,
NameEncryptShareStorageAction: TyEncryptShareStorageAction, NameEncryptShareStorageAction: TyEncryptShareStorageAction,
NameEncryptAddAction: TyEncryptAddAction,
} }
//定义log的id和具体log类型及名称,填入具体自定义log类型 //定义log的id和具体log类型及名称,填入具体自定义log类型
logMap = map[int64]*types.LogInfo{ logMap = map[int64]*types.LogInfo{
...@@ -69,6 +73,7 @@ var ( ...@@ -69,6 +73,7 @@ var (
TyLinkStorageLog: {Ty: reflect.TypeOf(Storage{}), Name: "LogLinkStorage"}, TyLinkStorageLog: {Ty: reflect.TypeOf(Storage{}), Name: "LogLinkStorage"},
TyEncryptStorageLog: {Ty: reflect.TypeOf(Storage{}), Name: "LogEncryptStorage"}, TyEncryptStorageLog: {Ty: reflect.TypeOf(Storage{}), Name: "LogEncryptStorage"},
TyEncryptShareStorageLog: {Ty: reflect.TypeOf(Storage{}), Name: "LogEncryptShareStorage"}, TyEncryptShareStorageLog: {Ty: reflect.TypeOf(Storage{}), Name: "LogEncryptShareStorage"},
TyEncryptAddLog: {Ty: reflect.TypeOf(Storage{}), Name: "LogEncryptAdd"},
} }
) )
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment