Commit 38558bd2 authored by QM's avatar QM

Merge remote-tracking branch 'upstream/master' into issue999_autonomy_para_adjust

parents 419e010a 0670237f
...@@ -104,61 +104,3 @@ jobs: ...@@ -104,61 +104,3 @@ jobs:
run: | run: |
make docker-compose make docker-compose
make docker-compose-down make docker-compose-down
ci_relay:
name: ci_relay
runs-on: ubuntu-latest
steps:
- name: Set up Golang
uses: actions/setup-go@v2
with:
go-version: 1.15
id: go
- name: set go env
run: export PATH=${PATH}:`go env GOPATH`/bin
- name: checkout
uses: actions/checkout@v2
- name: deploy
run: |
make docker-compose dapp=relay
make docker-compose-down dapp=relay
ci_paracross:
name: ci_paracross
runs-on: ubuntu-latest
steps:
- name: Set up Golang
uses: actions/setup-go@v2
with:
go-version: 1.15
id: go
- name: set go env
run: export PATH=${PATH}:`go env GOPATH`/bin
- name: checkout
uses: actions/checkout@v2
- name: deploy
run: |
make docker-compose dapp=paracross
make docker-compose-down dapp=paracross
ci_cross2eth:
name: ci_cross2eth
runs-on: ubuntu-latest
steps:
- name: Set up Golang
uses: actions/setup-go@v2
with:
go-version: 1.15
id: go
- name: checkout
uses: actions/checkout@v2
- name: deploy
run: |
export GOPATH=$HOME/go
export PATH=${PATH}:`go env GOPATH`/bin
echo $GOPATH
make
make docker-compose dapp=cross2eth
make docker-compose-down dapp=cross2eth
name: build
on: [push,pull_request]
jobs:
ci_cross2eth:
name: ci_cross2eth
runs-on: ubuntu-latest
steps:
- name: Set up Golang
uses: actions/setup-go@v2
with:
go-version: 1.15
id: go
- name: checkout
uses: actions/checkout@v2
- name: deploy
run: |
export GOPATH=$HOME/go
export PATH=${PATH}:`go env GOPATH`/bin
echo $GOPATH
make
make docker-compose dapp=cross2eth
make docker-compose-down dapp=cross2eth
name: build
on: [push,pull_request]
jobs:
ci_mix:
name: ci_mix
runs-on: ubuntu-latest
steps:
- name: Set up Golang
uses: actions/setup-go@v2
with:
go-version: 1.15
id: go
- name: set go env
run: export PATH=${PATH}:`go env GOPATH`/bin
- name: checkout
uses: actions/checkout@v2
- name: download zk key file
run: |
pwd&&cd ./plugin/dapp/mix/cmd/
wget https://github.com/mdj33/gnark/blob/main/chain33key.tar.gz?raw=true -O chain33key.tar.gz
tar -xzvf chain33key.tar.gz
cp chain33key/* ./gnark/
cd -
- name: deploy
run: |
make docker-compose dapp=mix
make docker-compose-down dapp=mix
name: build
on: [push,pull_request]
jobs:
ci_paracross:
name: ci_paracross
runs-on: ubuntu-latest
steps:
- name: Set up Golang
uses: actions/setup-go@v2
with:
go-version: 1.15
id: go
- name: set go env
run: export PATH=${PATH}:`go env GOPATH`/bin
- name: checkout
uses: actions/checkout@v2
- name: deploy
run: |
make docker-compose dapp=paracross
make docker-compose-down dapp=paracross
name: build
on: [push,pull_request]
jobs:
ci_relay:
name: ci_relay
runs-on: ubuntu-latest
steps:
- name: Set up Golang
uses: actions/setup-go@v2
with:
go-version: 1.15
id: go
- name: set go env
run: export PATH=${PATH}:`go env GOPATH`/bin
- name: checkout
uses: actions/checkout@v2
- name: deploy
run: |
make docker-compose dapp=relay
make docker-compose-down dapp=relay
...@@ -24,7 +24,7 @@ pipeline { ...@@ -24,7 +24,7 @@ pipeline {
gitlabCommitStatus(name: 'deploy'){ gitlabCommitStatus(name: 'deploy'){
sh 'go version' sh 'go version'
sh 'make build_ci' sh 'make build_ci'
sh "cd build && mkdir ${env.BUILD_NUMBER} && cp ci/* ${env.BUILD_NUMBER} -r && ./docker-compose-pre.sh modify && cp chain33* Dockerfile* docker* *.sh ${env.BUILD_NUMBER}/ && cd ${env.BUILD_NUMBER}/ && rm -rf cross2eth && ./docker-compose-pre.sh run ${env.BUILD_NUMBER} all " sh "cd build && mkdir ${env.BUILD_NUMBER} && cp ci/* ${env.BUILD_NUMBER} -r && ./docker-compose-pre.sh modify && cp chain33* Dockerfile* docker* *.sh ${env.BUILD_NUMBER}/ && cd ${env.BUILD_NUMBER}/ && rm -rf cross2eth mix && ./docker-compose-pre.sh run ${env.BUILD_NUMBER} all "
} }
} }
} }
......
...@@ -47,11 +47,12 @@ function run_dapp() { ...@@ -47,11 +47,12 @@ function run_dapp() {
mv docker-compose-metrics.yml docker-compose-paracross.yml mv docker-compose-metrics.yml docker-compose-paracross.yml
app="paracross" app="paracross"
else else
rm -rf "${app}"-ci && mkdir -p "${app}"-ci && cp ./"${app}"/* ./"${app}"-ci && echo $? rm -rf "${app}"-ci && mkdir -p "${app}"-ci && cp -r ./"${app}"/* ./"${app}"-ci && echo $?
cp -n ./* ./"${app}"-ci/ && echo $? cp -n ./* ./"${app}"-ci/ && echo $?
if [ "$app" == "paracross" ]; then if [ "$app" == "paracross" ]; then
cp -r dapptest/ "${app}"-ci/ && echo $? cp -r dapptest/ "${app}"-ci/ && echo $?
fi fi
cd "${app}"-ci/ && pwd cd "${app}"-ci/ && pwd
fi fi
...@@ -100,7 +101,7 @@ function main() { ...@@ -100,7 +101,7 @@ function main() {
echo "============ run main end =================" echo "============ run main end ================="
find . -maxdepth 1 -type d -name "*-ci" -exec rm -rf {} \; find . -maxdepth 1 -type d -name "*-ci" -exec rm -rf {} \;
dir=$(find . -maxdepth 1 -type d ! -name system ! -name . ! -name cross2eth | sed 's/^\.\///') dir=$(find . -maxdepth 1 -type d ! -name system ! -name . | sed 's/^\.\///')
for app in $dir; do for app in $dir; do
run_single_app "${app}" "$TESTCASEFILE" "down" run_single_app "${app}" "$TESTCASEFILE" "down"
done done
...@@ -111,7 +112,7 @@ function main() { ...@@ -111,7 +112,7 @@ function main() {
fi fi
elif [ "${OP}" == "down" ]; then elif [ "${OP}" == "down" ]; then
if [ "${DAPP}" == "all" ] || [ "${DAPP}" == "ALL" ]; then if [ "${DAPP}" == "all" ] || [ "${DAPP}" == "ALL" ]; then
dir=$(find . -maxdepth 1 -type d ! -name system ! -name . ! -name cross2eth | sed 's/^\.\///') dir=$(find . -maxdepth 1 -type d ! -name system ! -name . | sed 's/^\.\///')
for app in $dir; do for app in $dir; do
down_dapp "${app}" down_dapp "${app}"
done done
......
...@@ -245,6 +245,7 @@ function miner() { ...@@ -245,6 +245,7 @@ function miner() {
fi fi
} }
function block_wait() { function block_wait() {
if [ "$#" -lt 2 ]; then if [ "$#" -lt 2 ]; then
echo "wrong block_wait params" echo "wrong block_wait params"
......
...@@ -72,6 +72,7 @@ grpcFuncWhitelist=["*"] ...@@ -72,6 +72,7 @@ grpcFuncWhitelist=["*"]
[mempool] [mempool]
name="para" name="para"
poolCacheSize=10240 poolCacheSize=10240
#联盟链没有交易费,对应平行链minTxFeeRate需要设为0
minTxFeeRate=100000 minTxFeeRate=100000
maxTxNumPerAccount=10000 maxTxNumPerAccount=10000
...@@ -118,11 +119,13 @@ writeBlockSeconds=2 ...@@ -118,11 +119,13 @@ writeBlockSeconds=2
authAccount="" authAccount=""
#创世地址额度 #创世地址额度
genesisAmount=100000000 genesisAmount=100000000
#主链计算blockhash forkheight,需要和主链保持严格一致,不可修改,209186是bityuan主链对应高度, ycc或其他按实际修改 #主链计算blockhash forkheight,需要和主链保持严格一致,不可修改,1是bityuan主链对应高度, ycc或其他按实际修改
mainBlockHashForkHeight=209186 mainBlockHashForkHeight=1
#主链支持平行链共识tx分叉高度,需要和主链保持严格一致,不可修改,2270000是bityuan主链对应高度, ycc或其他按实际修改 #主链支持平行链共识tx分叉高度,需要和主链保持严格一致,不可修改,2270000是bityuan主链对应高度, ycc或其他按实际修改
#不可为0,主链Local时候需特殊配置
mainForkParacrossCommitTx=2270000 mainForkParacrossCommitTx=2270000
#主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度, ycc或其他按实际修改 #主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度, ycc或其他按实际修改
#不可为0,主链Local时候需特殊配置
mainLoopCheckCommitTxDoneForkHeight=4320000 mainLoopCheckCommitTxDoneForkHeight=4320000
#无平行链交易的主链区块间隔,平行链产生一个空块,从高度0开始,配置[blockHeight:interval],比如["0:50","1000:100"] #无平行链交易的主链区块间隔,平行链产生一个空块,从高度0开始,配置[blockHeight:interval],比如["0:50","1000:100"]
emptyBlockInterval=["0:50"] emptyBlockInterval=["0:50"]
...@@ -199,6 +202,17 @@ useBalance=false ...@@ -199,6 +202,17 @@ useBalance=false
ethMapFromExecutor="paracross" ethMapFromExecutor="paracross"
ethMapFromSymbol="coins.bty" ethMapFromSymbol="coins.bty"
[exec.sub.mix]
#私对私的交易费,交易比较大,需要多的手续费
txFee=0
#私对私token转账,花费token(true)还是BTY(false),
tokenFee=false
#curve H point
pointHX="19172955941344617222923168298456110557655645809646772800021167670156933290312"
pointHY="21116962883761739586121793871108889864627195706475546685847911817475098399811"
#电路最大支持1024个叶子hash,10 level, 配置可以小于1024,但不能大于
maxTreeLeaves=1024
#系统中所有的fork,默认用chain33的测试网络的 #系统中所有的fork,默认用chain33的测试网络的
#但是我们可以替换 #但是我们可以替换
[fork.system] [fork.system]
...@@ -346,6 +360,9 @@ Enable=0 ...@@ -346,6 +360,9 @@ Enable=0
[fork.sub.multisig] [fork.sub.multisig]
Enable=0 Enable=0
[fork.sub.mix]
Enable=0
[fork.sub.unfreeze] [fork.sub.unfreeze]
Enable=0 Enable=0
ForkTerminatePart=0 ForkTerminatePart=0
......
...@@ -273,6 +273,10 @@ superManager=[ ...@@ -273,6 +273,10 @@ superManager=[
nodeGroupFrozenCoins=0 nodeGroupFrozenCoins=0
#平行链共识停止后主链等待的高度 #平行链共识停止后主链等待的高度
paraConsensusStopBlocks=30000 paraConsensusStopBlocks=30000
#配置平行链资产跨链交易的高度列表,title省略user.p,不同title使用,分割,不同hit高度使用"."分割,
#不同ignore范围高度使用"-"分割,hit高度在ignore范围内,为平行链自身的高度,不是主链高度
#para.hit.10.50.250, para.ignore.1-100.200-300
paraCrossAssetTxHeightList=[]
[exec.sub.autonomy] [exec.sub.autonomy]
total="16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp" total="16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp"
...@@ -285,6 +289,18 @@ evmGasLimit=2000000 ...@@ -285,6 +289,18 @@ evmGasLimit=2000000
#evm内部调试输出,指令级的,默认关闭,0:关闭;1:打开 #evm内部调试输出,指令级的,默认关闭,0:关闭;1:打开
evmDebugEnable=0 evmDebugEnable=0
[exec.sub.mix]
#私对私的交易费,交易比较大,需要多的手续费
txFee=100000000
#私对私token转账,花费token(true)还是BTY(false),
tokenFee=false
#curve H point
pointHX="19172955941344617222923168298456110557655645809646772800021167670156933290312"
pointHY="21116962883761739586121793871108889864627195706475546685847911817475098399811"
#电路最大支持1024个叶子hash,10 level, 配置可以小于1024,但不能大于
maxTreeLeaves=1024
[metrics] [metrics]
#是否使能发送metrics数据的发送 #是否使能发送metrics数据的发送
enableMetrics=false enableMetrics=false
......
...@@ -12,6 +12,8 @@ require ( ...@@ -12,6 +12,8 @@ require (
github.com/bitly/go-simplejson v0.5.0 github.com/bitly/go-simplejson v0.5.0
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/btcsuite/btcd v0.22.0-beta github.com/btcsuite/btcd v0.22.0-beta
github.com/consensys/gnark v0.5.0
github.com/consensys/gnark-crypto v0.5.0
github.com/coreos/etcd v3.3.15+incompatible github.com/coreos/etcd v3.3.15+incompatible
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1
......
...@@ -189,6 +189,11 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH ...@@ -189,6 +189,11 @@ github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWH
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/consensys/bavard v0.1.8-0.20210105233146-c16790d2aa8b/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ= github.com/consensys/bavard v0.1.8-0.20210105233146-c16790d2aa8b/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
github.com/consensys/bavard v0.1.8-0.20210806153619-fcffe4ffd871/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
github.com/consensys/gnark v0.5.0 h1:VZ4HR1vXTDaAQODkcI2KxTsbpIs7smIsLUFCd7xevO0=
github.com/consensys/gnark v0.5.0/go.mod h1:pjzjv55TTNbqcqnbMj7TgPZtFEZ0Q1obK33ZGpHS+Hs=
github.com/consensys/gnark-crypto v0.5.0 h1:c+1SOpCPKmw5lKth/hIoRgcw23KSgWnNR/b5M+JRC3k=
github.com/consensys/gnark-crypto v0.5.0/go.mod h1:wAZ9dsKCDVTSIy2KVTik+ZF16GUX9qp96mxFBDl9iAQ=
github.com/consensys/goff v0.3.10/go.mod h1:xTldOBEHmFiYS0gPXd3NsaEqZWlnmeWcRLWgD3ba3xc= github.com/consensys/goff v0.3.10/go.mod h1:xTldOBEHmFiYS0gPXd3NsaEqZWlnmeWcRLWgD3ba3xc=
github.com/consensys/gurvy v0.3.8/go.mod h1:sN75xnsiD593XnhbhvG2PkOy194pZBzqShWF/kwuW/g= github.com/consensys/gurvy v0.3.8/go.mod h1:sN75xnsiD593XnhbhvG2PkOy194pZBzqShWF/kwuW/g=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
...@@ -290,6 +295,8 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM ...@@ -290,6 +295,8 @@ github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fxamacker/cbor/v2 v2.2.0 h1:6eXqdDDe588rSYAi1HfZKbx6YYQO4mxQ9eC6xYpU/JQ=
github.com/fxamacker/cbor/v2 v2.2.0/go.mod h1:TA1xS00nchWmaBnEIxPSE5oHLuJBAVvqrtAnWBwBCVo=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
...@@ -1099,6 +1106,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE ...@@ -1099,6 +1106,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ= github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
...@@ -1298,6 +1306,8 @@ github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1: ...@@ -1298,6 +1306,8 @@ github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
...@@ -1586,6 +1596,7 @@ golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7w ...@@ -1586,6 +1596,7 @@ golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210317225723-c4fcb01b228e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426080607-c94f62235c83/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
......
...@@ -326,6 +326,7 @@ func validMainBlocks(txs *types.ParaTxDetails) *types.ParaTxDetails { ...@@ -326,6 +326,7 @@ func validMainBlocks(txs *types.ParaTxDetails) *types.ParaTxDetails {
return txs return txs
} }
//主链blockchain支持按过滤平行链交易后,此接口弃用
func (client *client) requestTxsFromBlock(currSeq int64, preMainBlockHash []byte) (*types.ParaTxDetails, error) { func (client *client) requestTxsFromBlock(currSeq int64, preMainBlockHash []byte) (*types.ParaTxDetails, error) {
cfg := client.GetAPI().GetConfig() cfg := client.GetAPI().GetConfig()
blockSeq, err := client.GetBlockOnMainBySeq(currSeq) blockSeq, err := client.GetBlockOnMainBySeq(currSeq)
......
...@@ -7,6 +7,8 @@ package commands ...@@ -7,6 +7,8 @@ package commands
import ( import (
"strings" "strings"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/33cn/chain33/common/address" "github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
) )
...@@ -23,7 +25,7 @@ func GetExecAddr(exec string) (string, error) { ...@@ -23,7 +25,7 @@ func GetExecAddr(exec string) (string, error) {
} }
func getRealExecName(paraName string, name string) string { func getRealExecName(paraName string, name string) string {
if strings.HasPrefix(name, "user.p.") { if strings.HasPrefix(name, pt.ParaPrefix) {
return name return name
} }
return paraName + name return paraName + name
......
...@@ -24,6 +24,7 @@ go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_D" -ldflags "-X ${SRC_EBCLI}/buildfl ...@@ -24,6 +24,7 @@ go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_D" -ldflags "-X ${SRC_EBCLI}/buildfl
# shellcheck disable=SC2086,1072 # shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/boss4x" "${SRC_BOSS4XCLI}" go build -i ${FLAG} -v -o "${OUT_DIR}/boss4x" "${SRC_BOSS4XCLI}"
cp ../../../../chain33.para.toml ./build/
cp ../ebrelayer/relayer.toml "${OUT_DIR}/relayer.toml" cp ../ebrelayer/relayer.toml "${OUT_DIR}/relayer.toml"
cp ./build/* "${OUT_DIR}" cp ./build/* "${OUT_DIR}"
cp ./build/abi/* "${OUT_DIR}" cp ./build/abi/* "${OUT_DIR}"
......
Title="user.p.para."
TestNet=false
CoinSymbol="para"
EnableParaFork=true
ChainID=0
[crypto]
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
loglevel = "debug"
logConsoleLevel = "info"
# 日志文件名,可带目录,所有生成的日志文件都放到此目录下
logFile = "logs/chain33.para.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="paradatadir"
dbCache=64
isStrongConsistency=true
singleMode=true
batchsync=false
#平行链钱包通过平行链区块seqence索引高度,缺省是true
isRecordBlockSequence=true
isParaChain = true
enableTxQuickIndex=true
# 升级storedb是否重新执行localdb,bityuan主链升级不需要开启,平行链升级需要开启
enableReExecLocal=true
# 使能精简localdb
enableReduceLocaldb=false
enablePushSubscribe=true
[p2p]
types=["dht"]
enable=false
driver="leveldb"
dbPath="paradatadir/addrbook"
dbCache=4
grpcLogFile="grpc33.log"
waitPid=true
[p2p.sub.dht]
DHTDataPath="paradatadir/p2pstore"
[rpc]
# 避免与主链配置冲突
jrpcBindAddr="localhost:8901"
grpcBindAddr="localhost:8902"
whitelist=["127.0.0.1"]
jrpcFuncWhitelist=["*"]
grpcFuncWhitelist=["*"]
[mempool]
name="para"
poolCacheSize=10240
minTxFeeRate=100000
maxTxNumPerAccount=10000
[consensus]
name="para"
genesisBlockTime=1514533390
genesis="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
minerExecs=["paracross"] #配置挖矿合约
[mver.consensus]
fundKeyAddr = "1BQXS6TxaYYG5mADaWij4AxhZZUTpw95a5"
powLimitBits = "0x1f00ffff"
maxTxNumber = 1600
[mver.consensus.paracross]
#超级节点挖矿奖励
coinReward=18
#发展基金奖励
coinDevFund=12
#如果超级节点上绑定了委托账户,则奖励超级节点coinBaseReward,其余部分(coinReward-coinBaseReward)按权重分给委托账户
coinBaseReward=3
#委托账户最少解绑定时间(按小时)
unBindTime=24
#支持挖矿奖励的1e8小数模式,比如18coin 需要配置成1800000000 以支持小数位后的配置,如果true,意味着已经打开即coinReward=1800000000
decimalMode=false
#挖矿模式, normal:缺省挖矿,其他自定义,注册名字需要和配置名字保持一致
minerMode="normal"
#挖矿减半周期,按高度减半
halvePeriod=1000
[consensus.sub.para]
#主链节点的grpc服务器ip,当前可以支持多ip负载均衡,如“118.31.177.1:8802,39.97.2.127:8802”
#ParaRemoteGrpcClient="118.31.177.1:8802,39.97.2.127:8802,120.77.111.44:8802,jiedian2.bityuan.com,cloud.bityuan.com"
ParaRemoteGrpcClient="localhost:8802"
#主链指定高度的区块开始同步
startHeight=345850
#打包时间间隔,单位秒
writeBlockSeconds=2
#验证账户,验证节点需要配置自己的账户,并且钱包导入对应种子,非验证节点留空
authAccount=""
#创世地址额度
genesisAmount=100000000
#主链计算blockhash forkheight,需要和主链保持严格一致,不可修改,209186是bityuan主链对应高度, ycc或其他按实际修改
mainBlockHashForkHeight=209186
#主链支持平行链共识tx分叉高度,需要和主链保持严格一致,不可修改,2270000是bityuan主链对应高度, ycc或其他按实际修改
mainForkParacrossCommitTx=2270000
#主链开启循环检查共识交易done的fork高度,需要和主链保持严格一致,不可修改,4320000是bityuan主链对应高度, ycc或其他按实际修改
mainLoopCheckCommitTxDoneForkHeight=4320000
#无平行链交易的主链区块间隔,平行链产生一个空块,从高度0开始,配置[blockHeight:interval],比如["0:50","1000:100"]
emptyBlockInterval=["0:50"]
[store]
name="kvmvccmavl"
driver="leveldb"
storedbVersion="2.0.0"
dbPath="paradatadir/mavltree"
dbCache=128
[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
# 该参数针对平行链,如果平行链的ForkKvmvccmavl高度不为0,需要开启此功能,开启此功能需要从0开始执行区块
enableEmptyBlockHandle=false
[wallet]
minFee=100000
driver="leveldb"
dbPath="parawallet"
dbCache=16
signType="secp256k1"
minerdisable=true
[exec]
enableStat=false
enableMVCC=false
[exec.sub.relay]
genesis="12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
[exec.sub.manage]
superManager=["12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"]
[exec.sub.token]
saveTokenTxList=true
tokenApprs=[]
[exec.sub.paracross]
#平行链自共识停止n个空块的对应主链高度后,超级账户可以直接参与投票,这个高度只在主链有效
paraConsensusStopBlocks=30000
[exec.sub.autonomy]
total="16htvcBNSEA7fZhAdLJphDwQRQJaHpyHTp"
useBalance=false
[exec.sub.evm]
#平行链evm合约ETH资产映射的合约和资产类型(symbol)
ethMapFromExecutor="paracross"
ethMapFromSymbol="coins.bty"
#系统中所有的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=7200000
[fork.sub.coins]
Enable=0
[fork.sub.coinsx]
Enable=0
[fork.sub.ticket]
Enable=0
ForkTicketId =0
ForkTicketVrf =0
[fork.sub.retrieve]
Enable=0
ForkRetrive=0
ForkRetriveAsset=0
[fork.sub.hashlock]
Enable=0
ForkBadRepeatSecret=0
[fork.sub.manage]
Enable=0
ForkManageExec=0
[fork.sub.token]
Enable=0
ForkTokenBlackList= 0
ForkBadTokenSymbol= 0
ForkTokenPrice=0
ForkTokenSymbolWithNumber=0
ForkTokenCheck= 0
[fork.sub.trade]
Enable=0
ForkTradeBuyLimit= 0
ForkTradeAsset= 0
ForkTradeID = 0
ForkTradeFixAssetDB = 0
ForkTradePrice = 0
[fork.sub.paracross]
Enable=0
ForkParacrossWithdrawFromParachain=0
ForkParacrossCommitTx=0
ForkLoopCheckCommitTxDone=0
#仅平行链适用,自共识分阶段开启,缺省是0,若对应主链高度7200000之前开启过自共识,需要重新配置此分叉,并为之前自共识设置selfConsensEnablePreContract配置项
ForkParaSelfConsStages=0
ForkParaAssetTransferRbk=0
#仅平行链适用,开启挖矿交易的高度,已有代码版本可能未在0高度开启挖矿,需要设置这个高度,新版本默认从0开启挖矿,通过交易配置分阶段奖励
ForkParaFullMinerHeight=0
[fork.sub.evm]
Enable=0
ForkEVMState=0
ForkEVMABI=0
ForkEVMFrozen=0
ForkEVMKVHash=0
ForkEVMYoloV1=0
ForkEVMTxGroup=0
[fork.sub.blackwhite]
Enable=0
ForkBlackWhiteV2=0
[fork.sub.cert]
Enable=0
[fork.sub.guess]
Enable=0
[fork.sub.lottery]
Enable=0
[fork.sub.oracle]
Enable=0
[fork.sub.relay]
Enable=0
[fork.sub.norm]
Enable=0
[fork.sub.pokerbull]
Enable=0
[fork.sub.privacy]
Enable=0
[fork.sub.game]
Enable=0
[fork.sub.vote]
Enable=0
[fork.sub.accountmanager]
Enable=0
[fork.sub.exchange]
Enable=0
[fork.sub.wasm]
Enable=0
[fork.sub.valnode]
Enable=0
[fork.sub.dpos]
Enable=0
[fork.sub.echo]
Enable=0
[fork.sub.storage]
Enable=0
ForkStorageLocalDB=0
[fork.sub.qbftNode]
Enable=0
[fork.sub.multisig]
Enable=0
[fork.sub.unfreeze]
Enable=0
ForkTerminatePart=0
ForkUnfreezeIDX= 0
[fork.sub.autonomy]
Enable=0
ForkAutonomyDelRule=0
[fork.sub.jsvm]
Enable=0
[fork.sub.issuance]
Enable=0
ForkIssuanceTableUpdate=0
[fork.sub.collateralize]
Enable=0
ForkCollateralizeTableUpdate=0
#对已有的平行链如果不是从0开始同步数据,需要设置这个kvmvccmavl的对应平行链高度的fork,如果从0开始同步,statehash会跟以前mavl的不同
[fork.sub.store-kvmvccmavl]
ForkKvmvccmavl=0
[pprof]
listenAddr = "localhost:6061"
[metrics]
#是否使能发送metrics数据的发送
enableMetrics=false
#数据保存模式
dataEmitMode="influxdb"
[metrics.sub.influxdb]
#以纳秒为单位的发送间隔
duration=1000000000
url="http://influxdb:8086"
database="chain33metrics"
username=""
password=""
namespace=""
...@@ -370,10 +370,9 @@ func (chain33Relayer *Relayer4Chain33) relayLockBurnToChain33(claim *ebTypes.Eth ...@@ -370,10 +370,9 @@ func (chain33Relayer *Relayer4Chain33) relayLockBurnToChain33(claim *ebTypes.Eth
} }
var tokenAddr string var tokenAddr string
operationType := "" operationType := events.ClaimType(claim.ClaimType).String()
if int32(events.ClaimTypeBurn) == claim.ClaimType { if int32(events.ClaimTypeBurn) == claim.ClaimType {
//burn 分支 //burn 分支
operationType = "Burn"
if ebTypes.SYMBOL_BTY == claim.Symbol { if ebTypes.SYMBOL_BTY == claim.Symbol {
tokenAddr = ebTypes.BTYAddrChain33 tokenAddr = ebTypes.BTYAddrChain33
} else { } else {
...@@ -385,7 +384,6 @@ func (chain33Relayer *Relayer4Chain33) relayLockBurnToChain33(claim *ebTypes.Eth ...@@ -385,7 +384,6 @@ func (chain33Relayer *Relayer4Chain33) relayLockBurnToChain33(claim *ebTypes.Eth
} }
} else { } else {
//lock 分支 //lock 分支
operationType = "Lock"
var exist bool var exist bool
tokenAddr, exist = chain33Relayer.symbol2Addr[claim.Symbol] tokenAddr, exist = chain33Relayer.symbol2Addr[claim.Symbol]
if !exist { if !exist {
......
...@@ -11,6 +11,8 @@ import ( ...@@ -11,6 +11,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/33cn/plugin/plugin/dapp/cross2eth/ebrelayer/relayer/events"
erc20 "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/erc20/generated" erc20 "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/erc20/generated"
btcec_secp256k1 "github.com/btcsuite/btcd/btcec" btcec_secp256k1 "github.com/btcsuite/btcd/btcec"
...@@ -77,9 +79,8 @@ func createEvmTx(privateKey chain33Crypto.PrivKey, action proto.Message, execer, ...@@ -77,9 +79,8 @@ func createEvmTx(privateKey chain33Crypto.PrivKey, action proto.Message, execer,
} }
func relayEvmTx2Chain33(privateKey chain33Crypto.PrivKey, claim *ebrelayerTypes.EthBridgeClaim, parameter, rpcURL, oracleAddr string) (string, error) { func relayEvmTx2Chain33(privateKey chain33Crypto.PrivKey, claim *ebrelayerTypes.EthBridgeClaim, parameter, rpcURL, oracleAddr string) (string, error) {
note := fmt.Sprintf("relayEvmTx2Chain33 by validator:%s with nonce:%d", note := fmt.Sprintf("relay with type:%s, chain33-receiver:%s, ethereum-sender:%s, symbol:%s, amout:%s, ethTxHash:%s",
address.PubKeyToAddr(privateKey.PubKey().Bytes()), events.ClaimType(claim.ClaimType).String(), claim.Chain33Receiver, claim.EthereumSender, claim.Symbol, claim.Amount, claim.EthTxHash)
claim.Nonce)
_, packData, err := evmAbi.Pack(parameter, generated.OracleABI, false) _, packData, err := evmAbi.Pack(parameter, generated.OracleABI, false)
if nil != err { if nil != err {
chain33txLog.Info("relayEvmTx2Chain33", "Failed to do abi.Pack due to:", err.Error()) chain33txLog.Info("relayEvmTx2Chain33", "Failed to do abi.Pack due to:", err.Error())
......
...@@ -473,9 +473,8 @@ func (ethRelayer *Relayer4Ethereum) handleChain33Msg(chain33Msg *events.Chain33M ...@@ -473,9 +473,8 @@ func (ethRelayer *Relayer4Ethereum) handleChain33Msg(chain33Msg *events.Chain33M
prophecyClaim := ethtxs.Chain33MsgToProphecyClaim(*chain33Msg) prophecyClaim := ethtxs.Chain33MsgToProphecyClaim(*chain33Msg)
var tokenAddr common.Address var tokenAddr common.Address
exist := false exist := false
operationType := "" operationType := chain33Msg.ClaimType.String()
if chain33Msg.ClaimType == events.ClaimTypeLock { if chain33Msg.ClaimType == events.ClaimTypeLock {
operationType = "lock"
tokenAddr, exist = ethRelayer.symbol2Addr[prophecyClaim.Symbol] tokenAddr, exist = ethRelayer.symbol2Addr[prophecyClaim.Symbol]
if !exist { if !exist {
relayerLog.Info("handleChain33Msg", "Query address from ethereum for symbol", prophecyClaim.Symbol) relayerLog.Info("handleChain33Msg", "Query address from ethereum for symbol", prophecyClaim.Symbol)
...@@ -497,7 +496,6 @@ func (ethRelayer *Relayer4Ethereum) handleChain33Msg(chain33Msg *events.Chain33M ...@@ -497,7 +496,6 @@ func (ethRelayer *Relayer4Ethereum) handleChain33Msg(chain33Msg *events.Chain33M
tokenAddr = common.HexToAddress(addr) tokenAddr = common.HexToAddress(addr)
} }
} else { } else {
operationType = "burn"
tokenAddr, exist = ethRelayer.symbol2LockAddr[prophecyClaim.Symbol] tokenAddr, exist = ethRelayer.symbol2LockAddr[prophecyClaim.Symbol]
if !exist { if !exist {
//因为是burn操作,必须从允许lock的token地址中进行查询 //因为是burn操作,必须从允许lock的token地址中进行查询
...@@ -665,7 +663,7 @@ func (ethRelayer *Relayer4Ethereum) procBridgeBankLogs(vLog types.Log) { ...@@ -665,7 +663,7 @@ func (ethRelayer *Relayer4Ethereum) procBridgeBankLogs(vLog types.Log) {
//lock,用于捕捉 (ETH/ERC20----->chain33) 跨链转移 //lock,用于捕捉 (ETH/ERC20----->chain33) 跨链转移
if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventLockSig { if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventLockSig {
eventName := events.LogLock.String() eventName := events.LogLockFromETH.String()
relayerLog.Info("Relayer4Ethereum proc", "Going to process", eventName, relayerLog.Info("Relayer4Ethereum proc", "Going to process", eventName,
"Block number:", vLog.BlockNumber, "Tx hash:", vLog.TxHash.Hex()) "Block number:", vLog.BlockNumber, "Tx hash:", vLog.TxHash.Hex())
err := ethRelayer.handleLogLockEvent(ethRelayer.clientChainID, ethRelayer.bridgeBankAbi, eventName, vLog) err := ethRelayer.handleLogLockEvent(ethRelayer.clientChainID, ethRelayer.bridgeBankAbi, eventName, vLog)
...@@ -676,7 +674,7 @@ func (ethRelayer *Relayer4Ethereum) procBridgeBankLogs(vLog types.Log) { ...@@ -676,7 +674,7 @@ func (ethRelayer *Relayer4Ethereum) procBridgeBankLogs(vLog types.Log) {
} }
} else if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventBurnSig { } else if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventBurnSig {
//burn,用于捕捉 (chain33 token----->chain33) 实现chain33资产withdraw操作,之后在chain33上实现unlock操作 //burn,用于捕捉 (chain33 token----->chain33) 实现chain33资产withdraw操作,之后在chain33上实现unlock操作
eventName := events.LogChain33TokenBurn.String() eventName := events.LogBurnFromETH.String()
relayerLog.Info("Relayer4Ethereum proc", "Going to process", eventName, relayerLog.Info("Relayer4Ethereum proc", "Going to process", eventName,
"Block number:", vLog.BlockNumber, "Tx hash:", vLog.TxHash.Hex()) "Block number:", vLog.BlockNumber, "Tx hash:", vLog.TxHash.Hex())
err := ethRelayer.handleLogBurnEvent(ethRelayer.clientChainID, ethRelayer.bridgeBankAbi, eventName, vLog) err := ethRelayer.handleLogBurnEvent(ethRelayer.clientChainID, ethRelayer.bridgeBankAbi, eventName, vLog)
...@@ -782,9 +780,9 @@ func (ethRelayer *Relayer4Ethereum) prePareSubscribeEvent() { ...@@ -782,9 +780,9 @@ func (ethRelayer *Relayer4Ethereum) prePareSubscribeEvent() {
//bridgeBank处理 //bridgeBank处理
contactAbi := ethtxs.LoadABI(ethtxs.BridgeBankABI) contactAbi := ethtxs.LoadABI(ethtxs.BridgeBankABI)
ethRelayer.bridgeBankAbi = contactAbi ethRelayer.bridgeBankAbi = contactAbi
eventName = events.LogLock.String() eventName = events.LogLockFromETH.String()
ethRelayer.bridgeBankEventLockSig = contactAbi.Events[eventName].ID.Hex() ethRelayer.bridgeBankEventLockSig = contactAbi.Events[eventName].ID.Hex()
eventName = events.LogChain33TokenBurn.String() eventName = events.LogBurnFromETH.String()
ethRelayer.bridgeBankEventBurnSig = contactAbi.Events[eventName].ID.Hex() ethRelayer.bridgeBankEventBurnSig = contactAbi.Events[eventName].ID.Hex()
ethRelayer.bridgeBankAddr = ethRelayer.x2EthDeployInfo.BridgeBank.Address ethRelayer.bridgeBankAddr = ethRelayer.x2EthDeployInfo.BridgeBank.Address
} }
......
...@@ -57,7 +57,6 @@ type BurnEventOnChain33 struct { ...@@ -57,7 +57,6 @@ type BurnEventOnChain33 struct {
Nonce *big.Int Nonce *big.Int
} }
// UnpackChain33LogLock UnpackLogLock : Handles new LogLock events
func UnpackChain33LogLock(contractAbi abi.ABI, eventName string, eventData []byte) (lockEvent *LockEventOnChain33, err error) { func UnpackChain33LogLock(contractAbi abi.ABI, eventName string, eventData []byte) (lockEvent *LockEventOnChain33, err error) {
lockEvent = &LockEventOnChain33{} lockEvent = &LockEventOnChain33{}
// Parse the event's attributes as Ethereum network variables // Parse the event's attributes as Ethereum network variables
......
...@@ -7,9 +7,10 @@ import ( ...@@ -7,9 +7,10 @@ import (
type ClaimType int32 type ClaimType int32
type Event int type Event int
var eventsLog = log.New("module", "ethereum_relayer") var eventsLog = log.New("module", "cross2eth_relayer")
const ( const (
ClaimTypeUnknown = ClaimType(0)
ClaimTypeBurn = ClaimType(1) ClaimTypeBurn = ClaimType(1)
ClaimTypeLock = ClaimType(2) ClaimTypeLock = ClaimType(2)
) )
...@@ -17,40 +18,17 @@ const ( ...@@ -17,40 +18,17 @@ const (
const ( const (
// Unsupported : unsupported Chain33 or Ethereum event // Unsupported : unsupported Chain33 or Ethereum event
Unsupported Event = iota Unsupported Event = iota
// MsgBurn : Chain33 event 'Chain33Msg' type MsgBurn // LogLockFromETH : Ethereum event 'LogLock'
MsgBurn LogLockFromETH
// MsgLock : Chain33 event 'Chain33Msg' type MsgLock // LogBurnFromETH : Ethereum event 'LogChain33TokenBurn'
MsgLock LogBurnFromETH
// LogLock : Ethereum event 'LockEvent'
LogLock
// LogChain33TokenBurn : Ethereum event 'LogChain33TokenBurn' in contract chain33Bank
LogChain33TokenBurn
// LogNewProphecyClaim : Ethereum event 'NewProphecyClaimEvent'
LogNewProphecyClaim
) )
// String : returns the event type as a string // 此处的名字命令不能随意改动,需要与合约event中的命名完全一致
func (d Event) String() string { func (d Event) String() string {
return [...]string{"unknown-x2ethereum", "Chain33ToEthBurn", "Chain33ToEthLock", "LogLock", "LogChain33TokenBurn", "LogNewProphecyClaim"}[d] return [...]string{"unknown-LOG", "LogLock", "LogChain33TokenBurn"}[d]
} }
// Chain33MsgAttributeKey : enum containing supported attribute keys func (d ClaimType) String() string {
type Chain33MsgAttributeKey int return [...]string{"unknown-LOG", "burn", "lock"}[d]
const (
// UnsupportedAttributeKey : unsupported attribute key
UnsupportedAttributeKey Chain33MsgAttributeKey = iota
// Chain33Sender : sender's address on Chain33 network
Chain33Sender
// EthereumReceiver : receiver's address on Ethereum network
EthereumReceiver
// Coin : coin type
Coin
// TokenContractAddress : coin's corresponding contract address deployed on the Ethereum network
TokenContractAddress
)
// String : returns the event type as a string
func (d Chain33MsgAttributeKey) String() string {
return [...]string{"unsupported", "chain33_sender", "ethereum_receiver", "amount", "token_contract_address"}[d]
} }
...@@ -6,7 +6,6 @@ import ( ...@@ -6,7 +6,6 @@ import (
"github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4eth/generated" "github.com/33cn/plugin/plugin/dapp/cross2eth/contracts/contracts4eth/generated"
"github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/accounts/abi"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
...@@ -14,7 +13,7 @@ func Test_UnpackLogLock(t *testing.T) { ...@@ -14,7 +13,7 @@ func Test_UnpackLogLock(t *testing.T) {
abiJSON := generated.BridgeBankABI abiJSON := generated.BridgeBankABI
contractABI, err := abi.JSON(strings.NewReader(abiJSON)) contractABI, err := abi.JSON(strings.NewReader(abiJSON))
require.Nil(t, err) require.Nil(t, err)
eventName := LogLock.String() eventName := LogLockFromETH.String()
eventData := []byte("nil") eventData := []byte("nil")
_, err = UnpackLogLock(contractABI, eventName, eventData) _, err = UnpackLogLock(contractABI, eventName, eventData)
...@@ -23,11 +22,3 @@ func Test_UnpackLogLock(t *testing.T) { ...@@ -23,11 +22,3 @@ func Test_UnpackLogLock(t *testing.T) {
_, err = UnpackLogBurn(contractABI, eventName, eventData) _, err = UnpackLogBurn(contractABI, eventName, eventData)
require.NotNil(t, err) require.NotNil(t, err)
} }
func Test_Chain33MsgAttributeKey(t *testing.T) {
assert.Equal(t, UnsupportedAttributeKey.String(), "unsupported")
assert.Equal(t, Chain33Sender.String(), "chain33_sender")
assert.Equal(t, EthereumReceiver.String(), "ethereum_receiver")
assert.Equal(t, Coin.String(), "amount")
assert.Equal(t, TokenContractAddress.String(), "token_contract_address")
}
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
_ "github.com/33cn/plugin/plugin/dapp/issuance" //auto gen _ "github.com/33cn/plugin/plugin/dapp/issuance" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/js" //auto gen _ "github.com/33cn/plugin/plugin/dapp/js" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/lottery" //auto gen _ "github.com/33cn/plugin/plugin/dapp/lottery" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/mix" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/multisig" //auto gen _ "github.com/33cn/plugin/plugin/dapp/multisig" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/norm" //auto gen _ "github.com/33cn/plugin/plugin/dapp/norm" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/oracle" //auto gen _ "github.com/33cn/plugin/plugin/dapp/oracle" //auto gen
......
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
\ No newline at end of file
#!/usr/bin/env bash
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
OUT_DIR="${1}/$strapp"
mkdir -p "${OUT_DIR}"/gnark
# shellcheck disable=SC2086
cp ./build/* "${OUT_DIR}"
cp -r ./gnark/* "${OUT_DIR}"/gnark
#OUT_TESTDIR="${1}/dapptest/$strapp"
#mkdir -p "${OUT_TESTDIR}"
#cp ./test/* "${OUT_TESTDIR}"
FROM ubuntu:16.04
WORKDIR /root
COPY chain33 chain33
COPY chain33-cli chain33-cli
COPY chain33.toml chain33*.toml ./
ADD gnark gnark/
CMD ["/root/chain33", "-f", "/root/chain33.toml"]
This diff is collapsed.
This diff is collapsed.
// 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 executor
import (
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
"github.com/golang/protobuf/proto"
token "github.com/33cn/plugin/plugin/dapp/token/types"
)
type action struct {
coinsAccount *account.DB
db dbm.KV
localdb dbm.KVDB
txhash []byte
fromaddr string
blocktime int64
height int64
execaddr string
api client.QueueProtocolAPI
tx *types.Transaction
exec *Mix
}
func newAction(t *Mix, tx *types.Transaction) *action {
hash := tx.Hash()
fromaddr := tx.From()
return &action{t.GetCoinsAccount(), t.GetStateDB(), t.GetLocalDB(), hash, fromaddr,
t.GetBlockTime(), t.GetHeight(), dapp.ExecAddress(string(tx.Execer)), t.GetAPI(), tx, t}
}
func createAccount(cfg *types.Chain33Config, execer, symbol string, db dbm.KV) (*account.DB, error) {
var accDB *account.DB
if symbol == "" {
accDB = account.NewCoinsAccount(cfg)
accDB.SetDB(db)
return accDB, nil
}
if execer == "" {
execer = token.TokenX
}
return account.NewAccountDB(cfg, execer, symbol, db)
}
func isNotFound(err error) bool {
if err != nil && (err == dbm.ErrNotFoundInDb || err == types.ErrNotFound) {
return true
}
return false
}
func mergeReceipt(receipt1, receipt2 *types.Receipt) *types.Receipt {
if receipt2 != nil {
receipt1.KV = append(receipt1.KV, receipt2.KV...)
receipt1.Logs = append(receipt1.Logs, receipt2.Logs...)
}
return receipt1
}
func makeReceipt(key []byte, logTy int32, data proto.Message) *types.Receipt {
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(data)},
},
Logs: []*types.ReceiptLog{
{Ty: logTy, Log: types.Encode(data)},
},
}
}
// 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 executor
import (
"github.com/consensys/gnark/frontend"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
func (a *action) authParamCheck(exec, symbol string, input *mixTy.AuthorizeCircuit) error {
//check tree rootHash exist
treeRootHash := frontend.FromInterface(frontend.GetAssignedValue(input.TreeRootHash))
exist, err := checkTreeRootHashExist(a.db, exec, symbol, mixTy.Str2Byte(treeRootHash.String()))
if err != nil {
return errors.Wrapf(err, "roothash=%s not found,exec=%s,symbol=%s", treeRootHash.String(), exec, symbol)
}
if !exist {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", treeRootHash.String())
}
//authorize key should not exist
authHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeHash))
authKey := calcAuthorizeHashKey(authHash.String())
_, err = a.db.Get(authKey)
if err == nil {
return errors.Wrapf(mixTy.ErrAuthorizeHashExist, "auth=%s", authHash.String())
}
if !isNotFound(err) {
return errors.Wrapf(err, "get auth=%s", authHash.String())
}
return nil
}
func (a *action) authorizePubInputs(exec, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.AuthorizeCircuit, error) {
var input mixTy.AuthorizeCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "setCircuitPubInput")
}
err = a.authParamCheck(exec, symbol, &input)
if err != nil {
return nil, err
}
return &input, nil
}
/*
1. verify(zk-proof)
2, check tree root hash exist
3, check authorize pubkey hash in config or not
4. check authorize hash if exist in authorize pool
5. set authorize hash and authorize_spend hash
*/
func (a *action) Authorize(authorize *mixTy.MixAuthorizeAction) (*types.Receipt, error) {
execer, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), authorize.AssetExec, authorize.AssetSymbol)
input, err := a.authorizePubInputs(execer, symbol, authorize.ProofInfo)
if err != nil {
return nil, err
}
//zk-proof校验
err = zkProofVerify(a.db, authorize.ProofInfo, mixTy.VerifyType_AUTHORIZE)
if err != nil {
return nil, err
}
receipt := &types.Receipt{Ty: types.ExecOk}
authNullHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeHash))
r := makeReceipt(calcAuthorizeHashKey(authNullHash.String()), mixTy.TyLogAuthorizeSet, &mixTy.ExistValue{Nullifier: authNullHash.String(), Exist: true})
mergeReceipt(receipt, r)
authSpendHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeSpendHash))
r = makeReceipt(calcAuthorizeSpendHashKey(authSpendHash.String()), mixTy.TyLogAuthorizeSpendSet, &mixTy.ExistValue{Nullifier: authSpendHash.String(), Exist: true})
mergeReceipt(receipt, r)
return receipt, nil
}
This diff is collapsed.
// 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 executor
import (
"testing"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/stretchr/testify/assert"
)
/*
leaf0 = "16308793397024662832064523892418908145900866571524124093537199035808550255649"
hash 4010939160279929375357088561050093294975728828994381439611270589357856115894
leaf1 = 21467822781369104390668289189963532506973289112396605437823854946060028754354
leaf hash 19846868408490658463513283235031798083935100648624648285566873440653365397815
leaf2= 4178471437305290899835614805415999986197321812505352791035422725360758750328
leaf hash 4062509694129705639089082212179777344962624935939361647381392834235969534831
leaf3= 10407830929890509544473717262275616077696950294748419792758056545898949331744
leaf hash 3656010751855274388516368747583374746848682779395325737100877017850943546836
leaf4= 11032604436245646157001636966356016502073301224837385665550497706958264582086
leaf hash 5949485921924623528448830799540295699445001672535082168235329176256394356669
merkleroot= 6988991286454436061784929049510388415076132311642532433013500389938249229356
0 proof str= 21467822781369104390668289189963532506973289112396605437823854946060028754354
1 proof str= 12096317366724227951683802305909172775715878134489527031786909074403605889217
2 proof str= 14541527209424185878803689752018034974129079647509824805270353433359922459228
3 proof str= 16581570556767364549626991605903512613557832602774591000372759906303762837296
*/
func TestGetProveData(t *testing.T) {
leaves := []string{
"16308793397024662832064523892418908145900866571524124093537199035808550255649",
"21467822781369104390668289189963532506973289112396605437823854946060028754354",
"4178471437305290899835614805415999986197321812505352791035422725360758750328",
"10407830929890509544473717262275616077696950294748419792758056545898949331744",
"11032604436245646157001636966356016502073301224837385665550497706958264582086",
}
proves := []string{
"21467822781369104390668289189963532506973289112396605437823854946060028754354",
"367337696696422936865919560478589243810446804477597373440139066420957868266",
"5538594811879266165080692952618163249542275094298127431082963485737222728396",
"143025316472030670451892215893941356364968202515180811944684799652132907215",
}
var leave [][]byte
for _, l := range leaves {
leave = append(leave, mixTy.Str2Byte(l))
}
ret, err := getProveData(leave[1], leave)
assert.Nil(t, err)
assert.Equal(t, uint32(5), ret.NumLeaves)
assert.Equal(t, uint32(1), ret.ProofIndex)
assert.Equal(t, "2857051084155588640772960772751117206153267452172716633910046945631762242957", ret.RootHash)
assert.Equal(t, len(proves), len(ret.ProofSet))
for i, k := range proves {
assert.Equal(t, k, ret.ProofSet[i])
}
assert.Equal(t, []uint32([]uint32{0, 1, 1}), ret.Helpers)
}
// 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 executor
import (
dbm "github.com/33cn/chain33/common/db"
manager "github.com/33cn/chain33/system/dapp/manage/types"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
// IsSuperManager is supper manager or not
func isSuperManager(cfg *types.Chain33Config, addr string) bool {
confManager := types.ConfSub(cfg, manager.ManageX)
for _, m := range confManager.GStrList("superManager") {
if addr == m {
return true
}
}
return false
}
// need super manager
func (a *action) Config(config *mixTy.MixConfigAction) (*types.Receipt, error) {
cfg := a.api.GetConfig()
switch config.Ty {
case mixTy.MixConfigType_Verify:
//必须是超级管理员才能配置
if !isSuperManager(cfg, a.fromaddr) {
return nil, errors.Wrapf(types.ErrNotAllow, "not super manager,%s", a.fromaddr)
}
return a.ConfigAddVerifyKey(config.GetVerifyKey())
case mixTy.MixConfigType_Auth:
//必须是超级管理员才能配置
if !isSuperManager(cfg, a.fromaddr) {
return nil, errors.Wrapf(types.ErrNotAllow, "not super manager,%s", a.fromaddr)
}
if config.Action == mixTy.MixConfigAct_Add {
return a.ConfigAddAuthPubKey(config.GetAuthKey())
} else {
return a.ConfigDeleteAuthPubKey(config.GetAuthKey())
}
case mixTy.MixConfigType_Payment:
//个人配置,个人负责,可重配
return a.ConfigPaymentPubKey(config.GetNoteAccountKey())
}
return nil, errors.Wrapf(types.ErrNotFound, "ty=%d", config.Ty)
}
func makeConfigVerifyKeyReceipt(data *mixTy.ZkVerifyKeys, ty int32) *types.Receipt {
key := getVerifyKeysKey(ty)
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(data)},
},
Logs: []*types.ReceiptLog{
{Ty: mixTy.TyLogMixConfigVk, Log: types.Encode(data)},
},
}
}
func getVerifyKeys(db dbm.KV, ty int32) (*mixTy.ZkVerifyKeys, error) {
key := getVerifyKeysKey(ty)
v, err := db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db verify key")
}
var keys mixTy.ZkVerifyKeys
err = types.Decode(v, &keys)
if err != nil {
return nil, errors.Wrapf(err, "decode db verify key")
}
return &keys, nil
}
func (a *action) ConfigAddVerifyKey(newKey *mixTy.ZkVerifyKey) (*types.Receipt, error) {
keys, err := getVerifyKeys(a.db, int32(newKey.Type))
if isNotFound(errors.Cause(err)) {
keys := &mixTy.ZkVerifyKeys{}
keys.Data = append(keys.Data, newKey)
return makeConfigVerifyKeyReceipt(keys, int32(newKey.Type)), nil
}
if err != nil {
return nil, errors.Wrapf(err, "AddVerifyKey,ty=%d", newKey.Type)
}
//逆序保存keys,保证新的key先遍历到
keys.Data = []*mixTy.ZkVerifyKey{newKey, keys.Data[0]}
return makeConfigVerifyKeyReceipt(keys, int32(newKey.Type)), nil
}
func makeConfigAuthKeyReceipt(data *mixTy.AuthKeys) *types.Receipt {
key := getAuthPubKeysKey()
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(data)},
},
Logs: []*types.ReceiptLog{
{Ty: mixTy.TyLogMixConfigAuth, Log: types.Encode(data)},
},
}
}
func (a *action) getAuthKeys() (*mixTy.AuthKeys, error) {
key := getAuthPubKeysKey()
v, err := a.db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db")
}
var keys mixTy.AuthKeys
err = types.Decode(v, &keys)
if err != nil {
return nil, errors.Wrapf(err, "decode db key")
}
return &keys, nil
}
func (a *action) ConfigAddAuthPubKey(key string) (*types.Receipt, error) {
keys, err := a.getAuthKeys()
if isNotFound(errors.Cause(err)) {
keys := &mixTy.AuthKeys{}
keys.Keys = append(keys.Keys, key)
return makeConfigAuthKeyReceipt(keys), nil
}
if err != nil {
return nil, err
}
keys.Keys = append(keys.Keys, key)
return makeConfigAuthKeyReceipt(keys), nil
}
func (a *action) ConfigDeleteAuthPubKey(key string) (*types.Receipt, error) {
keys, err := a.getAuthKeys()
if err != nil {
return nil, err
}
var newKeys mixTy.AuthKeys
for _, v := range keys.Keys {
if key == v {
continue
}
newKeys.Keys = append(newKeys.Keys, v)
}
return makeConfigAuthKeyReceipt(&newKeys), nil
}
func makeConfigPaymentKeyReceipt(data *mixTy.NoteAccountKey) *types.Receipt {
key := calcReceivingKey(data.Addr)
return &types.Receipt{
Ty: types.ExecOk,
KV: []*types.KeyValue{
{Key: key, Value: types.Encode(data)},
},
Logs: []*types.ReceiptLog{
{Ty: mixTy.TyLogMixConfigPaymentKey, Log: types.Encode(data)},
},
}
}
func GetPaymentPubKey(db dbm.KV, addr string) (*mixTy.NoteAccountKey, error) {
key := calcReceivingKey(addr)
v, err := db.Get(key)
if err != nil {
return nil, errors.Wrapf(err, "get db")
}
var keys mixTy.NoteAccountKey
err = types.Decode(v, &keys)
if err != nil {
return nil, errors.Wrapf(err, "decode db key")
}
return &keys, nil
}
func (a *action) ConfigPaymentPubKey(paykey *mixTy.NoteAccountKey) (*types.Receipt, error) {
if paykey == nil || len(paykey.NoteReceiveAddr) == 0 || len(paykey.SecretReceiveKey) == 0 || len(paykey.Addr) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "pubkey=%v", paykey)
}
//检查用户使用对应的addr的key,但不能确保key就是对应addr
if paykey.Addr != a.fromaddr {
return nil, errors.Wrapf(types.ErrInvalidParam, "register addr=%s not match with sign=%s", paykey.Addr, a.fromaddr)
}
//直接覆盖
return makeConfigPaymentKeyReceipt(&mixTy.NoteAccountKey{
Addr: a.fromaddr,
NoteReceiveAddr: paykey.NoteReceiveAddr,
SecretReceiveKey: paykey.SecretReceiveKey}), nil
}
// 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 executor
import (
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark/frontend"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
)
func makeNullifierSetReceipt(hash string, data proto.Message) *types.Receipt {
return makeReceipt(calcNullifierHashKey(hash), mixTy.TyLogNulliferSet, data)
}
func (a *action) depositVerify(proof *mixTy.ZkProofInfo) (*mixTy.DepositCircuit, error) {
var input mixTy.DepositCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "setCircuitPubInput")
}
err = zkProofVerify(a.db, proof, mixTy.VerifyType_DEPOSIT)
if err != nil {
return nil, errors.Wrapf(err, "verify fail for input=%s", proof.PublicInput)
}
return &input, nil
}
/*
1. verify zk-proof
2. verify commit value vs value
3. deposit to mix contract
4. add new commits to merkle tree
*/
func (a *action) Deposit(deposit *mixTy.MixDepositAction) (*types.Receipt, error) {
var notes []string
var sum uint64
//1. zk-proof校验
for _, p := range deposit.Proofs {
input, err := a.depositVerify(p)
if err != nil {
return nil, errors.Wrap(err, "get pub input")
}
v := frontend.FromInterface(frontend.GetAssignedValue(input.Amount))
sum += v.Uint64()
noteHash := frontend.FromInterface(frontend.GetAssignedValue(input.NoteHash))
notes = append(notes, noteHash.String())
}
//存款
cfg := a.api.GetConfig()
execer, symbol := mixTy.GetAssetExecSymbol(cfg, deposit.AssetExec, deposit.AssetSymbol)
accoutDb, err := createAccount(cfg, execer, symbol, a.db)
if err != nil {
return nil, errors.Wrapf(err, "createAccount,execer=%s,symbol=%s", execer, symbol)
}
//主链上存入toAddr为mix 执行器地址,平行链上为user.p.{}.mix执行器地址,execAddr和toAddr一致
execAddr := address.ExecAddress(string(a.tx.Execer))
receipt, err := accoutDb.ExecTransfer(a.fromaddr, execAddr, execAddr, int64(sum))
if err != nil {
return nil, errors.Wrapf(err, "account save to exec")
}
//push new commit to merkle tree
var leaves [][]byte
for _, n := range notes {
leaves = append(leaves, mixTy.Str2Byte(n))
}
conf := types.ConfSub(cfg, mixTy.MixX)
maxTreeLeaves := conf.GInt("maxTreeLeaves")
rpt, err := pushTree(a.db, execer, symbol, leaves, int32(maxTreeLeaves))
if err != nil {
return nil, errors.Wrap(err, "pushTree")
}
mergeReceipt(receipt, rpt)
return receipt, nil
}
// 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 executor
import (
"encoding/hex"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
//Exec_Commit consensus commit tx exec process
func (m *Mix) Exec_Config(payload *mixTy.MixConfigAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Config(payload)
if err != nil {
mlog.Error("mix config failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
//Exec_Deposit ...
func (m *Mix) Exec_Deposit(payload *mixTy.MixDepositAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Deposit(payload)
if err != nil {
mlog.Error("mix deposit failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
//Exec_Withdraw ...
func (m *Mix) Exec_Withdraw(payload *mixTy.MixWithdrawAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Withdraw(payload)
if err != nil {
mlog.Error("mix withdraw failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
func (m *Mix) Exec_Transfer(payload *mixTy.MixTransferAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Transfer(payload)
if err != nil {
mlog.Error("mix config failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
func (m *Mix) Exec_Authorize(payload *mixTy.MixAuthorizeAction, tx *types.Transaction, index int) (*types.Receipt, error) {
a := newAction(m, tx)
receipt, err := a.Authorize(payload)
if err != nil {
mlog.Error("mix config failed", "error", err, "hash", hex.EncodeToString(tx.Hash()))
return nil, err
}
return receipt, nil
}
// 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 executor
import (
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
//ExecLocal_Config asset withdraw local db process
func (m *Mix) ExecDelLocal_Config(payload *mixTy.MixConfigAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Deposit asset withdraw local db process
func (m *Mix) ExecDelLocal_Deposit(payload *mixTy.MixDepositAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoDelLocal(tx, receiptData)
}
//ExecLocal_Withdraw asset withdraw local db process
func (m *Mix) ExecDelLocal_Withdraw(payload *mixTy.MixWithdrawAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoDelLocal(tx, receiptData)
}
// ExecLocal_Transfer asset transfer local db process
func (m *Mix) ExecDelLocal_Transfer(payload *mixTy.MixTransferAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoDelLocal(tx, receiptData)
}
//ExecLocal_Authorize asset withdraw local db process
func (m *Mix) ExecDelLocal_Authorize(payload *mixTy.MixAuthorizeAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoDelLocal(tx, receiptData)
}
// 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 executor
import (
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
//ExecLocal_Config asset withdraw local db process
func (m *Mix) ExecLocal_Config(payload *mixTy.MixConfigAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return nil, nil
}
//ExecLocal_Deposit asset withdraw local db process
func (m *Mix) ExecLocal_Deposit(payload *mixTy.MixDepositAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoLocalMix(tx, receiptData, index)
}
//ExecLocal_Withdraw asset withdraw local db process
func (m *Mix) ExecLocal_Withdraw(payload *mixTy.MixWithdrawAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoLocalMix(tx, receiptData, index)
}
// ExecLocal_Transfer asset transfer local db process
func (m *Mix) ExecLocal_Transfer(payload *mixTy.MixTransferAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoLocalMix(tx, receiptData, index)
}
//ExecLocal_Authorize asset withdraw local db process
func (m *Mix) ExecLocal_Authorize(payload *mixTy.MixAuthorizeAction, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
return m.execAutoLocalMix(tx, receiptData, index)
}
// 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 executor
import (
"fmt"
)
var (
verifyKeys string
authPubKeys string
receivingKey string
commitTreeCurrentStatus string
commitTreeSubRoots string
commitTreeSubLeaves string
commitTreeArchiveRoots string
commitTreeRootLeaves string
authorizeHash string
authorizeSpendHash string
nullifierHash string
)
func setPrefix() {
verifyKeys = "mavl-mix-verify-keys-"
authPubKeys = "mavl-mix-auth-pubkeys-"
receivingKey = "mavl-mix-receiving-key-"
commitTreeCurrentStatus = "mavl-mix-commitTree-current-status-"
commitTreeSubRoots = "mavl-mix-commitTree-sub-roots-"
commitTreeSubLeaves = "mavl-mix-commitTree-sub-leaves-"
commitTreeRootLeaves = "mavl-mix-commitTree-root-Leaves-"
commitTreeArchiveRoots = "mavl-mix-commitTree-archive-roots-"
authorizeHash = "mavl-mix-authorizeHash"
authorizeSpendHash = "mavl-mix-authorizeSpendHash-"
nullifierHash = "mavl-mix-nullifierHash"
}
//support multi version verify parameter setting
func getVerifyKeysKey(ty int32) []byte {
return []byte(fmt.Sprintf(verifyKeys+"%d", ty))
}
func getAuthPubKeysKey() []byte {
return []byte(fmt.Sprintf(authPubKeys))
}
func calcReceivingKey(addr string) []byte {
return []byte(fmt.Sprintf(receivingKey+"%s", addr))
}
func calcCommitTreeCurrentStatusKey(exec, symbol string) []byte {
return []byte(fmt.Sprintf(commitTreeCurrentStatus+"%s-%s", exec, symbol))
}
func calcArchiveRootsKey(exec, symbol string, seq uint64) []byte {
return []byte(fmt.Sprintf(commitTreeArchiveRoots+"%s-%s-%022d", exec, symbol, seq))
}
func calcSubRootsKey(exec, symbol string, seq int32) []byte {
return []byte(fmt.Sprintf(commitTreeSubRoots+"%s-%s-%010d", exec, symbol, seq))
}
func calcSubLeavesKey(exec, symbol string, seq int32) []byte {
return []byte(fmt.Sprintf(commitTreeSubLeaves+"%s-%s-%010d", exec, symbol, seq))
}
func calcCommitTreeRootLeaves(exec, symbol string, rootHash string) []byte {
return []byte(fmt.Sprintf(commitTreeRootLeaves+"%s-%s-%s", exec, symbol, rootHash))
}
func calcAuthorizeHashKey(hash string) []byte {
return []byte(fmt.Sprintf(authorizeHash+"%s", hash))
}
func calcAuthorizeSpendHashKey(hash string) []byte {
return []byte(fmt.Sprintf(authorizeSpendHash+"%s", hash))
}
func calcNullifierHashKey(hash string) []byte {
return []byte(fmt.Sprintf(nullifierHash+"%s", hash))
}
// from https://gitlab.com/NebulousLabs/merkletree
package merkletree
import (
"errors"
"hash"
"io"
)
// ReadAll will read segments of size 'segmentSize' and push them into the tree
// until EOF is reached. Success will return 'err == nil', not 'err == EOF'. No
// padding is added to the data, so the last element may be smaller than
// 'segmentSize'.
func (t *Tree) ReadAll(r io.Reader, segmentSize int) error {
for {
segment := make([]byte, segmentSize)
n, readErr := io.ReadFull(r, segment)
if readErr == io.EOF {
// All data has been read.
break
} else if readErr == io.ErrUnexpectedEOF {
// This is the last segment, and there aren't enough bytes to fill
// the entire segment. Note that the next call will return io.EOF.
segment = segment[:n]
} else if readErr != nil {
return readErr
}
t.Push(segment)
}
return nil
}
// ReaderRoot returns the Merkle root of the data read from the reader, where
// each leaf is 'segmentSize' long and 'h' is used as the hashing function. All
// leaves will be 'segmentSize' bytes except the last leaf, which will not be
// padded out if there are not enough bytes remaining in the reader.
func ReaderRoot(r io.Reader, h hash.Hash, segmentSize int) (root []byte, err error) {
tree := New(h)
err = tree.ReadAll(r, segmentSize)
if err != nil {
return
}
root = tree.Root()
return
}
// BuildReaderProof returns a proof that certain data is in the merkle tree
// created by the data in the reader. The merkle root, set of proofs, and the
// number of leaves in the Merkle tree are all returned. All leaves will we
// 'segmentSize' bytes except the last leaf, which will not be padded out if
// there are not enough bytes remaining in the reader.
func BuildReaderProof(r io.Reader, h hash.Hash, segmentSize int, index uint64) (root []byte, proofSet [][]byte, numLeaves uint64, err error) {
tree := New(h)
err = tree.SetIndex(index)
if err != nil {
// This code should be unreachable - SetIndex will only return an error
// if the tree is not empty, and yet the tree should be empty at this
// point.
panic(err)
}
err = tree.ReadAll(r, segmentSize)
if err != nil {
return
}
root, proofSet, _, numLeaves = tree.Prove()
if len(proofSet) == 0 {
err = errors.New("index was not reached while creating proof")
return
}
return
}
This diff is collapsed.
// 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 merkletree
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc"
)
func TestLeafHash(t *testing.T) {
leaves := []string{
"16308793397024662832064523892418908145900866571524124093537199035808550255649",
}
h := mimc.NewMiMC("seed")
s := leafSum(h, mixTy.Str2Byte(leaves[0]))
assert.Equal(t, "4010939160279929375357088561050093294975728828994381439611270589357856115894", mixTy.Byte2Str(s))
leaves = []string{
"4062509694129705639089082212179777344962624935939361647381392834235969534831",
"3656010751855274388516368747583374746848682779395325737100877017850943546836",
}
h.Reset()
s = nodeSum(h, mixTy.Str2Byte(leaves[0]), mixTy.Str2Byte(leaves[1]))
assert.Equal(t, "19203142125680456902129919467753534834062383756119332074615431762320316227830", mixTy.Byte2Str(s))
proves := []string{
"21467822781369104390668289189963532506973289112396605437823854946060028754354",
"4010939160279929375357088561050093294975728828994381439611270589357856115894",
"19203142125680456902129919467753534834062383756119332074615431762320316227830",
"5949485921924623528448830799540295699445001672535082168235329176256394356669",
}
var sum []byte
for i, l := range proves {
if len(sum) == 0 {
sum = leafSum(h, mixTy.Str2Byte(l))
continue
}
//第0个leaf在第一个leaf的右侧,需要调整顺序
if i < 2 {
sum = nodeSum(h, mixTy.Str2Byte(l), sum)
continue
}
sum = nodeSum(h, sum, mixTy.Str2Byte(l))
}
fmt.Println("sum", mixTy.Byte2Str(sum))
}
// from https://gitlab.com/NebulousLabs/merkletree
package merkletree
import (
"bytes"
"hash"
)
// VerifyProof takes a Merkle root, a proofSet, and a proofIndex and returns
// true if the first element of the proof set is a leaf of data in the Merkle
// root. False is returned if the proof set or Merkle root is nil, and if
// 'numLeaves' equals 0.
func VerifyProof(h hash.Hash, merkleRoot []byte, proofSet [][]byte, proofIndex uint64, numLeaves uint64) bool {
// Return false for nonsense input. A switch statement is used so that the
// cover tool will reveal if a case is not covered by the test suite. This
// would not be possible using a single if statement due to the limitations
// of the cover tool.
if merkleRoot == nil {
return false
}
if proofIndex >= numLeaves {
return false
}
// In a Merkle tree, every node except the root node has a sibling.
// Combining the two siblings in the correct order will create the parent
// node. Each of the remaining hashes in the proof set is a sibling to a
// node that can be built from all of the previous elements of the proof
// set. The next node is built by taking:
//
// H(0x01 || sibling A || sibling B)
//
// The difficulty of the algorithm lies in determining whether the supplied
// hash is sibling A or sibling B. This information can be determined by
// using the proof index and the total number of leaves in the tree.
//
// A pair of two siblings forms a subtree. The subtree is complete if it
// has 1 << height total leaves. When the subtree is complete, the position
// of the proof index within the subtree can be determined by looking at
// the bounds of the subtree and determining if the proof index is in the
// first or second half of the subtree.
//
// When the subtree is not complete, either 1 or 0 of the remaining hashes
// will be sibling B. All remaining hashes after that will be sibling A.
// This is true because of the way that orphans are merged into the Merkle
// tree - an orphan at height n is elevated to height n + 1, and only
// hashed when it is no longer an orphan. Each subtree will therefore merge
// with at most 1 orphan to the right before becoming an orphan itself.
// Orphan nodes are always merged with larger subtrees to the left.
//
// One vulnerability with the proof verification is that the proofSet may
// not be long enough. Before looking at an element of proofSet, a check
// needs to be made that the element exists.
// The first element of the set is the original data. A sibling at height 1
// is created by getting the leafSum of the original data.
height := 0
if len(proofSet) <= height {
return false
}
sum := leafSum(h, proofSet[height])
height++
// While the current subtree (of height 'height') is complete, determine
// the position of the next sibling using the complete subtree algorithm.
// 'stableEnd' tells us the ending index of the last full subtree. It gets
// initialized to 'proofIndex' because the first full subtree was the
// subtree of height 1, created above (and had an ending index of
// 'proofIndex').
stableEnd := proofIndex
for {
// Determine if the subtree is complete. This is accomplished by
// rounding down the proofIndex to the nearest 1 << 'height', adding 1
// << 'height', and comparing the result to the number of leaves in the
// Merkle tree.
subTreeStartIndex := (proofIndex / (1 << uint(height))) * (1 << uint(height)) // round down to the nearest 1 << height
subTreeEndIndex := subTreeStartIndex + (1 << (uint(height))) - 1 // subtract 1 because the start index is inclusive
if subTreeEndIndex >= numLeaves {
// If the Merkle tree does not have a leaf at index
// 'subTreeEndIndex', then the subtree of the current height is not
// a complete subtree.
break
}
stableEnd = subTreeEndIndex
// Determine if the proofIndex is in the first or the second half of
// the subtree.
if len(proofSet) <= height {
return false
}
if proofIndex-subTreeStartIndex < 1<<uint(height-1) {
sum = nodeSum(h, sum, proofSet[height])
} else {
sum = nodeSum(h, proofSet[height], sum)
}
height++
}
// Determine if the next hash belongs to an orphan that was elevated. This
// is the case IFF 'stableEnd' (the last index of the largest full subtree)
// is equal to the number of leaves in the Merkle tree.
if stableEnd != numLeaves-1 {
if len(proofSet) <= height {
return false
}
sum = nodeSum(h, sum, proofSet[height])
height++
}
// All remaining elements in the proof set will belong to a left sibling.
for height < len(proofSet) {
sum = nodeSum(h, proofSet[height], sum)
height++
}
// Compare our calculated Merkle root to the desired Merkle root.
if bytes.Equal(sum, merkleRoot) {
return true
}
return false
}
// GenerateProofHelper generates an array of 1 or 0 telling if during the proof verification
// the hash to compute is h(sum, proof[i]) or h(proof[i], sum). The size of the resulting slice is
// len(proofSet)-1.
// cf gitlab.com/NebulousLabs/merkletree for the algorithm
func GenerateProofHelper(proofSet [][]byte, proofIndex, numLeaves uint64) []int {
res := make([]int, len(proofSet)-1)
height := 1
// While the current subtree (of height 'height') is complete, determine
// the position of the next sibling using the complete subtree algorithm.
// 'stableEnd' tells us the ending index of the last full subtree. It gets
// initialized to 'proofIndex' because the first full subtree was the
// subtree of height 1, created above (and had an ending index of
// 'proofIndex').
stableEnd := proofIndex
for {
// Determine if the subtree is complete. This is accomplished by
// rounding down the proofIndex to the nearest 1 << 'height', adding 1
// << 'height', and comparing the result to the number of leaves in the
// Merkle tree.
subTreeStartIndex := (proofIndex / (1 << uint(height))) * (1 << uint(height)) // round down to the nearest 1 << height
subTreeEndIndex := subTreeStartIndex + (1 << (uint(height))) - 1 // subtract 1 because the start index is inclusive
if subTreeEndIndex >= numLeaves {
// If the Merkle tree does not have a leaf at index
// 'subTreeEndIndex', then the subtree of the current height is not
// a complete subtree.
break
}
stableEnd = subTreeEndIndex
if proofIndex-subTreeStartIndex < 1<<uint(height-1) {
res[height-1] = 1
} else {
res[height-1] = 0
}
height++
}
// Determine if the next hash belongs to an orphan that was elevated. This
// is the case IFF 'stableEnd' (the last index of the largest full subtree)
// is equal to the number of leaves in the Merkle tree.
if stableEnd != numLeaves-1 {
res[height-1] = 1
height++
}
// All remaining elements in the proof set will belong to a left sibling.
for height < len(proofSet) {
res[height-1] = 0
height++
}
return res
}
// 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 executor
import (
"github.com/33cn/chain33/common"
log "github.com/33cn/chain33/common/log/log15"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
var (
mlog = log.New("module", "execs.mix")
driverName = mixTy.MixX
)
// Mix exec
type Mix struct {
drivers.DriverBase
}
//Init paracross exec register
func Init(name string, cfg *types.Chain33Config, sub []byte) {
drivers.Register(cfg, GetName(), newMix, cfg.GetDappFork(driverName, "Enable"))
InitExecType()
setPrefix()
}
//InitExecType ...
func InitExecType() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&Mix{}))
}
//GetName return paracross name
func GetName() string {
return newMix().GetName()
}
func newMix() drivers.Driver {
c := &Mix{}
c.SetChild(c)
c.SetExecutorType(types.LoadExecutorType(driverName))
return c
}
// GetDriverName return paracross driver name
func (m *Mix) GetDriverName() string {
return mixTy.MixX
}
// CheckTx check transaction
func (m *Mix) CheckTx(tx *types.Transaction, index int) error {
action := new(mixTy.MixAction)
if err := types.Decode(tx.Payload, action); err != nil {
mlog.Error("CheckTx decode", "err", err)
return err
}
if action.Ty != mixTy.MixActionTransfer {
// mix隐私交易,只私对私需要特殊签名验证
return m.DriverBase.CheckTx(tx, index)
}
_, _, err := MixTransferInfoVerify(m.GetAPI().GetConfig(), m.GetStateDB(), action.GetTransfer())
if err != nil {
mlog.Error("checkTx", "err", err, "txhash", common.ToHex(tx.Hash()))
return err
}
return nil
}
// 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 executor
import (
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
func (e *Mix) execAutoLocalMix(tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
if receiptData.Ty != types.ExecOk {
return nil, types.ErrInvalidParam
}
set, err := e.execLocalMix(tx, receiptData, index)
if err != nil {
return set, err
}
dbSet := &types.LocalDBSet{}
dbSet.KV = e.AddRollbackKV(tx, tx.Execer, set.KV)
return dbSet, nil
}
func (e *Mix) execLocalMix(tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
table := NewMixTxTable(e.GetLocalDB())
r := &mixTy.LocalMixTx{
Hash: common.ToHex(tx.Hash()),
Height: e.GetHeight(),
Index: int64(index),
}
err := table.Add(r)
if err != nil {
return nil, err
}
kvs, err := table.Save()
if err != nil {
return nil, err
}
dbSet := &types.LocalDBSet{}
dbSet.KV = append(dbSet.KV, kvs...)
return dbSet, nil
}
func (e *Mix) execAutoDelLocal(tx *types.Transaction, receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
kvs, err := e.DelRollbackKV(tx, tx.Execer)
if err != nil {
return nil, err
}
dbSet := &types.LocalDBSet{}
dbSet.KV = append(dbSet.KV, kvs...)
return dbSet, nil
}
func (e *Mix) listMixInfos(req *mixTy.MixTxListReq) (types.Message, error) {
if req == nil {
return nil, types.ErrInvalidParam
}
localDb := e.GetLocalDB()
query := NewMixTxTable(localDb).GetQuery(localDb)
var primary []byte
if len(req.TxIndex) > 0 {
primary = []byte(req.TxIndex)
}
cur := &MixTxRow{}
indexName := "height"
var prefix []byte
info := &mixTy.LocalMixTx{Height: req.Height, Index: req.Index}
if len(req.Hash) > 0 {
info.Hash = req.Hash
indexName = "hash"
var err error
prefix, err = cur.Get(indexName)
if err != nil {
mlog.Error("listMixInfos Get", "indexName", indexName, "err", err)
return nil, err
}
}
cur.SetPayload(info)
rows, err := query.ListIndex(indexName, prefix, primary, req.Count, req.Direction)
if err != nil {
mlog.Error("listMixInfos query failed", "indexName", indexName, "prefix", string(prefix), "key", string(primary), "err", err)
return nil, err
}
if len(rows) == 0 {
return nil, types.ErrNotFound
}
var rep mixTy.MixTxListResp
for _, row := range rows {
r, ok := row.Data.(*mixTy.LocalMixTx)
if !ok {
mlog.Error("listMixInfos", "err", "bad row type")
return nil, types.ErrDecode
}
rep.Txs = append(rep.Txs, r)
}
return &rep, nil
}
package executor
import (
"fmt"
"github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/table"
"github.com/33cn/chain33/types"
mix "github.com/33cn/plugin/plugin/dapp/mix/types"
)
/*
table struct
data: self consens stage
index: status
*/
var txBoardOpt = &table.Option{
Prefix: "LODB-mix",
Name: "tx",
Primary: "txIndex",
Index: []string{"height", "hash"},
}
//NewStageTable 新建表
func NewMixTxTable(kvdb db.KV) *table.Table {
rowmeta := NewMixTxRow()
table, err := table.NewTable(rowmeta, kvdb, txBoardOpt)
if err != nil {
panic(err)
}
return table
}
//MixRow table meta 结构
type MixTxRow struct {
*mix.LocalMixTx
}
//NewMixTxRow 新建一个meta 结构
func NewMixTxRow() *MixTxRow {
return &MixTxRow{LocalMixTx: &mix.LocalMixTx{}}
}
//CreateRow 新建数据行(注意index 数据一定也要保存到数据中,不能就保存heightindex)
func (r *MixTxRow) CreateRow() *table.Row {
return &table.Row{Data: &mix.LocalMixTx{}}
}
//SetPayload 设置数据
func (r *MixTxRow) SetPayload(data types.Message) error {
if d, ok := data.(*mix.LocalMixTx); ok {
r.LocalMixTx = d
return nil
}
return types.ErrTypeAsset
}
//Get 按照indexName 查询 indexValue
func (r *MixTxRow) Get(key string) ([]byte, error) {
switch key {
case "txIndex":
return []byte(dapp.HeightIndexStr(r.Height, r.Index)), nil
case "height":
return []byte(fmt.Sprintf("%022d", r.Height)), nil
case "hash":
return []byte(r.Hash), nil
default:
return nil, types.ErrNotFound
}
}
// 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 executor
import (
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
// Query_GetTreePath 根据leaf获取path 证明和roothash
func (m *Mix) Query_GetTreePath(in *mixTy.TreeInfoReq) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
return CalcTreeProve(m.GetStateDB(), in.AssetExec, in.AssetSymbol, in.RootHash, in.LeafHash)
}
// Query_GetTreeList query paracross title
func (m *Mix) Query_GetLeavesList(in *mixTy.TreeInfoReq) (types.Message, error) {
if in == nil {
return nil, types.ErrInvalidParam
}
var leaves *mixTy.CommitTreeLeaves
if len(in.RootHash) > 0 {
l, err := getCommitLeaves(m.GetStateDB(), calcCommitTreeRootLeaves(in.AssetExec, in.AssetSymbol, in.RootHash))
if err != nil {
return nil, err
}
leaves.Leaves = append(leaves.Leaves, l.Leaves...)
} else {
status, err := getCommitTreeStatus(m.GetStateDB(), in.AssetExec, in.AssetSymbol)
if err != nil {
return nil, err
}
for i := int32(1); i <= status.SubLeavesSeq; i++ {
l, err := getCommitLeaves(m.GetStateDB(), calcSubLeavesKey(in.AssetExec, in.AssetSymbol, i))
if err != nil {
return nil, errors.Wrapf(err, "get leaves of seq=%d", i)
}
leaves.Leaves = append(leaves.Leaves, l.Leaves...)
}
}
var resp mixTy.TreeListResp
for _, k := range leaves.Leaves {
resp.Leaves = append(resp.Leaves, mixTy.Byte2Str(k))
}
return &resp, nil
}
// Query_GetRootList query title
func (m *Mix) Query_GetRootList(in *mixTy.TreeInfoReq) (types.Message, error) {
var roots mixTy.CommitTreeRoots
if in.RootHeight > 0 {
r, err := getArchiveRoots(m.GetStateDB(), in.AssetExec, in.AssetSymbol, in.RootHeight)
if err != nil {
return nil, err
}
roots.Roots = append(roots.Roots, r.Roots...)
} else {
status, err := getCommitTreeStatus(m.GetStateDB(), in.AssetExec, in.AssetSymbol)
if err != nil {
return nil, err
}
for i := int32(1); i <= status.SubLeavesSeq; i++ {
r, err := getSubRoots(m.GetStateDB(), in.AssetExec, in.AssetSymbol, i)
if err != nil {
return nil, errors.Wrapf(err, "get roots of seq=%d", i)
}
roots.Roots = append(roots.Roots, r.Roots...)
}
}
var resp mixTy.RootListResp
for _, k := range roots.Roots {
resp.Roots = append(resp.Roots, mixTy.Byte2Str(k))
}
return &resp, nil
}
func (m *Mix) Query_GetTreeStatus(in *mixTy.TreeInfoReq) (types.Message, error) {
status, err := getCommitTreeStatus(m.GetStateDB(), in.AssetExec, in.AssetSymbol)
if err != nil {
return nil, err
}
var resp mixTy.TreeStatusResp
resp.SubLeavesSeq = status.SubLeavesSeq
resp.ArchiveRootsSeq = status.ArchiveRootsSeq
for _, h := range status.SubTrees.SubTrees {
resp.SubTrees = append(resp.SubTrees, &mixTy.SubTreeResp{Height: h.Height, Hash: mixTy.Byte2Str(h.Hash)})
}
return &resp, nil
}
// Query_ListMixTxs 批量查询
func (m *Mix) Query_ListMixTxs(in *mixTy.MixTxListReq) (types.Message, error) {
return m.listMixInfos(in)
}
// Query_PaymentPubKey 批量查询
func (m *Mix) Query_PaymentPubKey(addr *types.ReqString) (types.Message, error) {
return GetPaymentPubKey(m.GetStateDB(), addr.Data)
}
// Query_VerifyProof 批量查询
func (m *Mix) Query_VerifyProof(req *mixTy.VerifyProofInfo) (types.Message, error) {
return &types.ReqNil{}, zkProofVerify(m.GetStateDB(), req.Proof, req.Ty)
}
// Query_TokenFeeAddr 私对私token转账,代扣地址查询, 需预先转账主代币到相应资产地址下面才能完成私对私的转账,代扣地址coins不能提回
func (m *Mix) Query_TokenFeeAddr(req *mixTy.TokenTxFeeAddrReq) (types.Message, error) {
if req == nil || len(req.AssetExec) == 0 || len(req.AssetSymbol) == 0 {
return nil, errors.Wrapf(types.ErrInvalidParam, "asset exec or symbol not filled")
}
return &types.ReplyString{Data: address.ExecAddress(mixTy.MixX + req.AssetExec + req.AssetSymbol)}, nil
}
// 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 executor
import (
"github.com/consensys/gnark/frontend"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
dbm "github.com/33cn/chain33/common/db"
"github.com/pkg/errors"
)
/*
1. verify(zk-proof)
2. check if exist in authorize pool and nullifier pool
*/
func transferInput(cfg *types.Chain33Config, db dbm.KV, execer, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.TransferInputCircuit, error) {
var input mixTy.TransferInputCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
treeRootHash := frontend.FromInterface(frontend.GetAssignedValue(input.TreeRootHash))
nullifierHash := frontend.FromInterface(frontend.GetAssignedValue(input.NullifierHash))
authSpendHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeSpendHash))
err = spendVerify(db, execer, symbol, treeRootHash.String(), nullifierHash.String(), authSpendHash.String())
if err != nil {
return nil, errors.Wrap(err, "transferInput verify spendVerify")
}
//确保用户使用的和链配置的一致,不能私自篡改
conf := types.ConfSub(cfg, mixTy.MixX)
pointHX := conf.GStr("pointHX")
pointHY := conf.GStr("pointHY")
inputHX := frontend.FromInterface(frontend.GetAssignedValue(input.ShieldPointHX))
inputHY := frontend.FromInterface(frontend.GetAssignedValue(input.ShieldPointHY))
if pointHX != inputHX.String() || pointHY != inputHY.String() {
return nil, errors.Wrapf(types.ErrInvalidParam, "input circuit H point=%s-%s not match config", inputHX.String(), inputHY.String())
}
err = zkProofVerify(db, proof, mixTy.VerifyType_TRANSFERINPUT)
if err != nil {
return nil, errors.Wrap(err, "transferInput verify proof verify")
}
return &input, nil
}
/*
1. verify(zk-proof)
2. check if exist in authorize pool and nullifier pool
*/
func transferOutputVerify(cfg *types.Chain33Config, db dbm.KV, proof *mixTy.ZkProofInfo) (*mixTy.TransferOutputCircuit, error) {
var input mixTy.TransferOutputCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "decode string=%s", proof.PublicInput)
}
//确保用户使用的和链配置的一致,不能私自篡改
conf := types.ConfSub(cfg, mixTy.MixX)
pointHX := conf.GStr("pointHX")
pointHY := conf.GStr("pointHY")
inputHX := frontend.FromInterface(frontend.GetAssignedValue(input.ShieldPointHX))
inputHY := frontend.FromInterface(frontend.GetAssignedValue(input.ShieldPointHY))
if pointHX != inputHX.String() || pointHY != inputHY.String() {
return nil, errors.Wrapf(types.ErrInvalidParam, "output circuit H point=%s-%s not match config", inputHX.String(), inputHY.String())
}
err = zkProofVerify(db, proof, mixTy.VerifyType_TRANSFEROUTPUT)
if err != nil {
return nil, errors.Wrap(err, "Output verify proof verify")
}
return &input, nil
}
func VerifyCommitValues(inputs []*mixTy.TransferInputCircuit, outputs []*mixTy.TransferOutputCircuit, txFee uint64) bool {
var inputPoints, outputPoints []*twistededwards.PointAffine
for _, in := range inputs {
var p twistededwards.PointAffine
p.X.SetInterface(frontend.GetAssignedValue(in.ShieldAmountX))
p.Y.SetInterface(frontend.GetAssignedValue(in.ShieldAmountY))
inputPoints = append(inputPoints, &p)
}
for _, out := range outputs {
var p twistededwards.PointAffine
p.X.SetInterface(frontend.GetAssignedValue(out.ShieldAmountX))
p.Y.SetInterface(frontend.GetAssignedValue(out.ShieldAmountY))
outputPoints = append(outputPoints, &p)
}
//out value add fee
//对于平行链来说, 隐私交易需要一个公共账户扣主链的手续费,隐私交易只需要扣平行链执行器内的费用即可
//由于平行链的隐私交易没有实际扣平行链mix合约的手续费,平行链Mix合约会有手续费留下,平行链隐私可以考虑手续费为0
outputPoints = append(outputPoints, mixTy.MulCurvePointG(txFee))
//sum input and output
sumInput := inputPoints[0]
sumOutput := outputPoints[0]
for _, p := range inputPoints[1:] {
sumInput.Add(sumInput, p)
}
for _, p := range outputPoints[1:] {
sumOutput.Add(sumOutput, p)
}
if sumInput.X.Equal(&sumOutput.X) && sumInput.Y.Equal(&sumOutput.Y) {
return true
}
return false
}
func MixTransferInfoVerify(cfg *types.Chain33Config, db dbm.KV, transfer *mixTy.MixTransferAction) ([]*mixTy.TransferInputCircuit, []*mixTy.TransferOutputCircuit, error) {
var inputs []*mixTy.TransferInputCircuit
var outputs []*mixTy.TransferOutputCircuit
execer, symbol := mixTy.GetAssetExecSymbol(cfg, transfer.AssetExec, transfer.AssetSymbol)
txFee := mixTy.GetTransferTxFee(cfg, execer)
//inputs
for _, i := range transfer.Inputs {
in, err := transferInput(cfg, db, execer, symbol, i)
if err != nil {
return nil, nil, err
}
inputs = append(inputs, in)
}
//output
out, err := transferOutputVerify(cfg, db, transfer.Output)
if err != nil {
return nil, nil, err
}
outputs = append(outputs, out)
//change
change, err := transferOutputVerify(cfg, db, transfer.Change)
if err != nil {
return nil, nil, err
}
outputs = append(outputs, change)
if !VerifyCommitValues(inputs, outputs, uint64(txFee)) {
return nil, nil, errors.Wrap(mixTy.ErrSpendInOutValueNotMatch, "verify shieldValue")
}
return inputs, outputs, nil
}
//1. 如果
func (a *action) processTransferFee(exec, symbol string) (*types.Receipt, error) {
cfg := a.api.GetConfig()
accoutDb, err := createAccount(cfg, exec, symbol, a.db)
if err != nil {
return nil, err
}
txFee := mixTy.GetTransferTxFee(cfg, exec)
execAddr := address.ExecAddress(string(a.tx.Execer))
//需要mix执行器下的mix账户扣fee, 和mix 扣coins或token手续费保持一致,不然会看到mix的coins账户下和mix的mix账户下不一致
accFrom := accoutDb.LoadExecAccount(execAddr, execAddr)
if accFrom.GetBalance()-txFee >= 0 {
copyfrom := *accFrom
accFrom.Balance = accFrom.GetBalance() - txFee
receiptBalance := &types.ReceiptAccountTransfer{Prev: &copyfrom, Current: accFrom}
set := accoutDb.GetExecKVSet(execAddr, accFrom)
feelog := &types.ReceiptLog{Ty: types.TyLogFee, Log: types.Encode(receiptBalance)}
return &types.Receipt{
Ty: types.ExecOk,
KV: set,
Logs: append([]*types.ReceiptLog{}, feelog),
}, nil
}
return nil, types.ErrNoBalance
}
/*
1. verify(zk-proof, sum value of spend and new commits)
2. check if exist in authorize pool and nullifier pool
3. add nullifier to pool
*/
func (a *action) Transfer(transfer *mixTy.MixTransferAction) (*types.Receipt, error) {
inputs, outputs, err := MixTransferInfoVerify(a.api.GetConfig(), a.db, transfer)
if err != nil {
return nil, errors.Wrap(err, "Transfer.MixTransferInfoVerify")
}
receipt := &types.Receipt{Ty: types.ExecOk}
execer, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), transfer.AssetExec, transfer.AssetSymbol)
//扣除交易费
rTxFee, err := a.processTransferFee(execer, symbol)
if err != nil {
return nil, errors.Wrapf(err, "processTransferFee fail")
}
mergeReceipt(receipt, rTxFee)
for _, k := range inputs {
nullHash := frontend.FromInterface(frontend.GetAssignedValue(k.NullifierHash))
r := makeNullifierSetReceipt(nullHash.String(), &mixTy.ExistValue{Nullifier: nullHash.String(), Exist: true})
mergeReceipt(receipt, r)
}
//push new commit to merkle tree
var leaves [][]byte
for _, h := range outputs {
noteHash := frontend.FromInterface(frontend.GetAssignedValue(h.NoteHash))
leaves = append(leaves, mixTy.Str2Byte(noteHash.String()))
}
conf := types.ConfSub(a.api.GetConfig(), mixTy.MixX)
maxTreeLeaves := conf.GInt("maxTreeLeaves")
rpt, err := pushTree(a.db, execer, symbol, leaves, int32(maxTreeLeaves))
if err != nil {
return nil, errors.Wrap(err, "transfer.pushTree")
}
mergeReceipt(receipt, rpt)
return receipt, nil
}
// 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 executor
import (
"math/big"
"testing"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
"github.com/stretchr/testify/assert"
)
const (
baseHX = "19172955941344617222923168298456110557655645809646772800021167670156933290312"
baseHY = "21116962883761739586121793871108889864627195706475546685847911817475098399811"
fee = 100000
)
func TestVerifyCommitValuesBasePoint(t *testing.T) {
var in44, out10, out34 big.Int
//calc p1=44*G+100*G, p2=10*G+30*G,p3=34*G+70*G, p1=p2+p3+fee
in44.SetUint64(4400000)
out10.SetUint64(1000000)
out34.SetUint64(3400000 - fee)
ed := twistededwards.GetEdwardsCurve()
var p1, p2, p3 twistededwards.PointAffine
p1.ScalarMul(&ed.Base, &in44)
p2.ScalarMul(&ed.Base, &out10)
p3.ScalarMul(&ed.Base, &out34)
//t.Log("p1.x", p1.X.String())
//t.Log("p1.y", p1.Y.String())
//t.Log("p2.x", p2.X.String())
//t.Log("p2.y", p2.Y.String())
//t.Log("p3.x", p3.X.String())
//t.Log("p3.y", p3.Y.String())
var input1 mixTy.TransferInputCircuit
input1.ShieldAmountX.Assign(p1.X.String())
input1.ShieldAmountY.Assign(p1.Y.String())
var inputs []*mixTy.TransferInputCircuit
inputs = append(inputs, &input1)
var output1, output2 mixTy.TransferOutputCircuit
output1.ShieldAmountX.Assign(p2.X.String())
output1.ShieldAmountY.Assign(p2.Y.String())
output2.ShieldAmountX.Assign(p3.X.String())
output2.ShieldAmountY.Assign(p3.Y.String())
var outputs []*mixTy.TransferOutputCircuit
outputs = append(outputs, &output1)
outputs = append(outputs, &output2)
ret := VerifyCommitValues(inputs, outputs, fee)
assert.Equal(t, true, ret)
}
func TestVerifyCommitValuesBaseAddHPoint(t *testing.T) {
var in44, out10, out34 big.Int
in44.SetUint64(4400000)
out10.SetUint64(1000000)
out34.SetUint64(3400000 - fee)
//random value
var rIn100, rOut40, rOut60 big.Int
rIn100.SetUint64(10000000)
rOut40.SetUint64(3000000)
rOut60.SetUint64(7000000)
var baseH twistededwards.PointAffine
baseH.X.SetString(baseHX)
baseH.Y.SetString(baseHY)
ed := twistededwards.GetEdwardsCurve()
var p1, p2, p3, r1, r2, r3 twistededwards.PointAffine
p1.ScalarMul(&ed.Base, &in44)
p2.ScalarMul(&ed.Base, &out10)
p3.ScalarMul(&ed.Base, &out34)
r1.ScalarMul(&baseH, &rIn100)
r2.ScalarMul(&baseH, &rOut40)
r3.ScalarMul(&baseH, &rOut60)
p1.Add(&p1, &r1)
p2.Add(&p2, &r2)
p3.Add(&p3, &r3)
var input1 mixTy.TransferInputCircuit
input1.ShieldAmountX.Assign(p1.X.String())
input1.ShieldAmountY.Assign(p1.Y.String())
var inputs []*mixTy.TransferInputCircuit
inputs = append(inputs, &input1)
var output1, output2 mixTy.TransferOutputCircuit
output1.ShieldAmountX.Assign(p2.X.String())
output1.ShieldAmountY.Assign(p2.Y.String())
output2.ShieldAmountX.Assign(p3.X.String())
output2.ShieldAmountY.Assign(p3.Y.String())
var outputs []*mixTy.TransferOutputCircuit
outputs = append(outputs, &output1)
outputs = append(outputs, &output2)
ret := VerifyCommitValues(inputs, outputs, fee)
assert.Equal(t, true, ret)
}
// 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 executor
import (
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/plugin/plugin/dapp/mix/executor/zksnark"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
//考虑vk平滑切换的场景,允许有两个vk存在
func zkProofVerify(db dbm.KV, proof *mixTy.ZkProofInfo, ty mixTy.VerifyType) error {
keys, err := getVerifyKeys(db, int32(ty))
if err != nil {
return err
}
var pass bool
for _, verifyKey := range keys.Data {
ok, err := zksnark.Verify(verifyKey.Value, proof.Proof, proof.PublicInput)
if err != nil {
return err
}
if !ok {
continue
}
pass = true
break
}
if !pass {
return errors.Wrap(mixTy.ErrZkVerifyFail, "verify")
}
return nil
}
// 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 executor
import (
"github.com/33cn/chain33/common/address"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/consensys/gnark/frontend"
"github.com/pkg/errors"
)
func spendVerify(db dbm.KV, exec, symbol string, treeRootHash, nulliferHash, authorizeSpendHash string) error {
//zk-proof校验
//check tree rootHash exist
exist, err := checkTreeRootHashExist(db, exec, symbol, mixTy.Str2Byte(treeRootHash))
if err != nil {
return errors.Wrapf(err, "roothash=%s not found", treeRootHash)
}
if !exist {
return errors.Wrapf(mixTy.ErrTreeRootHashNotFound, "roothash=%s", treeRootHash)
}
//nullifier should not exist
nullifierKey := calcNullifierHashKey(nulliferHash)
_, err = db.Get(nullifierKey)
if err == nil {
return errors.Wrapf(mixTy.ErrNulliferHashExist, "nullifier=%s", nulliferHash)
}
if !isNotFound(err) {
return errors.Wrapf(err, "nullifier=%s", nulliferHash)
}
// authorize should exist if needed
if len(authorizeSpendHash) > 1 {
authKey := calcAuthorizeSpendHashKey(authorizeSpendHash)
_, err = db.Get(authKey)
if err != nil {
return errors.Wrapf(err, "authorize=%s", authorizeSpendHash)
}
}
return nil
}
func (a *action) withdrawVerify(exec, symbol string, proof *mixTy.ZkProofInfo) (*mixTy.WithdrawCircuit, error) {
var input mixTy.WithdrawCircuit
err := mixTy.ConstructCircuitPubInput(proof.PublicInput, &input)
if err != nil {
return nil, errors.Wrapf(err, "setCircuitPubInput")
}
treeRootHash := frontend.FromInterface(frontend.GetAssignedValue(input.TreeRootHash))
nullifierHash := frontend.FromInterface(frontend.GetAssignedValue(input.NullifierHash))
authSpendHash := frontend.FromInterface(frontend.GetAssignedValue(input.AuthorizeSpendHash))
err = spendVerify(a.db, exec, symbol, treeRootHash.String(), nullifierHash.String(), authSpendHash.String())
if err != nil {
return nil, err
}
err = zkProofVerify(a.db, proof, mixTy.VerifyType_WITHDRAW)
if err != nil {
return nil, err
}
return &input, nil
}
/*
1. verify(zk-proof, sum commit value)
2. withdraw from mix contract
3. set nullifier exist
*/
func (a *action) Withdraw(withdraw *mixTy.MixWithdrawAction) (*types.Receipt, error) {
exec, symbol := mixTy.GetAssetExecSymbol(a.api.GetConfig(), withdraw.AssetExec, withdraw.AssetSymbol)
var nulliferSet []string
var sumValue uint64
for _, k := range withdraw.Proofs {
input, err := a.withdrawVerify(exec, symbol, k)
if err != nil {
return nil, err
}
v := frontend.FromInterface(frontend.GetAssignedValue(input.Amount))
sumValue += v.Uint64()
nullHash := frontend.FromInterface(frontend.GetAssignedValue(input.NullifierHash))
nulliferSet = append(nulliferSet, nullHash.String())
}
if sumValue != withdraw.Amount {
return nil, errors.Wrapf(mixTy.ErrInputParaNotMatch, "amount:input=%d,proof sum=%d", withdraw.Amount, sumValue)
}
//withdraw value
cfg := a.api.GetConfig()
accoutDb, err := createAccount(cfg, exec, symbol, a.db)
if err != nil {
return nil, err
}
//主链上存入toAddr为mix 执行器地址,平行链上为user.p.{}.mix执行器地址,execAddr和toAddr一致
execAddr := address.ExecAddress(string(a.tx.Execer))
receipt, err := accoutDb.ExecTransfer(execAddr, a.fromaddr, execAddr, int64(withdraw.Amount))
if err != nil {
return nil, err
}
//set nullifier
for _, k := range nulliferSet {
r := makeNullifierSetReceipt(k, &mixTy.ExistValue{Nullifier: k, Exist: true})
mergeReceipt(receipt, r)
}
return receipt, nil
}
/*
Copyright © 2020 ConsenSys
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package zksnark
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend/groth16"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"github.com/pkg/errors"
)
func Verify(verifyKeyStr, proofStr, pubInputStr string) (bool, error) {
vkBuf, err := mixTy.GetByteBuff(verifyKeyStr)
if err != nil {
return false, errors.Wrapf(err, "zkVerify.vk.GetByteBuff")
}
vk := groth16.NewVerifyingKey(ecc.BN254)
if _, err := vk.ReadFrom(vkBuf); err != nil {
return false, errors.Wrapf(err, "zkVerify.read.vk=%s", verifyKeyStr[:10])
}
// load proof
proofBuf, err := mixTy.GetByteBuff(proofStr)
if err != nil {
return false, errors.Wrapf(err, "zkVerify.get.proof")
}
proof := groth16.NewProof(ecc.BN254)
if _, err = proof.ReadFrom(proofBuf); err != nil {
return false, errors.Wrapf(err, "zkVerify.read.proof=%s", proofStr[:10])
}
// decode pub input hex string
pubBuf, err := mixTy.GetByteBuff(pubInputStr)
if err != nil {
return false, errors.Wrapf(err, "zkVerify.pub.GetByteBuff")
}
// verify proof
//start := time.Now()
err = groth16.ReadAndVerify(proof, vk, pubBuf)
if err != nil {
return false, errors.Wrapf(err, "zkVerify.verify")
}
return true, nil
}
This diff is collapsed.
# mix执行器 基于零知识证明的混币隐私合约
## 场景
1. 存款,公转私,支持一次存入一个或多个目标账户,目标账户隐藏(自己或对方账户),转账金额公开(需要验证金额足够),生成未花费支票
1. 转账,私对私,花费某个支票,生成新支票即转账给目标账户,多出部分找零给自己,花费、目标和找零金额全隐藏
1. 提款,私对公,花费某些支票,统一转出给签名地址,转账金额公开(验证)
1. 授权,私对私,授权账户对某一请求其授权的转账支票授权,接收者或发送者都可看到支票在自己名下,但是锁定状态,
授权者授权接收者或者发送者为可花费用户,可花费用户才能花费此支票。
## 介绍
1. 任一希望接收支票的用户需要先注册支票接收账号和秘密加密公钥
1.1 支票账号分为接收key和花费key,花费key为用户链钱包账号私钥在c25519曲线上的公钥同时,花费key作为支票私钥,
计算hash值生成支票接收key。发送者使用对方的钱包地址即可检索其支票接收key,构建发送交易
1.2 为发送加密消息,接收者需要注册其加密公钥,发送者使用临时私钥和对方加密公钥生成密码,对消息对称加密
1. 支票有接收key,发送key,授权key,还有支票随机数等构成计算其hash,存到merkle树上。知道hash秘密数字的所有者
即可通过构建零知识证明,花费此支票。花费支票需要提供花费key,发送者虽然知道秘密数字也无法花费此支票。
1. 发送者用接收者的加密公钥和一次性临时私钥把支票私密数据进行加密,一次性临时公钥和秘密消息发送到链上,接收者可使用其加密私钥解密消息
1. 接收者需要使用加密私钥逐一检索尝试解密任一新的加密消息,解密成功即是发送给自己的加密消息
1. 对于需要授权的支票,发送者,授权者,接收者均可看到此支票,处于锁定状态,不能花费,只有授权者授权后,被授权方才可花费
// 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 paracross
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/mix/commands"
"github.com/33cn/plugin/plugin/dapp/mix/executor"
"github.com/33cn/plugin/plugin/dapp/mix/rpc"
"github.com/33cn/plugin/plugin/dapp/mix/types"
_ "github.com/33cn/plugin/plugin/dapp/mix/wallet" // register wallet package
)
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: types.MixX,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.MixCmd,
RPC: rpc.Init,
})
}
all:
sh ./create_protobuf.sh
#!/bin/sh
chain33_path=$(go list -f '{{.Dir}}' "github.com/33cn/chain33")
protoc --go_out=plugins=grpc:../types ./*.proto --proto_path=. --proto_path="${chain33_path}/types/proto/"
syntax = "proto3";
package types;
option go_package = "../types";
//DH one time pubkey with secret
message DHSecret{
string oneTimePubKey = 1;
string secret = 2;
}
//Diff-Helman 加密group, for spender, returner, authorizer to decrypt
message DHSecretGroup{
string receiver = 1;
string returner = 2;
string authorize = 3;
}
// note payment account
// receiveKey = hash(spendKey)
message NoteKeyPair {
string receiveKey = 1;
string spendKey = 2;
}
// diff-hellman crypto key pair
// secretPrivKey = wallet private key * G_25519
// secretPubKey = secretPrivKey * G_25519
message EncryptSecretKeyPair {
string secretPrivKey = 1;
string secretPubKey = 2;
}
//spend pair for note proof
//crypt pair for DH crypt/decrypt
message AccountPrivacyKey {
NoteKeyPair paymentKey = 1;
EncryptSecretKeyPair secretKey = 2;
}
message WalletAddrPrivacy {
AccountPrivacyKey privacy = 1;
string addr = 2;
}
message SecretData{
string receiverKey = 1;
string returnKey = 2;
string authorizeKey = 3;
string amount = 4;
string noteRandom = 5;
string assetExec = 6;
string assetSymbol = 7;
}
message EncryptSecretData{
string secret = 1;
string peerSecretPubKey = 2;
}
message DecryptSecretData{
string secret = 1;
string secretPriKey = 2;
string oneTimePubKey = 3;
}
syntax = "proto3";
package types;
option go_package = "../types";
//子树用高度和hash描述,2^10=1024个叶子节点,子树高度不会超过10
message CommitSubTree{
int32 height = 1;
bytes hash = 2;
}
//merkel tree由子树和叶子组成,三种场景:1,初始只一个叶子, 2,全是子树, 3,子树加一个叶子,不会有两个叶子,两个叶子一定构成子树
message CommitSubTrees{
repeated CommitSubTree subTrees = 1;
}
//描述当前commitTree的状态
//一颗merkel树1024叶子,考虑数据库读取原因,每个叶子都会存到相应seq db,待第1024次时候归档,重新开始新的merkle树,
message CommitTreeStatus{
CommitSubTrees subTrees = 1;
//1~1024叶子的归档
int32 subLeavesSeq = 2;
//root的归档 从1开始,数据库占位,不然全空会往前搜索
uint64 archiveRootsSeq = 3;
string assetExec = 4;
string assetSymbol = 5;
}
message ReceiptCommitTreeStatus{
CommitTreeStatus prev = 1;
CommitTreeStatus current = 2;
}
message ReceiptCommitSubLeaves{
int32 seq = 1;
string leaf = 2;
}
message ReceiptCommitSubRoots{
int32 seq = 1;
string root = 2;
}
message ReceiptArchiveLeaves{
int32 count = 1;
string rootHash = 2;
string lastLeaf = 3;
}
message ReceiptArchiveTreeRoot{
uint64 seq = 1;
string rootHash = 2;
}
message CommitTreeLeaves {
repeated bytes leaves = 1;
}
message CommitTreeRoots {
repeated bytes roots = 1;
}
message CommitTreeProve {
string rootHash = 1;
repeated string proofSet = 2;
uint32 proofIndex = 3;
uint32 numLeaves = 4;
repeated uint32 helpers = 5;
}
message TreeInfoReq{
string rootHash = 1;
string leafHash = 2;
string assetExec = 3;
string assetSymbol = 4;
uint64 rootHeight = 5;
}
message TreeListResp{
repeated string leaves = 1;
}
message RootListResp{
repeated string roots = 1;
}
message SubTreeResp{
int32 height = 1;
string hash = 2;
}
message TreeStatusResp{
int32 subLeavesSeq = 1;
uint64 archiveRootsSeq = 2;
repeated SubTreeResp subTrees = 3;
}
message TreePathProof{
string treeRootHash = 1;
repeated string treePath = 2;
repeated uint32 helpers = 3;
}
syntax = "proto3";
import "cryptokey.proto";
package types;
option go_package = "../types";
//区分不同的验证电路
enum VerifyType{
DEPOSIT = 0;
WITHDRAW = 1;
TRANSFERINPUT = 2;
TRANSFEROUTPUT = 3;
AUTHORIZE = 4;
}
message ZkVerifyKey {
VerifyType type = 1;
string value = 2;
}
message ZkVerifyKeys{
repeated ZkVerifyKey data = 1;
}
message AuthKeys{
repeated string keys = 1;
}
message NoteAccountKey{
//链上地址
string addr = 1;
//支票收款地址
string noteReceiveAddr = 2;
//note秘密信息接收key
string secretReceiveKey = 3;
}
message TokenTxFeeAddrReq{
string assetExec = 1;
string assetSymbol = 2;
}
enum MixConfigType{
Verify = 0;
//register unify authorize pubkey
Auth = 1;
//for spender's pay pubkey register,DH secret
//spender注册自己的payment公钥, 用来生成DiffHellman秘钥
Payment = 2;
}
enum MixConfigAct{
Add = 0;
Delete = 1;
}
//config verify parameter for proof
//当前authPk=mimc_hash(prikey),没有X,Y值
message MixConfigAction {
MixConfigType Ty = 1;
MixConfigAct Action = 2;
oneof value {
ZkVerifyKey verifyKey = 3;
string authKey = 4;
NoteAccountKey noteAccountKey = 5;
}
}
message ZkProofInfo {
string proof = 1;
string publicInput = 2;
DHSecretGroup secrets = 3;
}
message MixDepositAction {
string assetExec = 1;
string assetSymbol = 2;
repeated ZkProofInfo proofs = 3;
}
message MixTransferAction {
string assetExec = 1;
string assetSymbol = 2;
repeated ZkProofInfo inputs = 3;
ZkProofInfo output = 4;
ZkProofInfo change = 5;
}
message MixWithdrawAction {
string assetExec = 1;
string assetSymbol = 2;
uint64 amount = 3;
repeated ZkProofInfo proofs = 4;
}
message MixAuthorizeAction {
string assetExec = 1;
string assetSymbol = 2;
ZkProofInfo proofInfo = 3;
}
message MixAction {
int32 ty = 1;
oneof value {
MixConfigAction config = 2;
MixDepositAction deposit = 3;
MixWithdrawAction withdraw = 4;
MixTransferAction transfer = 5;
MixAuthorizeAction authorize = 6;
}
}
message VerifyProofInfo{
VerifyType ty = 1;
ZkProofInfo proof = 2;
}
//nullifer 存在value
message ExistValue {
string nullifier = 1;
bool exist = 2;
}
///////localdb index query
message LocalMixTx {
string hash = 1;
int64 height = 2;
int64 index = 3;
}
message MixTxListReq{
string txIndex = 1; //primary direct query
string hash = 2;
int64 height = 3;
int64 index = 4;
int32 count =5;
int32 direction = 6;
}
message MixTxListResp{
repeated LocalMixTx txs = 1;
}
syntax = "proto3";
import "common.proto";
import "transaction.proto";
import "cryptokey.proto";
package types;
option go_package = "../types";
//支持同时存入多个地址,多个地址具有相同的returnAddr和AuthorizeAddr,如果不同,则单个来存
message DepositInfo{
string receiverAddrs = 1;
string returnAddr = 2;
string authorizeAddr = 3;
string amounts = 4;
}
//钱包生成deposit tx
message DepositTxReq{
DepositInfo deposit = 1;
string zkPath = 2;
}
message DepositProofResp{
string noteHash = 1;
SecretData proof = 2;
DHSecretGroup secrets = 3;
}
//可withdraw 多个note
message WithdrawTxReq{
uint64 totalAmount = 1;
string noteHashs = 2; // seperate by ","
string zkPath = 3;
}
//只授权一个note,超过一个,toAddr不好设置
message AuthTxReq{
string noteHash = 1;
string authorizeToAddr = 2;
string zkPath = 3;
}
message TransferInputTxReq{
string noteHashs = 1;
}
message TransferOutputTxReq{
DepositInfo deposit = 1;
}
message TransferTxReq{
TransferInputTxReq input = 1;
TransferOutputTxReq output = 2;
string zkPath = 3;
}
message CreateZkKeyFileReq{
int32 ty = 1;
string savePath = 2;
}
//加密了的input/output amount
message ShieldAmount{
string X = 1;
string Y = 2;
}
message ShieldAmountRst{
repeated string inputRandoms = 1;
string outputRandom = 2;
string changeRandom = 3;
repeated ShieldAmount inputs = 4;
ShieldAmount output = 5;
ShieldAmount change = 6;
}
message CreateRawTxReq{
int32 actionTy = 1;
bytes data = 4;
string assetExec = 2;
string assetSymbol = 3;
string title = 6; //平行链名字
bool verifyOnChain = 7; //true:链上验证,false:本地验证
}
message PaymentKeysReq{
string privKey = 1; //user wallet priv key
string addr = 2; //user addr
bool detail = 3; //获取私钥信息
}
enum NoteStatus{
UNDEF = 0;
VALID = 1; //已授权可使用 相对消费者
USED = 2; //已使用
FROZEN = 3; //未授权
UNFROZEN = 4; //已授权 相对授权者
}
message WalletNoteInfo {
string noteHash = 1;
string nullifier = 2;
string authorizeSpendHash = 3;
string authorizeHash = 4;
string account = 5; //账户地址
NoteStatus status = 6;
SecretData secret = 7;
}
message WalletDbMixInfo {
WalletNoteInfo info = 1;
string txIndex = 2;
}
message WalletMixIndexReq {
string noteHash = 1;
string nullifier = 2;
string authorizeSpendHash = 3;
string authorizeHash = 4;
string account = 5;
int32 status = 6;
int32 count = 7;
int32 direction = 8;
}
message WalletNoteResp {
repeated WalletNoteInfo notes = 1;
}
message WalletEnablePrivacyRst{
string addr = 1;
bool isOK = 2;
string msg = 3;
}
message WalletEnablePrivacyResp{
repeated WalletEnablePrivacyRst resps = 1;
}
enum MixWalletRescanStatus{
IDLE = 0;
SCANNING = 1;
FINISHED = 2;
}
message PrivacyAddrResult{
string addr = 1;
bool isOK = 2;
string msg = 3;
}
message ReqEnablePrivacyRst{
repeated PrivacyAddrResult results = 1;
}
service mixPrivacy {
// 扫描UTXO以及获取扫描UTXO后的状态
rpc GetRescanStatus(ReqNil) returns (ReqString) {}
// 使能隐私账户
rpc RescanNotes(ReqNil) returns (ReqString) {}
// 创建隐私交易
rpc EnablePrivacy(ReqAddrs) returns (ReqEnablePrivacyRst) {}
}
\ No newline at end of file
// 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 rpc
import (
"encoding/hex"
"encoding/json"
"github.com/33cn/chain33/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
"golang.org/x/net/context"
)
// 显示指定地址的公钥对信息,可以作为后续交易参数
//func (g *channelClient) ShowPrivacyKey(ctx context.Context, in *types.ReqString) (*mixTy.AccountPrivacyKey, error) {
// data, err := g.ExecWalletFunc(mixTy.MixX, "ShowPrivacyKey", in)
// if err != nil {
// return nil, err
// }
// return data.(*mixTy.AccountPrivacyKey), nil
//}
func (g *channelClient) GetRescanStatus(ctx context.Context, in *types.ReqNil) (*types.ReqString, error) {
data, err := g.ExecWalletFunc(mixTy.MixX, "GetRescanStatus", in)
if err != nil {
return nil, err
}
return data.(*types.ReqString), nil
}
//
//// 扫描UTXO以及获取扫描UTXO后的状态
func (g *channelClient) RescanNotes(ctx context.Context, in *types.ReqNil) (*types.ReqString, error) {
data, err := g.ExecWalletFunc(mixTy.MixX, "RescanNotes", in)
if err != nil {
return nil, err
}
return data.(*types.ReqString), nil
}
// 使能隐私账户
func (g *channelClient) EnablePrivacy(ctx context.Context, in *types.ReqAddrs) (*mixTy.ReqEnablePrivacyRst, error) {
data, err := g.ExecWalletFunc(mixTy.MixX, "EnablePrivacy", in)
if err != nil {
return nil, err
}
return data.(*mixTy.ReqEnablePrivacyRst), nil
}
// ShowPrivacyAccountInfo display privacy account information for json rpc
func (c *Jrpc) ShowAccountPrivacyInfo(in *mixTy.PaymentKeysReq, result *json.RawMessage) error {
reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "ShowAccountPrivacyInfo", in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
/////////////////privacy///////////////
// ShowPrivacyAccountSpend display spend privacy account for json rpc
func (c *Jrpc) ShowAccountNoteInfo(in *mixTy.WalletMixIndexReq, result *json.RawMessage) error {
if in == nil {
return types.ErrInvalidParam
}
reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "ShowAccountNoteInfo", in)
if err != nil {
log.Error("ShowAccountNoteInfo", "return err info", err)
return err
}
*result, err = types.PBToJSON(reply)
return err
}
func (c *Jrpc) GetRescanStatus(in *types.ReqNil, result *json.RawMessage) error {
reply, err := c.cli.GetRescanStatus(context.Background(), in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
// RescanUtxos rescan utxosl for json rpc
func (c *Jrpc) RescanNotes(in *types.ReqNil, result *json.RawMessage) error {
reply, err := c.cli.RescanNotes(context.Background(), in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
// EnablePrivacy enable privacy for json rpc
func (c *Jrpc) EnablePrivacy(in *types.ReqAddrs, result *json.RawMessage) error {
reply, err := c.cli.EnablePrivacy(context.Background(), in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
//func (c *Jrpc) EncodeSecretData(in *mixTy.SecretData, result *json.RawMessage) error {
// reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "EncodeSecretData", in)
// if err != nil {
// return err
// }
// *result, err = types.PBToJSON(reply)
// return err
//}
func (c *Jrpc) EncryptSecretData(in *mixTy.EncryptSecretData, result *json.RawMessage) error {
reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "EncryptSecretData", in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
func (c *Jrpc) DecryptSecretData(in *mixTy.DecryptSecretData, result *json.RawMessage) error {
reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "DecryptSecretData", in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
func (c *Jrpc) CreateRawTransaction(in *mixTy.CreateRawTxReq, result *interface{}) error {
reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "CreateRawTransaction", in)
if err != nil {
return err
}
*result = hex.EncodeToString(types.Encode(reply))
return err
}
func (c *Jrpc) CreateZkKeyFile(in *mixTy.CreateZkKeyFileReq, result *interface{}) error {
reply, err := c.cli.ExecWalletFunc(mixTy.MixX, "CreateZkKeyFile", in)
if err != nil {
return err
}
*result, err = types.PBToJSON(reply)
return err
}
// 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 rpc
import (
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/rpc/types"
mixTy "github.com/33cn/plugin/plugin/dapp/mix/types"
)
var log = log15.New("module", "mix.rpc")
// Jrpc json rpc class
type Jrpc struct {
cli *channelClient
}
// Grpc grpc class
type Grpc struct {
*channelClient
}
type channelClient struct {
types.ChannelClient
}
// Init init rpc server
func Init(name string, s types.RPCServer) {
cli := &channelClient{}
grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc)
mixTy.RegisterMixPrivacyServer(s.GRPC(), grpc)
}
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
type AuthorizeCircuit struct {
TreeRootHash frontend.Variable `gnark:",public"`
AuthorizeHash frontend.Variable `gnark:",public"`
AuthorizeSpendHash frontend.Variable `gnark:",public"`
Amount frontend.Variable
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
AuthorizePriKey frontend.Variable
SpendFlag frontend.Variable
NoteRandom frontend.Variable
NoteHash frontend.Variable
//tree path info
Path0 frontend.Variable
Path1 frontend.Variable
Path2 frontend.Variable
Path3 frontend.Variable
Path4 frontend.Variable
Path5 frontend.Variable
Path6 frontend.Variable
Path7 frontend.Variable
Path8 frontend.Variable
Path9 frontend.Variable
Helper0 frontend.Variable
Helper1 frontend.Variable
Helper2 frontend.Variable
Helper3 frontend.Variable
Helper4 frontend.Variable
Helper5 frontend.Variable
Helper6 frontend.Variable
Helper7 frontend.Variable
Helper8 frontend.Variable
Helper9 frontend.Variable
Valid0 frontend.Variable
Valid1 frontend.Variable
Valid2 frontend.Variable
Valid3 frontend.Variable
Valid4 frontend.Variable
Valid5 frontend.Variable
Valid6 frontend.Variable
Valid7 frontend.Variable
Valid8 frontend.Variable
Valid9 frontend.Variable
}
// Define declares the circuit's constraints
func (circuit *AuthorizeCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
// hash function
h, _ := mimc.NewMiMC(MimcHashSeed, curveID, cs)
mimc := &h
mimc.Write(circuit.AuthorizePriKey)
cs.AssertIsEqual(circuit.AuthorizePubKey, mimc.Sum())
mimc.Reset()
mimc.Write(circuit.AuthorizePubKey, circuit.NoteRandom)
cs.AssertIsEqual(circuit.AuthorizeHash, mimc.Sum())
mimc.Reset()
cs.AssertIsBoolean(circuit.SpendFlag)
targetSpendKey := cs.Select(circuit.SpendFlag, circuit.ReceiverPubKey, circuit.ReturnPubKey)
mimc.Write(targetSpendKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.AuthorizeSpendHash, mimc.Sum())
mimc.Reset()
mimc.Write(circuit.ReceiverPubKey, circuit.ReturnPubKey, circuit.AuthorizePubKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
var proofSet, helper, valid []frontend.Variable
proofSet = append(proofSet, circuit.NoteHash)
proofSet = append(proofSet, circuit.Path0)
proofSet = append(proofSet, circuit.Path1)
proofSet = append(proofSet, circuit.Path2)
proofSet = append(proofSet, circuit.Path3)
proofSet = append(proofSet, circuit.Path4)
proofSet = append(proofSet, circuit.Path5)
proofSet = append(proofSet, circuit.Path6)
proofSet = append(proofSet, circuit.Path7)
proofSet = append(proofSet, circuit.Path8)
proofSet = append(proofSet, circuit.Path9)
//helper[0],valid[0]占位, 方便接口只设置有效值
helper = append(helper, cs.Constant("1"))
helper = append(helper, circuit.Helper0)
helper = append(helper, circuit.Helper1)
helper = append(helper, circuit.Helper2)
helper = append(helper, circuit.Helper3)
helper = append(helper, circuit.Helper4)
helper = append(helper, circuit.Helper5)
helper = append(helper, circuit.Helper6)
helper = append(helper, circuit.Helper7)
helper = append(helper, circuit.Helper8)
helper = append(helper, circuit.Helper9)
valid = append(valid, cs.Constant("1"))
valid = append(valid, circuit.Valid0)
valid = append(valid, circuit.Valid1)
valid = append(valid, circuit.Valid2)
valid = append(valid, circuit.Valid3)
valid = append(valid, circuit.Valid4)
valid = append(valid, circuit.Valid5)
valid = append(valid, circuit.Valid6)
valid = append(valid, circuit.Valid7)
valid = append(valid, circuit.Valid8)
valid = append(valid, circuit.Valid9)
VerifyMerkleProof(cs, mimc, circuit.TreeRootHash, proofSet, helper, valid)
return nil
}
package types
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
func TestAuthorize(t *testing.T) {
assert := groth16.NewAssert(t)
var authCircuit AuthorizeCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &authCircuit)
assert.NoError(err)
{
authCircuit.TreeRootHash.Assign("18953560960857123326054550555759265877143310030168748002053709716397549796490")
authCircuit.AuthorizeHash.Assign("4895770928816523282558547614022568289586238930922185617307655942541278140196")
authCircuit.AuthorizeSpendHash.Assign("17847836824302447823607018011193117302314262324241905063439417486141908449945")
authCircuit.ReceiverPubKey.Assign("13496572805321444273664325641440458311310163934354047265362731297880627774936")
authCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
authCircuit.AuthorizePubKey.Assign("21375443884718346645287794853944958188610587325651351394209548420684867245331")
authCircuit.AuthorizePriKey.Assign("17822967620457187568904804290291537271142779717280482398091401115827760898835")
authCircuit.NoteRandom.Assign("2824204835")
authCircuit.Amount.Assign("28242048")
authCircuit.SpendFlag.Assign("1")
authCircuit.NoteHash.Assign("4641322019922509455032097629889269851124503217947103069347447050214760728147")
authCircuit.Path0.Assign("19561523370160677851616596032513161448778901506614020103852017946679781620105")
authCircuit.Path1.Assign("13898857070666440684265042188056372750257678232709763835292910585848522658637")
authCircuit.Path2.Assign("15019169196974879571470243100379529757970866395477207575033769902587972032431")
authCircuit.Path3.Assign("0")
authCircuit.Path4.Assign("0")
authCircuit.Path5.Assign("0")
authCircuit.Path6.Assign("0")
authCircuit.Path7.Assign("0")
authCircuit.Path8.Assign("0")
authCircuit.Path9.Assign("0")
authCircuit.Helper0.Assign("1")
authCircuit.Helper1.Assign("1")
authCircuit.Helper2.Assign("1")
authCircuit.Helper3.Assign("0")
authCircuit.Helper4.Assign("0")
authCircuit.Helper5.Assign("0")
authCircuit.Helper6.Assign("0")
authCircuit.Helper7.Assign("0")
authCircuit.Helper8.Assign("0")
authCircuit.Helper9.Assign("0")
authCircuit.Valid0.Assign("1")
authCircuit.Valid1.Assign("1")
authCircuit.Valid2.Assign("1")
authCircuit.Valid3.Assign("0")
authCircuit.Valid4.Assign("0")
authCircuit.Valid5.Assign("0")
authCircuit.Valid6.Assign("0")
authCircuit.Valid7.Assign("0")
authCircuit.Valid8.Assign("0")
authCircuit.Valid9.Assign("0")
assert.ProverSucceeded(r1cs, &authCircuit)
}
}
This diff is collapsed.
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
//spend commit hash the circuit implementing
type DepositCircuit struct {
NoteHash frontend.Variable `gnark:",public"`
Amount frontend.Variable `gnark:",public"`
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
NoteRandom frontend.Variable
}
func (circuit *DepositCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
// hash function
mimc, _ := mimc.NewMiMC(MimcHashSeed, curveID, cs)
mimc.Write(circuit.ReceiverPubKey, circuit.ReturnPubKey, circuit.AuthorizePubKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
return nil
}
package types
import (
"bytes"
"encoding/hex"
"fmt"
"reflect"
"testing"
"github.com/consensys/gnark/backend/witness"
"github.com/stretchr/testify/assert"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
//receiver prikey="10190477835300927557649934238820360529458681672073866116232821892325659279502"
//receiver pubkey="13496572805321444273664325641440458311310163934354047265362731297880627774936"
//return prikey="7969140283216448215269095418467361784159407896899334866715345504515077887397"
//return pubkey="10193030166569398670555398535278072963719579248877156082361830729347727033510"
//authorize prikey="17822967620457187568904804290291537271142779717280482398091401115827760898835"
//authorize pubkey="2302306531516619173363925550130201424458047172090558749779153607734711372580"
//spend prikey="10407830929890509544473717262275616077696950294748419792758056545898949331744"
//spend pubkey="3656010751855274388516368747583374746848682779395325737100877017850943546836"
func TestDeposit(t *testing.T) {
assert := groth16.NewAssert(t)
var depositCircuit DepositCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &depositCircuit)
assert.NoError(err)
{
//var witness Deposit
depositCircuit.NoteHash.Assign("14803109164298493466684583242985432968056297173621710679077236816845588688436")
depositCircuit.Amount.Assign(28242048)
depositCircuit.ReceiverPubKey.Assign("13496572805321444273664325641440458311310163934354047265362731297880627774936")
depositCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
depositCircuit.AuthorizePubKey.Assign("2302306531516619173363925550130201424458047172090558749779153607734711372580")
depositCircuit.NoteRandom.Assign(2824204835)
assert.ProverSucceeded(r1cs, &depositCircuit)
}
var pubBuf bytes.Buffer
witness.WritePublicTo(&pubBuf, ecc.BN254, &depositCircuit)
//fmt.Println("buf",hex.EncodeToString(pubBuf.Bytes()))
pubStr := hex.EncodeToString(pubBuf.Bytes())
var buf bytes.Buffer
pk, vk, err := groth16.Setup(r1cs)
assert.Nil(err)
buf.Reset()
vk.WriteTo(&buf)
//fmt.Println("vk",hex.EncodeToString(buf.Bytes()))
vkStr := hex.EncodeToString(buf.Bytes())
proof, err := groth16.Prove(r1cs, pk, &depositCircuit)
assert.Nil(err)
buf.Reset()
proof.WriteTo(&buf)
//fmt.Println("proof",hex.EncodeToString(buf.Bytes()))
pfStr := hex.EncodeToString(buf.Bytes())
d, _ := hex.DecodeString(vkStr)
vkt := groth16.NewVerifyingKey(ecc.BN254)
buf.Reset()
buf.Write(d)
vkt.ReadFrom(&buf)
d, _ = hex.DecodeString(pfStr)
buf.Reset()
buf.Write(d)
prt := groth16.NewProof(ecc.BN254)
prt.ReadFrom(&buf)
d, _ = hex.DecodeString(pubStr)
buf.Reset()
buf.Write(d)
err = groth16.ReadAndVerify(prt, vkt, &buf)
assert.Nil(err)
}
func TestDepositSetVal(t *testing.T) {
pubInput := "0000000218b9b448bd793dab9075f70ce404a87497b3a2d0d0b5d177441d6cada1e9b2d20000000000000000000000000000000000000000000000000000000001aef080"
str, _ := hex.DecodeString(pubInput)
var buf bytes.Buffer
buf.Write(str)
var val Witness
n, err := val.LimitReadFrom(&buf)
assert.Nil(t, err)
fmt.Println("n=", n)
//val=make([]fr.Element,2)
//val[0].SetInterface(0x18b9b448bd793dab9075f70ce404a87497b3a2d0d0b5d177441d6cada1e9b2d2)
//val[0].set
//val[1].SetInterface(0x0000000000000000000000000000000000000000000000000000000001aef080)
fmt.Println("0=", val[0].String(), "1=", val[1].String())
var depositCircuit DepositCircuit
getVal(&depositCircuit, val)
fmt.Println("deposit", frontend.GetAssignedValue(depositCircuit.NoteHash))
fmt.Println("amount", frontend.GetAssignedValue(depositCircuit.Amount))
}
func getVal(input frontend.Circuit, w Witness) {
tValue := reflect.ValueOf(input)
if tValue.Kind() == reflect.Ptr {
tValue = tValue.Elem()
}
//reft := reflect.TypeOf(input)
fmt.Println("fields", tValue.NumField())
for i, v := range w {
field := tValue.Type().Field((i))
fmt.Println("i=", i, "name=", field.Name)
f := tValue.FieldByName(field.Name)
a := f.Addr().Interface().(*frontend.Variable)
//a:=tValue.Field(i).Interface().(frontend.Variable)
a.Assign(v.String())
}
}
// 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 types
import "errors"
var (
// ErrZkVerifyFail zk verify fail
ErrZkVerifyFail = errors.New("ErrZkVerifyFail")
//ErrInputParaNotMatch input paras not match
ErrInputParaNotMatch = errors.New("ErrInputParaNotMatch")
//ErrLeafNotFound not found leaf
ErrLeafNotFound = errors.New("ErrLeafNotFound")
//ErrTreeRootHashNotFound not found leaf
ErrTreeRootHashNotFound = errors.New("ErrTreeRootHashNotFound")
//ErrNulliferHashExist exist
ErrNulliferHashExist = errors.New("ErrNulliferHashExist")
//ErrAuthorizeHashExist exist
ErrAuthorizeHashExist = errors.New("ErrAuthorizeHashExist")
//ErrSpendInOutValueNotMatch spend input and output value not match
ErrSpendInOutValueNotMatch = errors.New("ErrSpendInOutValueNotMatch")
//ErrDecryptDataFail decrypt data fail like by wrong prikey
ErrDecryptDataFail = errors.New("ErrDecryptDataFail")
)
This diff is collapsed.
// 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 types
import (
"github.com/33cn/chain33/common/log/log15"
)
var tlog = log15.New("module", MixX)
const (
//MaxTreeLeaves = 1024
TreeLevel = 10
//MimcHashSeed 电路不支持作为公共输入,设为全局常数
MimcHashSeed = "19172955941344617222923168298456110557655645809646772800021167670156933290312"
)
// 执行器的日志类型
const (
// TyLogParacrossCommit commit log key
TyLogMixLocalDeposit = 750
TyLogMixLocalNullifier = 751
TyLogMixLocalAuth = 752
TyLogMixLocalAuthSpend = 753
TyLogMixConfigVk = 754
TyLogMixConfigAuth = 755
TyLogSubLeaves = 756
TyLogSubRoots = 757
TyLogArchiveRootLeaves = 758
TyLogCommitTreeArchiveRoot = 759
TyLogCommitTreeStatus = 760
TyLogNulliferSet = 761
TyLogAuthorizeSet = 762
TyLogAuthorizeSpendSet = 763
TyLogMixConfigPaymentKey = 764
)
//action type
const (
MixActionConfig = iota
MixActionDeposit
MixActionWithdraw
MixActionTransfer
MixActionAuth
)
//circuits default file name
const (
DepositPk = "circuit_deposit.pk"
DepositVk = "circuit_deposit.vk"
WithdrawPk = "circuit_withdraw.pk"
WithdrawVk = "circuit_withdraw.vk"
AuthPk = "circuit_auth.pk"
AuthVk = "circuit_auth.vk"
TransInputPk = "circuit_transfer_input.pk"
TransInputVk = "circuit_transfer_input.vk"
TransOutputPk = "circuit_transfer_output.pk"
TransOutputVk = "circuit_transfer_output.vk"
)
This diff is collapsed.
This diff is collapsed.
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
type TransferInputCircuit struct {
TreeRootHash frontend.Variable `gnark:",public"`
AuthorizeSpendHash frontend.Variable `gnark:",public"`
NullifierHash frontend.Variable `gnark:",public"`
ShieldAmountX frontend.Variable `gnark:",public"`
ShieldAmountY frontend.Variable `gnark:",public"`
ShieldPointHX frontend.Variable `gnark:",public"`
ShieldPointHY frontend.Variable `gnark:",public"`
//secret
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
NoteRandom frontend.Variable
Amount frontend.Variable
AmountRandom frontend.Variable
SpendPriKey frontend.Variable
SpendFlag frontend.Variable
AuthorizeFlag frontend.Variable
NoteHash frontend.Variable
//tree path info
Path0 frontend.Variable
Path1 frontend.Variable
Path2 frontend.Variable
Path3 frontend.Variable
Path4 frontend.Variable
Path5 frontend.Variable
Path6 frontend.Variable
Path7 frontend.Variable
Path8 frontend.Variable
Path9 frontend.Variable
Helper0 frontend.Variable
Helper1 frontend.Variable
Helper2 frontend.Variable
Helper3 frontend.Variable
Helper4 frontend.Variable
Helper5 frontend.Variable
Helper6 frontend.Variable
Helper7 frontend.Variable
Helper8 frontend.Variable
Helper9 frontend.Variable
Valid0 frontend.Variable
Valid1 frontend.Variable
Valid2 frontend.Variable
Valid3 frontend.Variable
Valid4 frontend.Variable
Valid5 frontend.Variable
Valid6 frontend.Variable
Valid7 frontend.Variable
Valid8 frontend.Variable
Valid9 frontend.Variable
}
// Define declares the circuit's constraints
func (circuit *TransferInputCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
cs.AssertIsBoolean(circuit.SpendFlag)
cs.AssertIsBoolean(circuit.AuthorizeFlag)
// hash function
h, _ := mimc.NewMiMC(MimcHashSeed, curveID, cs)
mimc := &h
//verify spend private key
targetSpendKey := cs.Select(circuit.SpendFlag, circuit.ReceiverPubKey, circuit.ReturnPubKey)
mimc.Write(circuit.SpendPriKey)
cs.AssertIsEqual(targetSpendKey, mimc.Sum())
nullValue := cs.Constant(0)
mimc.Reset()
mimc.Write(targetSpendKey, circuit.Amount, circuit.NoteRandom)
calcAuthSpendHash := mimc.Sum()
targetAuthSpendHash := cs.Select(circuit.AuthorizeFlag, calcAuthSpendHash, nullValue)
cs.AssertIsEqual(circuit.AuthorizeSpendHash, targetAuthSpendHash)
mimc.Reset()
mimc.Write(circuit.NoteRandom)
cs.AssertIsEqual(circuit.NullifierHash, mimc.Sum())
//
calcReturnPubkey := cs.Select(circuit.AuthorizeFlag, circuit.ReturnPubKey, nullValue)
calcAuthPubkey := cs.Select(circuit.AuthorizeFlag, circuit.AuthorizePubKey, nullValue)
mimc.Reset()
mimc.Write(circuit.ReceiverPubKey, calcReturnPubkey, calcAuthPubkey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
var proofSet, helper, valid []frontend.Variable
proofSet = append(proofSet, circuit.NoteHash)
proofSet = append(proofSet, circuit.Path0)
proofSet = append(proofSet, circuit.Path1)
proofSet = append(proofSet, circuit.Path2)
proofSet = append(proofSet, circuit.Path3)
proofSet = append(proofSet, circuit.Path4)
proofSet = append(proofSet, circuit.Path5)
proofSet = append(proofSet, circuit.Path6)
proofSet = append(proofSet, circuit.Path7)
proofSet = append(proofSet, circuit.Path8)
proofSet = append(proofSet, circuit.Path9)
//helper[0],valid[0]占位, 方便接口只设置有效值
helper = append(helper, cs.Constant("1"))
helper = append(helper, circuit.Helper0)
helper = append(helper, circuit.Helper1)
helper = append(helper, circuit.Helper2)
helper = append(helper, circuit.Helper3)
helper = append(helper, circuit.Helper4)
helper = append(helper, circuit.Helper5)
helper = append(helper, circuit.Helper6)
helper = append(helper, circuit.Helper7)
helper = append(helper, circuit.Helper8)
helper = append(helper, circuit.Helper9)
valid = append(valid, cs.Constant("1"))
valid = append(valid, circuit.Valid0)
valid = append(valid, circuit.Valid1)
valid = append(valid, circuit.Valid2)
valid = append(valid, circuit.Valid3)
valid = append(valid, circuit.Valid4)
valid = append(valid, circuit.Valid5)
valid = append(valid, circuit.Valid6)
valid = append(valid, circuit.Valid7)
valid = append(valid, circuit.Valid8)
valid = append(valid, circuit.Valid9)
CommitValueVerify(cs, circuit.Amount, circuit.AmountRandom, circuit.ShieldAmountX, circuit.ShieldAmountY, circuit.ShieldPointHX, circuit.ShieldPointHY)
VerifyMerkleProof(cs, mimc, circuit.TreeRootHash, proofSet, helper, valid)
return nil
}
package types
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
func TestTransferInput(t *testing.T) {
assert := groth16.NewAssert(t)
var inputCircuit TransferInputCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &inputCircuit)
assert.NoError(err)
{
inputCircuit.TreeRootHash.Assign("457812157273975068180144939194931372467682914013265626991402231230450012330")
inputCircuit.AuthorizeSpendHash.Assign("14463129595522277797353018005538222902035087589748809554960616199173731919802")
inputCircuit.NullifierHash.Assign("12376093571606701949533526735186436482268907783512509935977783346861805262929")
inputCircuit.ShieldAmountX.Assign("12598656472198560295956115825363858683566688303969048230275808317634686855820")
inputCircuit.ShieldAmountY.Assign("5287524325952639485224317845546845679649328720392059741208352845659048630229")
inputCircuit.ShieldPointHX.Assign("19172955941344617222923168298456110557655645809646772800021167670156933290312")
inputCircuit.ShieldPointHY.Assign("21116962883761739586121793871108889864627195706475546685847911817475098399811")
inputCircuit.ReceiverPubKey.Assign("20094753906906836700810108535649927887994772258248603565615394844515069419451")
inputCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
inputCircuit.AuthorizePubKey.Assign("2302306531516619173363925550130201424458047172090558749779153607734711372580")
inputCircuit.NoteRandom.Assign("2824204835")
inputCircuit.Amount.Assign("28242048")
inputCircuit.AmountRandom.Assign("282420481")
inputCircuit.SpendPriKey.Assign("10190477835300927557649934238820360529458681672073866116232821892325659279502")
inputCircuit.SpendFlag.Assign("1")
inputCircuit.AuthorizeFlag.Assign("1")
inputCircuit.NoteHash.Assign("1933334234871933218683301093524793045543211425994253628606123874146452475778")
inputCircuit.Path0.Assign("19561523370160677851616596032513161448778901506614020103852017946679781620105")
inputCircuit.Path1.Assign("13898857070666440684265042188056372750257678232709763835292910585848522658637")
inputCircuit.Path2.Assign("15019169196974879571470243100379529757970866395477207575033769902587972032431")
inputCircuit.Path3.Assign("0")
inputCircuit.Path4.Assign("0")
inputCircuit.Path5.Assign("0")
inputCircuit.Path6.Assign("0")
inputCircuit.Path7.Assign("0")
inputCircuit.Path8.Assign("0")
inputCircuit.Path9.Assign("0")
inputCircuit.Helper0.Assign("1")
inputCircuit.Helper1.Assign("1")
inputCircuit.Helper2.Assign("1")
inputCircuit.Helper3.Assign("0")
inputCircuit.Helper4.Assign("0")
inputCircuit.Helper5.Assign("0")
inputCircuit.Helper6.Assign("0")
inputCircuit.Helper7.Assign("0")
inputCircuit.Helper8.Assign("0")
inputCircuit.Helper9.Assign("0")
inputCircuit.Valid0.Assign("1")
inputCircuit.Valid1.Assign("1")
inputCircuit.Valid2.Assign("1")
inputCircuit.Valid3.Assign("0")
inputCircuit.Valid4.Assign("0")
inputCircuit.Valid5.Assign("0")
inputCircuit.Valid6.Assign("0")
inputCircuit.Valid7.Assign("0")
inputCircuit.Valid8.Assign("0")
inputCircuit.Valid9.Assign("0")
assert.ProverSucceeded(r1cs, &inputCircuit)
}
}
//
//func TestTransferInputReturnKey(t *testing.T) {
//
// assert := groth16.NewAssert(t)
//
// r1cs := NewTransferInput()
// r1csBN256 := backend_bn256.Cast(r1cs)
// {
// good := backend.NewAssignment()
// good.Assign(backend.Public, "treeRootHash", "10531321614990797034921282585661869614556487056951485265320464926630499341310")
// good.Assign(backend.Public, "shieldAmountX", "14087975867275911077371231345227824611951436822132762463787130558957838320348")
// good.Assign(backend.Public, "shieldAmountY", "15113519960384204624879642069520481336224311978035289236693658603675385299879")
// good.Assign(backend.Public, "authorizeSpendHash", "6026163592877030954825395224309219861774131411806846860652261047183070579370")
// good.Assign(backend.Public, "nullifierHash", "6747518781649068310795677405858353007442326529625450860668944156162052335195")
//
// good.Assign(backend.Secret, "amount", "28242048")
// good.Assign(backend.Secret, "amountRandom", "35")
//
// good.Assign(backend.Secret, "receiverPubKey", "13735985067536865723202617343666111332145536963656464451727087263423649028705")
// good.Assign(backend.Secret, "returnPubKey", "16067249407809359746114321133992130903102335882983385972747813693681808870497")
// good.Assign(backend.Secret, "authorizePubKey", "13519883267141251871527102103999205179714486518503885909948192364772977661583")
//
// good.Assign(backend.Secret, "spendPriKey", "7969140283216448215269095418467361784159407896899334866715345504515077887397")
// //returnkey spend notehash
// good.Assign(backend.Secret, "spendFlag", "0")
//
// good.Assign(backend.Secret, "authorizeFlag", "1")
//
// good.Assign(backend.Secret, "noteRandom", "2824204835")
//
// good.Assign(backend.Secret, "noteHash", "16308793397024662832064523892418908145900866571524124093537199035808550255649")
//
// //nodehash="16308793397024662832064523892418908145900866571524124093537199035808550255649"
// good.Assign(backend.Secret, "path1", "19561523370160677851616596032513161448778901506614020103852017946679781620105")
// good.Assign(backend.Secret, "path2", "13898857070666440684265042188056372750257678232709763835292910585848522658637")
// good.Assign(backend.Secret, "path3", "15019169196974879571470243100379529757970866395477207575033769902587972032431")
// good.Assign(backend.Secret, "path4", "0")
// good.Assign(backend.Secret, "path5", "0")
// good.Assign(backend.Secret, "path6", "0")
// good.Assign(backend.Secret, "path7", "0")
// good.Assign(backend.Secret, "path8", "0")
// good.Assign(backend.Secret, "path9", "0")
//
// good.Assign(backend.Secret, "helper1", "1")
// good.Assign(backend.Secret, "helper2", "1")
// good.Assign(backend.Secret, "helper3", "1")
// good.Assign(backend.Secret, "helper4", "0")
// good.Assign(backend.Secret, "helper5", "0")
// good.Assign(backend.Secret, "helper6", "0")
// good.Assign(backend.Secret, "helper7", "0")
// good.Assign(backend.Secret, "helper8", "0")
// good.Assign(backend.Secret, "helper9", "0")
//
// good.Assign(backend.Secret, "valid1", "1")
// good.Assign(backend.Secret, "valid2", "1")
// good.Assign(backend.Secret, "valid3", "1")
// good.Assign(backend.Secret, "valid4", "0")
// good.Assign(backend.Secret, "valid5", "0")
// good.Assign(backend.Secret, "valid6", "0")
// good.Assign(backend.Secret, "valid7", "0")
// good.Assign(backend.Secret, "valid8", "0")
// good.Assign(backend.Secret, "valid9", "0")
//
// assert.Solved(&r1csBN256, good, nil)
// }
//
//}
//
//func TestTransferInputNoAuthorize(t *testing.T) {
//
// assert := groth16.NewAssert(t)
//
// r1cs := NewTransferInput()
// r1csBN256 := backend_bn256.Cast(r1cs)
// {
// good := backend.NewAssignment()
// good.Assign(backend.Public, "treeRootHash", "8924377726623516198388981994706612588174229761660626844219523809311621081152")
// good.Assign(backend.Public, "shieldAmountX", "20026900249169569699397829614948056401416692452575929785554743563301443795984")
// good.Assign(backend.Public, "shieldAmountY", "11443294504840468048882645872852838384649876010412151915870299030068051779303")
// good.Assign(backend.Public, "authorizeSpendHash", "0")
// good.Assign(backend.Public, "nullifierHash", "4493238794492517147695618716694376637191823831910850819304582851540887491471")
//
// good.Assign(backend.Secret, "amount", "500000000")
// good.Assign(backend.Secret, "amountRandom", "103649245823269378598256096359743803233")
//
// good.Assign(backend.Secret, "receiverPubKey", "7244551457692363731356498279463138379576484998878425864678733206990733443457")
// good.Assign(backend.Secret, "returnPubKey", "0")
// good.Assign(backend.Secret, "authorizePubKey", "0")
//
// good.Assign(backend.Secret, "spendPriKey", "19115616183616714814727844928908633989028519974595353009754871398745087846141")
// good.Assign(backend.Secret, "spendFlag", "1")
// //not need authorize
// good.Assign(backend.Secret, "authorizeFlag", "0")
//
// good.Assign(backend.Secret, "noteRandom", "16855817802811010832998322637530013398737002960466904173163094025121554818471")
//
// good.Assign(backend.Secret, "noteHash", "4757455985754753449547885621755931629265767091930770913671501411452663313694")
//
// good.Assign(backend.Secret, "path1", "21609869341494920403470153054548069228540665950349313465330160010270609674984")
// good.Assign(backend.Secret, "path2", "0")
// good.Assign(backend.Secret, "path3", "0")
// good.Assign(backend.Secret, "path4", "0")
// good.Assign(backend.Secret, "path5", "0")
// good.Assign(backend.Secret, "path6", "0")
// good.Assign(backend.Secret, "path7", "0")
// good.Assign(backend.Secret, "path8", "0")
// good.Assign(backend.Secret, "path9", "0")
//
// good.Assign(backend.Secret, "helper1", "0")
// good.Assign(backend.Secret, "helper2", "1")
// good.Assign(backend.Secret, "helper3", "1")
// good.Assign(backend.Secret, "helper4", "0")
// good.Assign(backend.Secret, "helper5", "0")
// good.Assign(backend.Secret, "helper6", "0")
// good.Assign(backend.Secret, "helper7", "0")
// good.Assign(backend.Secret, "helper8", "0")
// good.Assign(backend.Secret, "helper9", "0")
//
// good.Assign(backend.Secret, "valid1", "1")
// good.Assign(backend.Secret, "valid2", "0")
// good.Assign(backend.Secret, "valid3", "0")
// good.Assign(backend.Secret, "valid4", "0")
// good.Assign(backend.Secret, "valid5", "0")
// good.Assign(backend.Secret, "valid6", "0")
// good.Assign(backend.Secret, "valid7", "0")
// good.Assign(backend.Secret, "valid8", "0")
// good.Assign(backend.Secret, "valid9", "0")
//
// assert.Solved(&r1csBN256, good, nil)
// }
//
//}
package types
import (
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/std/hash/mimc"
)
type TransferOutputCircuit struct {
//public
NoteHash frontend.Variable `gnark:",public"`
ShieldAmountX frontend.Variable `gnark:",public"`
ShieldAmountY frontend.Variable `gnark:",public"`
ShieldPointHX frontend.Variable `gnark:",public"`
ShieldPointHY frontend.Variable `gnark:",public"`
//secret
ReceiverPubKey frontend.Variable
ReturnPubKey frontend.Variable
AuthorizePubKey frontend.Variable
NoteRandom frontend.Variable
Amount frontend.Variable
AmountRandom frontend.Variable
}
// Define declares the circuit's constraints
func (circuit *TransferOutputCircuit) Define(curveID ecc.ID, cs *frontend.ConstraintSystem) error {
// hash function
h, _ := mimc.NewMiMC(MimcHashSeed, curveID, cs)
mimc := &h
mimc.Write(circuit.ReceiverPubKey, circuit.ReturnPubKey, circuit.AuthorizePubKey, circuit.Amount, circuit.NoteRandom)
cs.AssertIsEqual(circuit.NoteHash, mimc.Sum())
CommitValueVerify(cs, circuit.Amount, circuit.AmountRandom, circuit.ShieldAmountX, circuit.ShieldAmountY, circuit.ShieldPointHX, circuit.ShieldPointHY)
return nil
}
package types
import (
"testing"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend"
"github.com/consensys/gnark/backend/groth16"
"github.com/consensys/gnark/frontend"
)
func TestTransferOutput(t *testing.T) {
assert := groth16.NewAssert(t)
var outCircuit TransferOutputCircuit
// compiles our circuit into a R1CS
r1cs, err := frontend.Compile(ecc.BN254, backend.GROTH16, &outCircuit)
assert.NoError(err)
{
outCircuit.NoteHash.Assign("14803109164298493466684583242985432968056297173621710679077236816845588688436")
outCircuit.ShieldAmountX.Assign("12598656472198560295956115825363858683566688303969048230275808317634686855820")
outCircuit.ShieldAmountY.Assign("5287524325952639485224317845546845679649328720392059741208352845659048630229")
outCircuit.ShieldPointHX.Assign("19172955941344617222923168298456110557655645809646772800021167670156933290312")
outCircuit.ShieldPointHY.Assign("21116962883761739586121793871108889864627195706475546685847911817475098399811")
outCircuit.ReceiverPubKey.Assign("13496572805321444273664325641440458311310163934354047265362731297880627774936")
outCircuit.ReturnPubKey.Assign("10193030166569398670555398535278072963719579248877156082361830729347727033510")
outCircuit.AuthorizePubKey.Assign("2302306531516619173363925550130201424458047172090558749779153607734711372580")
outCircuit.NoteRandom.Assign("2824204835")
outCircuit.Amount.Assign("28242048")
outCircuit.AmountRandom.Assign("282420481")
assert.ProverSucceeded(r1cs, &outCircuit)
}
}
// 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 types
import (
"reflect"
log "github.com/33cn/chain33/common/log/log15"
coins "github.com/33cn/chain33/system/dapp/coins/types"
"github.com/33cn/chain33/types"
token "github.com/33cn/plugin/plugin/dapp/token/types"
)
var (
// ParaX paracross exec name
MixX = "mix"
glog = log.New("module", MixX)
)
func init() {
// init executor type
types.AllowUserExec = append(types.AllowUserExec, []byte(MixX))
types.RegFork(MixX, InitFork)
types.RegExec(MixX, InitExecutor)
}
//InitFork ...
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(MixX, "Enable", 0)
}
//InitExecutor ...
func InitExecutor(cfg *types.Chain33Config) {
types.RegistorExecutor(MixX, NewType(cfg))
}
// GetExecName get para exec name
func GetExecName(cfg *types.Chain33Config) string {
return cfg.ExecName(MixX)
}
// ParacrossType base paracross type
type MixType struct {
types.ExecTypeBase
}
// NewType get paracross type
func NewType(cfg *types.Chain33Config) *MixType {
c := &MixType{}
c.SetChild(c)
c.SetConfig(cfg)
return c
}
// GetName 获取执行器名称
func (p *MixType) GetName() string {
return MixX
}
// GetLogMap get receipt log map
func (p *MixType) GetLogMap() map[int64]*types.LogInfo {
return map[int64]*types.LogInfo{
TyLogMixConfigVk: {Ty: reflect.TypeOf(ZkVerifyKeys{}), Name: "LogMixConfigVk"},
TyLogMixConfigAuth: {Ty: reflect.TypeOf(AuthKeys{}), Name: "LogMixConfigAuthPubKey"},
TyLogSubLeaves: {Ty: reflect.TypeOf(ReceiptCommitSubLeaves{}), Name: "LogSubLeaves"},
TyLogCommitTreeStatus: {Ty: reflect.TypeOf(ReceiptCommitTreeStatus{}), Name: "LogCommitTreeStatus"},
TyLogSubRoots: {Ty: reflect.TypeOf(ReceiptCommitSubRoots{}), Name: "LogSubRoots"},
TyLogArchiveRootLeaves: {Ty: reflect.TypeOf(ReceiptArchiveLeaves{}), Name: "LogArchiveRootLeaves"},
TyLogCommitTreeArchiveRoot: {Ty: reflect.TypeOf(ReceiptArchiveTreeRoot{}), Name: "LogCommitTreeArchiveRoot"},
TyLogMixConfigPaymentKey: {Ty: reflect.TypeOf(NoteAccountKey{}), Name: "LogConfigReceivingKey"},
TyLogNulliferSet: {Ty: reflect.TypeOf(ExistValue{}), Name: "LogNullifierSet"},
}
}
// GetTypeMap get action type
func (p *MixType) GetTypeMap() map[string]int32 {
return map[string]int32{
"Config": MixActionConfig,
"Deposit": MixActionDeposit,
"Withdraw": MixActionWithdraw,
"Transfer": MixActionTransfer,
"Authorize": MixActionAuth,
}
}
// GetPayload mix get action payload
func (p *MixType) GetPayload() types.Message {
return &MixAction{}
}
func GetAssetExecSymbol(cfg *types.Chain33Config, execer, symbol string) (string, string) {
if symbol == "" {
return coins.CoinsX, cfg.GetCoinSymbol()
}
if execer == "" {
return token.TokenX, symbol
}
return execer, symbol
}
func GetTransferTxFee(cfg *types.Chain33Config, assetExecer string) int64 {
conf := types.ConfSub(cfg, MixX)
txFee := conf.GInt("txFee")
tokenFee := conf.IsEnable("tokenFee")
//一切非coins的token资产 在tokenFee=false都不收txfee,特殊地址代扣
if assetExecer != coins.CoinsX && !tokenFee {
return 0
}
//tokenFee=true或者coins都按txfee数量收txFee
return txFee
}
package types
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMulCurvePointG(t *testing.T) {
p := MulCurvePointG(3300000)
assert.Equal(t, "16340309671848023141603674621476146712179749929747125480153351030768864391631", p.X.String())
assert.Equal(t, "7282133334630698770430559968655675427988723121976895210725923327624387185615", p.Y.String())
}
package types
import (
"bytes"
"encoding/binary"
"encoding/hex"
"io"
"math/big"
"reflect"
"github.com/consensys/gnark-crypto/ecc"
bn254 "github.com/consensys/gnark-crypto/ecc/bn254/twistededwards"
"github.com/consensys/gnark/frontend"
"github.com/pkg/errors"
"github.com/consensys/gnark/std/algebra/twistededwards"
"github.com/consensys/gnark/std/hash/mimc"
ecc_bn254 "github.com/consensys/gnark-crypto/ecc/bn254"
"github.com/consensys/gnark-crypto/ecc/bn254/fr"
)
type Witness []fr.Element
func (witness *Witness) LimitReadFrom(r io.Reader) (int64, error) {
var buf [4]byte
if read, err := io.ReadFull(r, buf[:4]); err != nil {
return int64(read), err
}
sliceLen := binary.BigEndian.Uint32(buf[:4])
if len(*witness) != int(sliceLen) {
*witness = make([]fr.Element, sliceLen)
}
lr := io.LimitReader(r, int64(sliceLen*fr.Limbs*8))
dec := ecc_bn254.NewDecoder(lr)
for i := 0; i < int(sliceLen); i++ {
if err := dec.Decode(&(*witness)[i]); err != nil {
return dec.BytesRead() + 4, err
}
}
return dec.BytesRead() + 4, nil
}
func VerifyMerkleProof(cs *frontend.ConstraintSystem, mimc *mimc.MiMC, treeRootHash frontend.Variable, proofSet, helper, valid []frontend.Variable) {
sum := leafSum(mimc, proofSet[0])
for i := 1; i < len(proofSet); i++ {
cs.AssertIsBoolean(helper[i])
d1 := cs.Select(helper[i], sum, proofSet[i])
d2 := cs.Select(helper[i], proofSet[i], sum)
rst := nodeSum(mimc, d1, d2)
sum = cs.Select(valid[i], rst, sum)
}
// Compare our calculated Merkle root to the desired Merkle root.
cs.AssertIsEqual(sum, treeRootHash)
}
// nodeSum returns the hash created from data inserted to form a leaf.
// Without domain separation.
func nodeSum(mimc *mimc.MiMC, a, b frontend.Variable) frontend.Variable {
mimc.Reset()
mimc.Write(a, b)
return mimc.Sum()
}
// leafSum returns the hash created from data inserted to form a leaf.
// Without domain separation.
func leafSum(mimc *mimc.MiMC, data frontend.Variable) frontend.Variable {
mimc.Reset()
mimc.Write(data)
return mimc.Sum()
}
func CommitValueVerify(cs *frontend.ConstraintSystem, amount, amountRandom,
shieldAmountX, shieldAmountY, shieldPointHX, shieldPointHY frontend.Variable) {
cs.AssertIsLessOrEqual(amount, 9000000000000000000)
curve, _ := twistededwards.NewEdCurve(ecc.BN254)
var pointAmount twistededwards.Point
pointAmount.ScalarMulFixedBase(cs, curve.BaseX, curve.BaseY, amount, curve)
var pointH twistededwards.Point
pointH.X = shieldPointHX
pointH.Y = shieldPointHY
var pointRandom twistededwards.Point
pointRandom.ScalarMulNonFixedBase(cs, &pointH, amountRandom, curve)
var pointSum twistededwards.Point
pointSum.AddGeneric(cs, &pointAmount, &pointRandom, curve)
cs.AssertIsEqual(pointSum.X, shieldAmountX)
cs.AssertIsEqual(pointSum.Y, shieldAmountY)
}
func ConstructCircuitPubInput(pubInput string, circuit frontend.Circuit) error {
buf, err := GetByteBuff(pubInput)
if err != nil {
return errors.Wrapf(err, "decode string=%s", pubInput)
}
var witness Witness
_, err = witness.LimitReadFrom(buf)
if err != nil {
return errors.Wrapf(err, "LimitReadFrom pub input=%s", pubInput)
}
tValue := reflect.ValueOf(circuit)
if tValue.Kind() == reflect.Ptr {
tValue = tValue.Elem()
}
for i, v := range witness {
field := tValue.Type().Field(i)
tValue.FieldByName(field.Name).Addr().Interface().(*frontend.Variable).Assign(v.String())
}
return nil
}
func MulCurvePointG(val interface{}) *bn254.PointAffine {
var v fr.Element
v.SetInterface(val)
var scale big.Int
v.ToBigIntRegular(&scale)
var point bn254.PointAffine
ed := bn254.GetEdwardsCurve()
point.ScalarMul(&ed.Base, &scale)
return &point
}
func MulCurvePointH(pointHX, pointHY, val string) *bn254.PointAffine {
var v fr.Element
v.SetInterface(val)
var scale big.Int
v.ToBigIntRegular(&scale)
var pointV, pointH bn254.PointAffine
pointH.X.SetString(pointHX)
pointH.Y.SetString(pointHY)
pointV.ScalarMul(&pointH, &scale)
return &pointV
}
func GetCurveSum(points ...*bn254.PointAffine) *bn254.PointAffine {
//Add之前需初始化pointSum,不能空值,不然会等于0
pointSum := bn254.NewPointAffine(points[0].X, points[0].Y)
for _, a := range points[1:] {
pointSum.Add(&pointSum, a)
}
return &pointSum
}
//A=B+C
func CheckSumEqual(points ...*bn254.PointAffine) bool {
if len(points) < 2 {
return false
}
//Add之前需初始化pointSum,不能空值,不然会等于0
pointSum := bn254.NewPointAffine(points[1].X, points[1].Y)
for _, a := range points[2:] {
pointSum.Add(&pointSum, a)
}
if pointSum.X.Equal(&points[0].X) && pointSum.Y.Equal(&points[0].Y) {
return true
}
return false
}
func GetByteBuff(input string) (*bytes.Buffer, error) {
var buffInput bytes.Buffer
res, err := hex.DecodeString(input)
if err != nil {
return nil, errors.Wrapf(err, "getByteBuff to %s", input)
}
_, err = buffInput.Write(res)
if err != nil {
return nil, errors.Wrapf(err, "write buff %s", input)
}
return &buffInput, nil
}
func Str2Byte(v string) []byte {
var fr fr.Element
fr.SetString(v)
b := fr.Bytes()
return b[:]
}
func Byte2Str(v []byte) string {
var f fr.Element
f.SetBytes(v)
return f.String()
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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