Unverified Commit 4b5cd0a0 authored by vipwzw's avatar vipwzw Committed by GitHub

Merge pull request #849 from zhengjunhe/x2eth_200507

X2eth 200507
parents a3abe8fc 42c84150
......@@ -42,6 +42,12 @@ function down() {
docker-compose down --rmi local
fi
# shellcheck disable=SC2155
local isGanacheExit=$(docker ps | grep ganachetest)
if [[ ${isGanacheExit} != "" ]]; then
docker stop ganachetest
docker rm ganachetest
fi
}
# run script
......
......@@ -73,7 +73,6 @@ echo "CLI=$CLI"
####################
function base_init() {
# update test environment
sed -i $sedfix 's/^Title.*/Title="local"/g' chain33.toml
sed -i $sedfix 's/^TestNet=.*/TestNet=true/g' chain33.toml
......@@ -116,6 +115,11 @@ function base_init() {
#autonomy
sed -i $sedfix 's/^useBalance=.*/useBalance=true/g' chain33.toml
sed -i $sedfix 's/^total="16htvcBNS.*/total="1Q9sQwothzM1gKSzkVZ8Dt1tqKX1uzSagx"/g' chain33.toml
if [ "$DAPP" == "x2ethereum" ]; then
sed -i $sedfix 's/^enableReduceLocaldb=.*/enableReduceLocaldb=false/g' chain33.toml
sed -i $sedfix 's/^enablePushSubscribe=.*/enablePushSubscribe=true/g' chain33.toml
fi
}
function start() {
......
......@@ -7,19 +7,25 @@ require (
github.com/BurntSushi/toml v0.3.1
github.com/NebulousLabs/Sia v1.3.7
github.com/beorn7/perks v1.0.1 // indirect
github.com/bitly/go-simplejson v0.5.0
github.com/btcsuite/btcd v0.20.1-beta
github.com/coreos/etcd v3.3.15+incompatible
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f // indirect
github.com/davecgh/go-spew v1.1.1
github.com/ethereum/go-ethereum v1.9.9
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/golang/protobuf v1.3.4
github.com/hashicorp/golang-lru v0.5.3
github.com/huin/goupnp v1.0.0
github.com/jackpal/go-nat-pmp v1.0.1
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458
github.com/miguelmota/go-solidity-sha3 v0.1.0
github.com/mr-tron/base58 v1.1.3
github.com/pborman/uuid v1.2.0
github.com/pkg/errors v0.8.1
github.com/prometheus/client_golang v0.9.2 // indirect
github.com/prometheus/common v0.4.1 // indirect
github.com/prometheus/common v0.4.1
github.com/prometheus/procfs v0.0.3 // indirect
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d
github.com/rs/cors v1.6.0
......@@ -35,5 +41,4 @@ require (
golang.org/x/net v0.0.0-20200301022130-244492dfa37a
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect
google.golang.org/grpc v1.28.0
gopkg.in/sourcemap.v1 v1.0.5 // indirect
)
......@@ -5,6 +5,19 @@ github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7 h1:PqzgE6kAMi
github.com/AndreasBriese/bbloom v0.0.0-20180913140656-343706a395b7/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9 h1:HD8gA2tkByhMAwYaFAX9w2l7vxvBQ5NMoxDrkhqhtn4=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
github.com/Azure/azure-storage-blob-go v0.7.0/go.mod h1:f9YQKtsG1nMisotuTPpO0tjNuEjKRYAcJU8/ydDI++4=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/Kubuxu/go-os-helper v0.0.1/go.mod h1:N8B+I7vPCT80IcP58r50u4+gEEcsZETFUpAzWW2ep1Y=
......@@ -18,19 +31,35 @@ github.com/NebulousLabs/fastrand v0.0.0-20180208210444-3cf7173006a0 h1:g/ETZwHx5
github.com/NebulousLabs/fastrand v0.0.0-20180208210444-3cf7173006a0/go.mod h1:Bdzq+51GR4/0DIhaICZEOm+OHvXGwwB2trKZ8B4Y6eQ=
github.com/NebulousLabs/merkletree v0.0.0-20181025040823-2a1d1d1dc33c h1:PylSN1KOCPRtX4FM3rqEYIk4tWUOLkB6xGvK/RqHdP4=
github.com/NebulousLabs/merkletree v0.0.0-20181025040823-2a1d1d1dc33c/go.mod h1:Cn056wBLKay+uIS9LJn7ymwhgC5mqbOtG6iOhEvyy4M=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/VictoriaMetrics/fastcache v1.5.3 h1:2odJnXLbFZcoV9KYtQ+7TH1UOq3dn3AssMgieaezkR4=
github.com/VictoriaMetrics/fastcache v1.5.3/go.mod h1:+jv9Ckb+za/P1ZRg/sulP5Ni1v49daAVERr0H3CuscE=
github.com/XiaoMi/pegasus-go-client v0.0.0-20181029071519-9400942c5d1c h1:3fAhdHMhoSG57DjJ/dqLFfgD+FoooPbQH6szINbrr3k=
github.com/XiaoMi/pegasus-go-client v0.0.0-20181029071519-9400942c5d1c/go.mod h1:KcL6D/4RZ8RAYzQ5gKI0odcdWUmCVlbQTOlWrhP71CY=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5VpdgMhJosfJnn5/FoN2SRZ4p7fJNX58YPaU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/apache/thrift v0.0.0-20171203172758-327ebb6c2b6d h1:b/FqDLjWXDQI6XBYvWDVgEKv3xOTs68qRkuqyU37lBc=
github.com/apache/thrift v0.0.0-20171203172758-327ebb6c2b6d/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847 h1:rtI0fD4oG/8eVokGVPYJEW1F88p1ZNgXiEIs9thEE4A=
github.com/aristanetworks/goarista v0.0.0-20170210015632-ea17b1a17847/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.25.48/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/boltdb/bolt v1.3.1 h1:JQmyP4ZBrce+ZQu0dY660FMfatumYDLun9hBCUVIkF4=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/btcsuite/btcd v0.0.0-20181013004428-67e573d211ac/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
github.com/btcsuite/btcd v0.0.0-20190109040709-5bda5314ca95/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
github.com/btcsuite/btcd v0.0.0-20190213025234-306aecffea32/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
github.com/btcsuite/btcd v0.0.0-20190523000118-16327141da8c/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3 h1:A/EVblehb75cUgXA5njHPn0kLAsykn6mJGz7rnmW5W0=
......@@ -39,6 +68,7 @@ github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQj
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
......@@ -50,7 +80,14 @@ github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.0.1-0.20190104013014-3767db7a7e18/go.mod h1:HD5P3vAIAh+Y2GAxg0PrPN1P8WkepXGpjbUPDHJqqKM=
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/bbolt v1.3.0 h1:HIgH5xUWXT914HCI671AxuTTqjj64UOFr7pHn48LUTI=
github.com/coreos/bbolt v1.3.0/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
......@@ -58,6 +95,7 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
github.com/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE=
github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
......@@ -66,34 +104,61 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I=
github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
github.com/decred/base58 v1.0.0 h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w=
github.com/decred/base58 v1.0.0/go.mod h1:LLY1p5e3g91byL/UO1eiZaYd+uRoVRarybgcoymu9Ks=
github.com/dgraph-io/badger v1.5.4 h1:gVTrpUTbbr/T24uvoCaqY2KSHfNLVGm0w+hbee2HMeg=
github.com/dgraph-io/badger v1.5.4/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgraph-io/badger v1.5.5-0.20190226225317-8115aed38f8f/go.mod h1:VZxzAIRPHRVNRKRo6AXrX9BJegn6il06VMTZVJYCIjQ=
github.com/dgraph-io/badger v1.6.0-rc1 h1:JphPpoBZJ3WHha133BGYlQqltSGIhV+VsEID0++nN9A=
github.com/dgraph-io/badger v1.6.0-rc1/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20180109070241-2de33835d102 h1:afESQBXJEnj3fu+34X//E8Wg3nEbMJxJkwSc0tPePK0=
github.com/dgryski/go-farm v0.0.0-20180109070241-2de33835d102/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20190104051053-3adb47b1fb0f/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dlclark/regexp2 v1.2.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c h1:JHHhtb9XWJrGNMcrVP6vyzO4dusgi/HnceHTgxSejUM=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa h1:XKAhUk/dtp+CV0VO6mhG2V7jA9vbcGcnYF/Ay9NjZrY=
github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/ethereum/go-ethereum v1.8.20/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
github.com/ethereum/go-ethereum v1.9.9 h1:jnoBvjH8aMH++iH14XmiJdAsnRcmZUM+B5fsnEZBVE0=
github.com/ethereum/go-ethereum v1.9.9/go.mod h1:a9TqabFudpDu1nucId+k9S8R9whYaHnGBLKFouA5EAo=
github.com/ethereum/go-ethereum v1.9.13 h1:rOPqjSngvs1VSYH2H+PMPiWt4VEulvNRbFgqiGqJM3E=
github.com/ethereum/go-ethereum v1.9.13/go.mod h1:qwN9d1GLyDh0N7Ab8bMGd0H9knaji2jOBm2RrMGjXls=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
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/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI=
github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
......@@ -114,24 +179,34 @@ github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.0/go.mod h1:Qd/q+1AKNOZr9uGQzbzCmRO6sUih6GTPZv6a1/R87v0=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2-0.20190517061210-b285ee9cfc6c/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4 h1:87PNWwrRvUSnqS4dlcBU/ftvOIBep4sYuBLlh6rX2wk=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989 h1:giknQ4mEuDFmmHSrGcbargOuLHQGtywqo4mheITex54=
github.com/gorilla/websocket v1.4.1-0.20190629185528-ae1634f6a989/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
github.com/haltingstate/secp256k1-go v0.0.0-20151224084235-572209b26df6 h1:HE4YDtvtpZgjRJ2tCOmaXlcpBTFG2e0jvfNntM5sXOs=
github.com/haltingstate/secp256k1-go v0.0.0-20151224084235-572209b26df6/go.mod h1:73mKQiY8bLnscfGakn57WAJZTzT0eSUAy3qgMQNR/DI=
github.com/hashicorp/golang-lru v0.0.0-20160813221303-0a025b7e63ad/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
......@@ -140,11 +215,13 @@ github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/huin/goupnp v0.0.0-20161224104101-679507af18f3/go.mod h1:MZ2ZmwcBpvOoJ22IJsc7va19ZwoheaBk43rKg12SKag=
github.com/huin/goupnp v1.0.0 h1:wg75sLpL6DZqwHQN6E1Cfk6mtfzS45z8OV+ic+DtHRo=
github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/influxdata/influxdb v1.7.9 h1:uSeBTNO4rBkbp1Be5FKRsAmglM9nlx25TzVQRQt1An4=
github.com/influxdata/influxdb v1.7.9/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
......@@ -170,6 +247,8 @@ github.com/jackpal/gateway v1.0.5 h1:qzXWUJfuMdlLMtt0a3Dgt+xkWQiA5itDEITVJtuSwMc
github.com/jackpal/gateway v1.0.5/go.mod h1:lTpwd4ACLXmpyiCTRtfiNyVnUmqT9RivzCDQetPfnjA=
github.com/jackpal/go-nat-pmp v1.0.1 h1:i0LektDkO1QlrTm/cSuP+PyBCDnYvjPLGl4LdWEMiaA=
github.com/jackpal/go-nat-pmp v1.0.1/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA=
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jbenet/go-cienv v0.0.0-20150120210510-1bb1476777ec/go.mod h1:rGaEvXB4uRSZMmzKNLoXvTu1sfx+1kv/DojUlPrSZGs=
github.com/jbenet/go-cienv v0.1.0 h1:Vc/s0QbQtoxX8MwwSLWWh+xNNZvM3Lw7NsTcHrvvhMc=
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
......@@ -180,9 +259,13 @@ github.com/jbenet/goprocess v0.1.3 h1:YKyIEECS/XvcfHtBzxtjBBbWK+MbvA6dG8ASiqwvr1
github.com/jbenet/goprocess v0.1.3/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kami-zh/go-capturer v0.0.0-20171211120116-e492ea43421d/go.mod h1:P2viExyCEfeWGU259JnaQ34Inuec4R38JCyBx2edgD0=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 h1:I/yrLt2WilKxlQKCM52clh5rGzTKpVctGT1lH4Dc8Jw=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
......@@ -200,6 +283,7 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/libp2p/go-addr-util v0.0.1 h1:TpTQm9cXVRVSKsYbgQ7GKc3KbbHVTnbostgGaDEP+88=
github.com/libp2p/go-addr-util v0.0.1/go.mod h1:4ac6O7n9rIAKB1dnd+s8IbbMXkt+oBpzX4/+RACcnlQ=
github.com/libp2p/go-buffer-pool v0.0.1/go.mod h1:xtyIz9PMobb13WaxR6Zo1Pd1zXJKYg0a8KiIvDp3TzQ=
......@@ -314,17 +398,28 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329 h1:2gxZ0XQIU/5z3Z3
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4=
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5 h1:tHXDdz1cpzGaovsTB+TVB8q90WEokoVmfMqoVcrLUgw=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/miekg/dns v1.1.12 h1:WMhc1ik4LNkTg8U9l3hI1LvxKmIL+f1+WV/SZtCbDDA=
github.com/miekg/dns v1.1.12/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miguelmota/go-solidity-sha3 v0.1.0 h1:RoRqUD/qKqZCZIoAGVJhX6gEHeD6333uQv+jhBGpRDk=
github.com/miguelmota/go-solidity-sha3 v0.1.0/go.mod h1:FuaBKCJUkJcmPqCuKvPFYfzK1auYGr5+8i2evSBIm/Q=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0OXOcUbGjvZxxijuBwbbmlSxLiuofa+g=
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
......@@ -376,6 +471,12 @@ github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wS
github.com/multiformats/go-varint v0.0.1 h1:TR/0rdQtnNxuN2IhiB639xC3tWM4IUi7DkTBVTdGW/M=
github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c h1:1RHs3tNxjXGHeul8z2t6H2N2TlAqpKe5yryJztRx4Jk=
github.com/olekukonko/tablewriter v0.0.2-0.20190409134802-7e037d187b0c/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
......@@ -385,7 +486,13 @@ github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pborman/uuid v0.0.0-20170112150404-1b00554d8222/go.mod h1:VyrYX9gd7irzKovcSS6BIIEwPRkP2Wm2m9ufcdFSJ34=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
......@@ -398,6 +505,7 @@ github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
......@@ -405,23 +513,36 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.3 h1:CTwfnzjQ+8dS6MhHHu4YswVAD99sL2wjPqP+VkURmKE=
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150 h1:ZeU+auZj1iNzN8iVhff6M38Mfu73FQiJve/GEXYJBjE=
github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
github.com/robertkrimen/otto v0.0.0-20170205013659-6a77b7cbc37d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d h1:1VUlQbCfkoSGv7qP7Y+ro3ap1P1pPZxgdGVqiTVy5C4=
github.com/robertkrimen/otto v0.0.0-20180617131154-15f95af6e78d/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
github.com/rs/xhandler v0.0.0-20160618193221-ed27b6fd6521/go.mod h1:RvLn4FgxWubrpZHtQLnOf6EwhN2hEMusxZOhcW9H3UQ=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smola/gocompat v0.2.0 h1:6b1oIMlUXIpz//VKEDzPVBK8KG7beVwmHIUEBIs/Pns=
github.com/smola/gocompat v0.2.0/go.mod h1:1B0MlxbmoZNo3h8guHp8HztB3BSYR5itql9qtVc0ypY=
github.com/spacemonkeygo/openssl v0.0.0-20181017203307-c2dcc5cca94a/go.mod h1:7AyxJNCJ7SBZ1MfVQCWD6Uqo2oubI2Eq2y2eqf+A5r0=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.0.1-0.20190317074736-539464a789e9/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
github.com/spf13/cobra v0.0.5 h1:f0B+LkLX6DtmRH1isoNA9VTtNUK9K8xYd28JNNfOv/s=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
......@@ -429,6 +550,12 @@ github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/src-d/envconfig v1.0.0/go.mod h1:Q9YQZ7BKITldTBnoxsE5gOeB5y66RyPXeue/R4aaNBc=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570 h1:gIlAHnH1vJb5vwEjIp5kBj/eu99p/bl0Ay2goiPe5xE=
github.com/steakknife/bloomfilter v0.0.0-20180922174646-6819c0d2a570/go.mod h1:8OR4w3TdeIHIh1g6EMY5p0gVNOovcWC+1vpc7naMuAw=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3 h1:njlZPzLwU639dk2kqnCPPv+wNjq7Xb6EfUxe/oX0/NM=
github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUWaI9xL8pRQCTXQgocU38Qw1g0Us7n5PxxTwTCYU=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
......@@ -437,11 +564,17 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/syndtr/goleveldb v0.0.0-20181105012736-f9080354173f/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs=
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8 h1:6CNSDqI1wiE+JqyOy5Qt/yo/DoNI2/QmmOZeiCid2Nw=
github.com/tjfoc/gmsm v0.0.0-20171124023159-98aa888b79d8/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.5.0 h1:dhq+O9pmNZFF6qAXpasMO1xSm7dL4qEz2ylfZN8BG9w=
......@@ -462,6 +595,8 @@ github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9 h1:Y1/FEOpaCpD2
github.com/whyrusleeping/mdns v0.0.0-20190826153040-b9b60ed33aa9/go.mod h1:j4l84WPFclQPj320J9gp0XwNKBb3U0zt5CBqjPp22G4=
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7 h1:E9S12nwJwEOXe2d6gT6qxdvqMnNq+VnSsKPgm2ZZNds=
github.com/whyrusleeping/multiaddr-filter v0.0.0-20160516205228-e903e4adabd7/go.mod h1:X2c0RVCI1eSUFI8eLcY3c0423ykwiUdxLJtkDvruhjI=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8cVcUy5CeIBYhEESkOB7m6Gmkrk=
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/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
......@@ -478,6 +613,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190225124518-7f87c0fbb88b/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
......@@ -485,10 +621,13 @@ golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4 h1:QmwruyY+bKbDDL0BaglrbZABEali68eoMFhTZpCjYVA=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
......@@ -504,6 +643,8 @@ golang.org/x/net v0.0.0-20190227160552-c95aed5357e7/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0=
......@@ -518,6 +659,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
......@@ -527,12 +669,16 @@ golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 h1:xQwXv67TxFo9nC1GJFyab5eq/5B590r6RlnL/G8Sz7w=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
......@@ -553,16 +699,19 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200310143817-43be25429f5a h1:lRlI5zu6AFy3iU/F8YWyNrAmn/tPCnhiTxfwhWb76eU=
google.golang.org/genproto v0.0.0-20200310143817-43be25429f5a/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
......@@ -572,6 +721,9 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy
gopkg.in/go-playground/webhooks.v5 v5.2.0/go.mod h1:LZbya/qLVdbqDR1aKrGuWV6qbia2zCYSR5dpom2SInQ=
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3 h1:AFxeG48hTWHhDTQDk/m2gorfVHUEa9vo3tp3D7TzwjI=
gopkg.in/natefinch/lumberjack.v2 v2.0.0-20170531160350-a96e63847dc3/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200316214253-d7b0ff38cac9/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/src-d/go-cli.v0 v0.0.0-20181105080154-d492247bbc0d/go.mod h1:z+K8VcOYVYcSwSjGebuDL6176A1XskgbtNl64NSg+n8=
......@@ -580,8 +732,10 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637 h1:yiW+nvdHb9LVqSHQBXfZCieqV4fzYhNBql77zY0ykqs=
gopkg.in/tomb.v2 v2.0.0-20161208151619-d5d1b5820637/go.mod h1:BHsqpu/nsuzkT5BpiH1EMZPLyqSMM8JbIavyFACoFNk=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
......@@ -30,4 +30,5 @@ import (
_ "github.com/33cn/plugin/plugin/dapp/trade" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/unfreeze" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/valnode" //auto gen
_ "github.com/33cn/plugin/plugin/dapp/x2ethereum" //auto gen
)
# golang1.12 or latest
# 1. make help
# 2. make dep
# 3. make build
# ...
SRC_EBCLI := github.com/33cn/plugin/plugin/dapp/x2ethereum/ebcli
SRC_EBRELAYER := github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer
CLI_A := build/ebcli_A
CLI_B := build/ebcli_B
CLI_C := build/ebcli_C
CLI_D := build/ebcli_D
EBRELAER := build/ebrelayer ##通过配置文件启动不同的ebrelayer
LDFLAGS := -ldflags "-w -s"
proj := "build"
.PHONY: default dep all build release cli linter race test fmt vet bench msan coverage coverhtml docker docker-compose protobuf clean help autotest
default: build
build:
@go build -v -i -o $(EBRELAER) $(SRC_EBRELAYER)
@go build -v -i -o $(CLI_A) $(SRC_EBCLI)
@go build -v -i -o $(CLI_B) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9902" $(SRC_EBCLI)
@go build -v -i -o $(CLI_C) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9903" $(SRC_EBCLI)
@go build -v -i -o $(CLI_D) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9904" $(SRC_EBCLI)
@cp ebrelayer/relayer.toml build/
rebuild:
make -C ebrelayer/ethcontract
make build
cli:
@go build -v -i -o $(CLI_A) $(SRC_EBCLI)
@go build -v -i -o $(CLI_B) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9902" $(SRC_EBCLI)
@go build -v -i -o $(CLI_C) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9903" $(SRC_EBCLI)
@go build -v -i -o $(CLI_D) -ldflags "-X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:9904" $(SRC_EBCLI)
build_ci: depends ## Build the binary file for CI
@go build -v -i -o $(CLI) $(SRC_EBCLI)
@go build $(BUILD_FLAGS) -v -o $(APP)
@cp chain33.toml build/
para:
@go build -v -o build/$(NAME) -ldflags "-X $(SRC_EBCLI)/buildflags.ParaName=user.p.$(NAME). -X $(SRC_EBCLI)/buildflags.RPCAddr=http://localhost:8901" $(SRC_EBCLI)
vet:
@go vet ${PKG_LIST_VET}
race: ## Run data race detector
@go test -race -short $(PKG_LIST)
test: ## Run unittests
@go test -race $(PKG_LIST)
fmt: fmt_proto fmt_shell ## go fmt
@go fmt ./...
@find . -name '*.go' -not -path "./vendor/*" | xargs goimports -l -w
.PHONY: fmt_proto fmt_shell
fmt_proto: ## go fmt protobuf file
#@find . -name '*.proto' -not -path "./vendor/*" | xargs clang-format -i
fmt_shell: ## check shell file
@find . -name '*.sh' -not -path "./vendor/*" | xargs shfmt -w -s -i 4 -ci -bn
fmt_go: fmt_shell ## go fmt
@go fmt ./...
@find . -name '*.go' -not -path "./vendor/*" | xargs goimports -l -w
docker: ## build docker image for chain33 run
@sudo docker build . -f ./build/Dockerfile-run -t chain33:latest
docker-compose: ## build docker-compose for chain33 run
@cd build && if ! [ -d ci ]; then \
make -C ../ ; \
fi; \
cp chain33* Dockerfile docker-compose* ci/ && cd ci/ && ./docker-compose-pre.sh run $(proj) $(dapp) && cd ../..
docker-compose-down: ## build docker-compose for chain33 run
@cd build && if [ -d ci ]; then \
cp chain33* Dockerfile docker-compose* ci/ && cd ci/ && ./docker-compose-pre.sh down $(proj) $(dapp) && cd .. ; \
fi; \
cd ..
clean: ## remove all the bins
@rm -rf $(CLI_A)
@rm -rf $(CLI_B)
@rm -rf $(CLI_C)
@rm -rf $(CLI_D)
@rm -rf $(EBRELAER)
@rm -rf build/*.toml
proto:protobuf
protobuf: ## Generate protbuf file of types package
# @cd ${CHAIN33_PATH}/types/proto && ./create_protobuf.sh && cd ../..
@find ./plugin/dapp -maxdepth 2 -type d -name proto -exec make -C {} \;
help: ## Display this help screen
@printf "Help doc:\nUsage: make [command]\n"
@printf "[command]\n"
@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
cleandata:
rm -rf build/datadir/addrbook
rm -rf build/datadir/blockchain.db
rm -rf build/datadir/mavltree
rm -rf build/chain33.log
.PHONY: checkgofmt
checkgofmt: ## get all go files and run go fmt on them
@files=$$(find . -name '*.go' -not -path "./vendor/*" | xargs gofmt -l -s); if [ -n "$$files" ]; then \
echo "Error: 'make fmt' needs to be run on:"; \
echo "${files}"; \
exit 1; \
fi;
@files=$$(find . -name '*.go' -not -path "./vendor/*" | xargs goimports -l -w); if [ -n "$$files" ]; then \
echo "Error: 'make fmt' needs to be run on:"; \
echo "${files}"; \
exit 1; \
fi;
all:
chmod +x ./build.sh
./build.sh $(OUT) $(FLAG)
#!/usr/bin/env bash
# 官方ci集成脚本
strpwd=$(pwd)
strcmd=${strpwd##*dapp/}
strapp=${strcmd%/cmd*}
SRC_EBCLI=github.com/33cn/plugin/plugin/dapp/x2ethereum/ebcli
SRC_EBRELAYER=github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer
OUT_DIR="${1}/$strapp"
FLAG=$2
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebrelayer" "${SRC_EBRELAYER}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_A" "${SRC_EBCLI}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_B" -ldflags "-X ${SRC_EBCLI}/buildflags.RPCAddr=http://localhost:9902" "${SRC_EBCLI}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_C" -ldflags "-X ${SRC_EBCLI}/buildflags.RPCAddr=http://localhost:9903" "${SRC_EBCLI}"
# shellcheck disable=SC2086,1072
go build -i ${FLAG} -v -o "${OUT_DIR}/ebcli_D" -ldflags "-X ${SRC_EBCLI}/buildflags.RPCAddr=http://localhost:9904" "${SRC_EBCLI}"
cp ../ebrelayer/relayer.toml "${OUT_DIR}/relayer.toml"
cp ./build/* "${OUT_DIR}"
OUT_TESTDIR="${1}/dapptest/$strapp"
mkdir -p "${OUT_TESTDIR}"
cp ./test/* "${OUT_TESTDIR}"
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
# 测试前请先阅读文档,对代码进行修改 http://note.youdao.com/noteshare?id=675ce9a1162b6639182206864985e935&sub=14A1CFAA14CB4318B207EAEC94991A93
set -x
set +e
source "./publicTest.sh"
CLIA="./ebcli_A"
CLIB="./ebcli_B"
CLIC="./ebcli_C"
CLID="./ebcli_D"
chain33SenderAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
# validatorsAddr=["0x92c8b16afd6d423652559c6e266cbe1c29bfd84f", "0x0df9a824699bc5878232c9e612fe1a5346a5a368", "0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1", "0xd9dab021e74ecf475788ed7b61356056b2095830"]
ethValidatorAddrKeyA="3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
ethValidatorAddrKeyB="a5f3063552f4483cfc20ac4f40f45b798791379862219de9e915c64722c1d400"
ethValidatorAddrKeyC="bbf5e65539e9af0eb0cfac30bad475111054b09c11d668fc0731d54ea777471e"
ethValidatorAddrKeyD="c9fa31d7984edf81b8ef3b40c761f1847f6fcd5711ab2462da97dc458f1f896b"
# 新增地址 chain33 需要导入地址 转入 10 bty当收费费
chain33Validator1="1GTxrmuWiXavhcvsaH5w9whgVxUrWsUMdV"
chain33Validator2="155ooMPBTF8QQsGAknkK7ei5D78rwDEFe6"
chain33Validator3="13zBdQwuyDh7cKN79oT2odkxYuDbgQiXFv"
chain33Validator4="113ZzVamKfAtGt9dq45fX1mNsEoDiN95HG"
chain33ValidatorKey1="0xd627968e445f2a41c92173225791bae1ba42126ae96c32f28f97ff8f226e5c68"
chain33ValidatorKey2="0x9d539bc5fd084eb7fe86ad631dba9aa086dba38418725c38d9751459f567da66"
chain33ValidatorKey3="0x0a6671f101e30a2cc2d79d77436b62cdf2664ed33eb631a9c9e3f3dd348a23be"
chain33ValidatorKey4="0x3818b257b05ee75b6e43ee0e3cfc2d8502342cf67caed533e3756966690b62a5"
ethReceiverAddr1="0xa4ea64a583f6e51c3799335b28a8f0529570a635"
ethReceiverAddrKey1="355b876d7cbcb930d5dfab767f66336ce327e082cbaa1877210c1bae89b1df71"
ethReceiverAddr2="0x0c05ba5c230fdaa503b53702af1962e08d0c60bf"
ethReceiverAddrKey2="9dc6df3a8ab139a54d8a984f54958ae0661f880229bf3bdbb886b87d58b56a08"
maturityDegree=10
tokenAddrBty=""
function kill_ebrelayerC() {
kill_ebrelayer "./C/ebrelayer"
}
function kill_ebrelayerD() {
kill_ebrelayer "./D/ebrelayer"
}
function start_ebrelayerC() {
start_ebrelayer_and_unlock C
block_wait "${Chain33Cli}" $((maturityDegree + 3))
eth_block_wait 3 https://ropsten-rpc.linkpool.io/
sleep 1
}
function start_ebrelayerD() {
start_ebrelayer_and_unlock D
block_wait "${Chain33Cli}" $((maturityDegree + 3))
eth_block_wait 3 https://ropsten-rpc.linkpool.io/
sleep 1
}
function InitAndDeploy() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
result=$(${CLIA} relayer ethereum deploy)
cli_ret "${result}" "deploy"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function StartRelayerAndDeploy() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
for name in A B C D; do
local ebrelayer="./$name/ebrelayer"
kill_ebrelayer "${ebrelayer}"
done
sleep 1
rm -rf './A' './B' './C' './D' './datadir' './ebrelayer.log' './logs'
mkdir './A' './B' './C' './D'
cp './relayer.toml' './A/relayer.toml'
cp './ebrelayer' './A/ebrelayer'
start_ebrelayer_and_setpwd_unlock A
# 部署合约
InitAndDeploy
# 获取 BridgeRegistry 地址
result=$(${CLIA} relayer ethereum bridgeRegistry)
BridgeRegistry=$(cli_ret "${result}" "bridgeRegistry" ".addr")
# BridgeRegistry="0xcA5E8FCE034888ea51eB568CCA83C413b9DE3F73"
kill_ebrelayer "./A/ebrelayer"
# 修改 relayer.toml 配置文件
updata_relayer_toml_ropston "${BridgeRegistry}" ${maturityDegree} "./A/relayer.toml"
updata_all_relayer_toml2
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# chian33 添加验证着及权重
function InitChain33Vilators() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# 导入 chain33Validators 私钥生成地址
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey1} -l validator1)
check_addr "${result}" ${chain33Validator1}
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey2} -l validator2)
check_addr "${result}" ${chain33Validator2}
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey3} -l validator3)
check_addr "${result}" ${chain33Validator3}
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey4} -l validator4)
check_addr "${result}" ${chain33Validator4}
# SetConsensusThreshold
hash=$(${Chain33Cli} send x2ethereum setconsensus -p 80 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
# add a validator
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator1} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator2} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator3} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator4} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
# query Validators
totalPower=$(${Chain33Cli} send x2ethereum query totalpower -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv | jq .totalPower | sed 's/\"//g')
check_number 100 "${totalPower}"
# cions 转帐到 x2ethereum 合约地址
hash=$(${Chain33Cli} send coins send_exec -e x2ethereum -a 200 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum)
balance_ret "${result}" "200.0000"
# chain33Validator 要有手续费
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator1}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator1}" -e coins)
balance_ret "${result}" "10.0000"
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator2}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator2}" -e coins)
balance_ret "${result}" "10.0000"
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator3}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator3}" -e coins)
balance_ret "${result}" "10.0000"
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator4}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator4}" -e coins)
balance_ret "${result}" "10.0000"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function StartAllEbrelayer() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
start_ebrelayer_and_unlock A
# 重启 ebrelayer 并解锁
for name in B C D; do
start_ebrelayer_and_setpwd_unlock $name
done
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function EthImportKey() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
result=$(${CLIA} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey1}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLIB} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey2}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLIC} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey3}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLID} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey4}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLIA} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyA}")
cli_ret "${result}" "A relayer chain33 import_privatekey"
result=$(${CLIB} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyB}")
cli_ret "${result}" "B relayer chain33 import_privatekey"
result=$(${CLIC} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyC}")
cli_ret "${result}" "C relayer chain33 import_privatekey"
result=$(${CLID} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyD}")
cli_ret "${result}" "D relayer chain33 import_privatekey"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestChain33ToEthAssets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# token4chain33 在 以太坊 上先有 bty
tokenSymbol="coins.bty"
result=$(${CLIA} relayer ethereum token4chain33 -s "${tokenSymbol}")
tokenAddrBty=$(cli_ret "${result}" "token4chain33" ".addr")
#tokenAddrBty="0xE79142B3171019fcfcA838f0792edB08d4F2a94F"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
# chain33 lock bty
hash=$(${Chain33Cli} send x2ethereum lock -a 5 -t "${tokenSymbol}" -r ${ethReceiverAddr1} -q "${tokenAddrBty}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 3))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum)
balance_ret "${result}" "195.0000"
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "5"
# eth burn
result=$(${CLIA} relayer ethereum burn -m 5 -k "${ethReceiverAddrKey1}" -r "${chain33SenderAddr}" -t "${tokenAddrBty}")
cli_ret "${result}" "burn"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
result=$(${Chain33Cli} account balance -a "${chain33SenderAddr}" -e x2ethereum)
balance_ret "${result}" "5"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# eth to chain33
# 在以太坊上锁定资产,然后在 chain33 上铸币,针对 eth 资产
function TestETH2Chain33Assets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0"
# eth lock 0.1
result=$(${CLIA} relayer ethereum lock -m 0.1 -k "${ethReceiverAddrKey1}" -r 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0.1"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0.1"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
balance=$(cli_ret "${result}" "balance" ".balance")
hash=$(${Chain33Cli} send x2ethereum burn -a 0.1 -t eth -r ${ethReceiverAddr2} -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 3))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2 https://ropsten-rpc.linkpool.io/
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
cli_ret "${result}" "balance" ".balance" "$(echo "${balance}+0.1" | bc)"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestETH2Chain33Erc20() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
# token4erc20 在 chain33 上先有 token,同时 mint
tokenSymbol="testc"
result=$(${CLIA} relayer ethereum token4erc20 -s "${tokenSymbol}")
tokenAddr=$(cli_ret "${result}" "token4erc20" ".addr")
#tokenAddr="0x47F62ba65bCa4150BE98F31566DC559b9b04fc2D"
# 先铸币 1000
result=$(${CLIA} relayer ethereum mint -m 1000 -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "mint"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "1000"
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
# lock 100
result=$(${CLIA} relayer ethereum lock -m 100 -k "${ethReceiverAddrKey1}" -r "${chain33Validator1}" -t "${tokenAddr}")
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "900"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "100"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr}" | jq ".res" | jq ".[]")
balance_ret "${result}" "100"
# chain33 burn 100
hash=$(${Chain33Cli} send x2ethereum burn -a 100 -t "${tokenSymbol}" -r ${ethReceiverAddr2} -q "${tokenAddr}" -k "${chain33Validator1}")
block_wait "${Chain33Cli}" $((maturityDegree + 3))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr}" | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2 https://ropsten-rpc.linkpool.io/
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "100"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestChain33ToEthAssetsKill() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
tokenSymbol="coins.bty"
if [ "${tokenAddrBty}" == "" ]; then
# token4chain33 在 以太坊 上先有 bty
result=$(${CLIA} relayer ethereum token4chain33 -s "${tokenSymbol}")
tokenAddrBty=$(cli_ret "${result}" "token4chain33" ".addr")
fi
# tokenAddrBty="0xE79142B3171019fcfcA838f0792edB08d4F2a94F"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
kill_ebrelayerC
kill_ebrelayerD
# chain33 lock bty
hash=$(${Chain33Cli} send x2ethereum lock -a 1.41 -t "${tokenSymbol}" -r ${ethReceiverAddr2} -q "${tokenAddrBty}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 3))
check_tx "${Chain33Cli}" "${hash}"
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
start_ebrelayerC
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "1.41"
# eth burn
result=$(${CLIA} relayer ethereum burn -m 1.41 -k "${ethReceiverAddrKey2}" -r "${chain33Validator1}" -t "${tokenAddrBty}")
cli_ret "${result}" "burn"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
result=$(${Chain33Cli} account balance -a "${chain33Validator1}" -e x2ethereum)
balance_ret "${result}" "0"
start_ebrelayerD
result=$(${Chain33Cli} account balance -a "${chain33Validator1}" -e x2ethereum)
balance_ret "${result}" "1.41"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# eth to chain33
# 在以太坊上锁定资产,然后在 chain33 上铸币,针对 eth 资产
function TestETH2Chain33AssetsKill() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
balance=$(cli_ret "${result}" "balance" ".balance")
kill_ebrelayerC
kill_ebrelayerD
# eth lock 0.1
result=$(${CLIA} relayer ethereum lock -m 0.133 -k "${ethReceiverAddrKey1}" -r 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "$(echo "${balance}+0.133" | bc)"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
balance=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]" | jq -r ".balance")
balance_ret "${result}" "0"
start_ebrelayerC
start_ebrelayerD
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]" | jq -r ".balance")
balance_ret "${result}" "0.133"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
balance=$(cli_ret "${result}" "balance" ".balance")
kill_ebrelayerC
kill_ebrelayerD
hash=$(${Chain33Cli} send x2ethereum burn -a 0.133 -t eth -r ${ethReceiverAddr2} -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 3))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2 https://ropsten-rpc.linkpool.io/
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0.133"
start_ebrelayerC
start_ebrelayerD
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
cli_ret "${result}" "balance" ".balance" "$(echo "${balance}+0.133" | bc)"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestETH2Chain33Erc20Kill() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
# token4erc20 在 chain33 上先有 token,同时 mint
tokenSymbol="testcc"
result=$(${CLIA} relayer ethereum token4erc20 -s "${tokenSymbol}")
tokenAddr=$(cli_ret "${result}" "token4erc20" ".addr")
# 先铸币 1000
result=$(${CLIA} relayer ethereum mint -m 1000 -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "mint"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "1000"
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
kill_ebrelayerC
kill_ebrelayerD
# lock 100
result=$(${CLIA} relayer ethereum lock -m 100 -k "${ethReceiverAddrKey1}" -r "${chain33Validator1}" -t "${tokenAddr}")
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "900"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "100"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 3)) https://ropsten-rpc.linkpool.io/
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr}" | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
start_ebrelayerC
start_ebrelayerD
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr}" | jq ".res" | jq ".[]")
balance_ret "${result}" "100"
kill_ebrelayerC
kill_ebrelayerD
# chain33 burn 100
hash=$(${Chain33Cli} send x2ethereum burn -a 100 -t "${tokenSymbol}" -r ${ethReceiverAddr2} -q "${tokenAddr}" -k "${chain33Validator1}")
block_wait "${Chain33Cli}" $((maturityDegree + 3))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr}" | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2 https://ropsten-rpc.linkpool.io/
start_ebrelayerC
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "100"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function AllRelayerMainTest() {
set +e
# docker cp ${GOPATH}/src/github.com/33cn/plugin/build/ci/x2ethereum build_chain33_1:/root/x2ethereum
# docker cp ${GOPATH}/src/github.com/33cn/plugin/plugin/dapp/x2ethereum/cmd/build/RopstenTest.sh build_chain33_1:/root/x2ethereum/RopstenTest.sh
Chain33Cli="./../chain33-cli"
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
if [[ ${1} != "" ]]; then
maturityDegree=${1}
echo -e "${GRE}maturityDegree is ${maturityDegree} ${NOC}"
fi
# init
StartRelayerAndDeploy
InitChain33Vilators
StartAllEbrelayer
EthImportKey
# test
TestChain33ToEthAssets
TestETH2Chain33Assets
TestETH2Chain33Erc20
# kill relayer and start relayer
TestChain33ToEthAssetsKill
TestETH2Chain33AssetsKill
TestETH2Chain33Erc20Kill
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
AllRelayerMainTest 1
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
set -x
set +e
source "./publicTest.sh"
CLIA="./ebcli_A"
CLIB="./ebcli_B"
CLIC="./ebcli_C"
CLID="./ebcli_D"
docker_chain33_ip=""
Chain33Cli=""
Chain33Cli="docker exec ${NODE3} /root/chain33-cli"
chain33SenderAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
# validatorsAddr=["0x92c8b16afd6d423652559c6e266cbe1c29bfd84f", "0x0df9a824699bc5878232c9e612fe1a5346a5a368", "0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1", "0xd9dab021e74ecf475788ed7b61356056b2095830"]
ethValidatorAddrKeyA="3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
ethValidatorAddrKeyB="a5f3063552f4483cfc20ac4f40f45b798791379862219de9e915c64722c1d400"
ethValidatorAddrKeyC="bbf5e65539e9af0eb0cfac30bad475111054b09c11d668fc0731d54ea777471e"
ethValidatorAddrKeyD="c9fa31d7984edf81b8ef3b40c761f1847f6fcd5711ab2462da97dc458f1f896b"
# 新增地址 chain33 需要导入地址 转入 10 bty当收费费
chain33Validator1="1GTxrmuWiXavhcvsaH5w9whgVxUrWsUMdV"
chain33Validator2="155ooMPBTF8QQsGAknkK7ei5D78rwDEFe6"
chain33Validator3="13zBdQwuyDh7cKN79oT2odkxYuDbgQiXFv"
chain33Validator4="113ZzVamKfAtGt9dq45fX1mNsEoDiN95HG"
chain33ValidatorKey1="0xd627968e445f2a41c92173225791bae1ba42126ae96c32f28f97ff8f226e5c68"
chain33ValidatorKey2="0x9d539bc5fd084eb7fe86ad631dba9aa086dba38418725c38d9751459f567da66"
chain33ValidatorKey3="0x0a6671f101e30a2cc2d79d77436b62cdf2664ed33eb631a9c9e3f3dd348a23be"
chain33ValidatorKey4="0x3818b257b05ee75b6e43ee0e3cfc2d8502342cf67caed533e3756966690b62a5"
ethReceiverAddr1="0xa4ea64a583f6e51c3799335b28a8f0529570a635"
ethReceiverAddrKey1="355b876d7cbcb930d5dfab767f66336ce327e082cbaa1877210c1bae89b1df71"
ethReceiverAddr2="0x0c05ba5c230fdaa503b53702af1962e08d0c60bf"
ethReceiverAddrKey2="9dc6df3a8ab139a54d8a984f54958ae0661f880229bf3bdbb886b87d58b56a08"
maturityDegree=10
tokenAddrBty=""
tokenAddr=""
function kill_ebrelayerC() {
kill_ebrelayer "./C/ebrelayer"
}
function kill_ebrelayerD() {
kill_ebrelayer "./D/ebrelayer"
}
function start_ebrelayerC() {
start_ebrelayer "./C/ebrelayer" "./C/ebrelayer.log"
${CLIC} relayer unlock -p 123456hzj
sleep 5
eth_block_wait $((maturityDegree + 2))
sleep 10
}
function start_ebrelayerD() {
start_ebrelayer "./D/ebrelayer" "./D/ebrelayer.log"
${CLID} relayer unlock -p 123456hzj
sleep 5
eth_block_wait $((maturityDegree + 2))
sleep 10
}
function InitAndDeploy() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
result=$(${CLIA} relayer set_pwd -p 123456hzj)
cli_ret "${result}" "set_pwd"
result=$(${CLIA} relayer unlock -p 123456hzj)
cli_ret "${result}" "unlock"
result=$(${CLIA} relayer ethereum deploy)
cli_ret "${result}" "deploy"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function EthImportKey() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# 重启 ebrelayer 并解锁
for name in A B C D; do
start_ebrelayer "./$name/ebrelayer" "./$name/ebrelayer.log"
# 导入测试地址私钥
CLI="./ebcli_$name"
result=$(${CLI} relayer set_pwd -p 123456hzj)
result=$(${CLI} relayer unlock -p 123456hzj)
cli_ret "${result}" "unlock"
done
result=$(${CLIA} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey1}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLIB} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey2}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLIC} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey3}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLID} relayer ethereum import_chain33privatekey -k "${chain33ValidatorKey4}")
cli_ret "${result}" "import_chain33privatekey"
result=$(${CLIA} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyA}")
cli_ret "${result}" "A relayer chain33 import_privatekey"
result=$(${CLIB} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyB}")
cli_ret "${result}" "B relayer chain33 import_privatekey"
result=$(${CLIC} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyC}")
cli_ret "${result}" "C relayer chain33 import_privatekey"
result=$(${CLID} relayer chain33 import_privatekey -k "${ethValidatorAddrKeyD}")
cli_ret "${result}" "D relayer chain33 import_privatekey"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function StartRelayerAndDeploy() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
for name in A B C D; do
local ebrelayer="./$name/ebrelayer"
kill_ebrelayer "${ebrelayer}"
done
sleep 1
rm -rf './A' './B' './C' './D' './datadir' './ebrelayer.log' './logs'
mkdir './A' './B' './C' './D'
cp './relayer.toml' './A/relayer.toml'
cp './ebrelayer' './A/ebrelayer'
start_trufflesuite
start_ebrelayer "./A/ebrelayer" "./A/ebrelayer.log"
# 部署合约
InitAndDeploy
# 获取 BridgeRegistry 地址
result=$(${CLIA} relayer ethereum bridgeRegistry)
BridgeRegistry=$(cli_ret "${result}" "bridgeRegistry" ".addr")
kill_ebrelayer "./A/ebrelayer"
# 修改 relayer.toml 配置文件
updata_relayer_toml "${BridgeRegistry}" ${maturityDegree} "./A/relayer.toml"
updata_all_relayer_toml2
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# chian33 添加验证着及权重
function InitChain33Vilators() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# 导入 chain33Validators 私钥生成地址
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey1} -l validator1)
check_addr "${result}" ${chain33Validator1}
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey2} -l validator2)
check_addr "${result}" ${chain33Validator2}
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey3} -l validator3)
check_addr "${result}" ${chain33Validator3}
result=$(${Chain33Cli} account import_key -k ${chain33ValidatorKey4} -l validator4)
check_addr "${result}" ${chain33Validator4}
# SetConsensusThreshold
hash=$(${Chain33Cli} send x2ethereum setconsensus -p 80 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
# add a validator
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator1} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator2} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator3} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
hash=$(${Chain33Cli} send x2ethereum add -a ${chain33Validator4} -p 25 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
# query Validators
totalPower=$(${Chain33Cli} send x2ethereum query totalpower -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv | jq .totalPower | sed 's/\"//g')
check_number 100 "${totalPower}"
# cions 转帐到 x2ethereum 合约地址
hash=$(${Chain33Cli} send coins send_exec -e x2ethereum -a 200 -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum)
balance_ret "${result}" "200.0000"
# chain33Validator 要有手续费
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator1}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator1}" -e coins)
balance_ret "${result}" "10.0000"
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator2}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator2}" -e coins)
balance_ret "${result}" "10.0000"
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator3}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator3}" -e coins)
balance_ret "${result}" "10.0000"
hash=$(${Chain33Cli} send coins transfer -a 10 -t "${chain33Validator4}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a "${chain33Validator4}" -e coins)
balance_ret "${result}" "10.0000"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestChain33ToEthAssets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
# token4chain33 在 以太坊 上先有 bty
result=$(${CLIA} relayer ethereum token4chain33 -s coins.bty)
tokenAddrBty=$(cli_ret "${result}" "token4chain33" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
# chain33 lock bty
hash=$(${Chain33Cli} send x2ethereum lock -a 5 -t coins.bty -r ${ethReceiverAddr1} -q "${tokenAddrBty}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 2))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum)
balance_ret "${result}" "195.0000"
eth_block_wait $((maturityDegree + 2))
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "5"
# eth burn
result=$(${CLIA} relayer ethereum burn -m 5 -k "${ethReceiverAddrKey1}" -r "${chain33SenderAddr}" -t "${tokenAddrBty}")
cli_ret "${result}" "burn"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 2))
result=$(${Chain33Cli} account balance -a "${chain33SenderAddr}" -e x2ethereum)
balance_ret "${result}" "5"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# eth to chain33
# 在以太坊上锁定资产,然后在 chain33 上铸币,针对 eth 资产
function TestETH2Chain33Assets() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0"
# eth lock 0.1
result=$(${CLIA} relayer ethereum lock -m 0.1 -k "${ethReceiverAddrKey1}" -r 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0.1"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 2))
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0.1"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
balance=$(cli_ret "${result}" "balance" ".balance")
hash=$(${Chain33Cli} send x2ethereum burn -a 0.1 -t eth -r ${ethReceiverAddr2} -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 2))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
cli_ret "${result}" "balance" ".balance" "$(echo "${balance}+0.1" | bc)"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestETH2Chain33Erc20() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
# token4erc20 在 chain33 上先有 token,同时 mint
tokenSymbol="testc"
result=$(${CLIA} relayer ethereum token4erc20 -s "${tokenSymbol}")
tokenAddr=$(cli_ret "${result}" "token4erc20" ".addr")
# 先铸币 1000
result=$(${CLIA} relayer ethereum mint -m 1000 -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "mint"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "1000"
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
# lock 100
result=$(${CLIA} relayer ethereum lock -m 100 -k "${ethReceiverAddrKey1}" -r "${chain33Validator1}" -t "${tokenAddr}")
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "900"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "100"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 2))
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr}" | jq ".res" | jq ".[]")
balance_ret "${result}" "100"
# chain33 burn 100
hash=$(${Chain33Cli} send x2ethereum burn -a 100 -t "${tokenSymbol}" -r ${ethReceiverAddr2} -q "${tokenAddr}" -k "${chain33Validator1}")
block_wait "${Chain33Cli}" $((maturityDegree + 2))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr}" | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "100"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr}")
cli_ret "${result}" "balance" ".balance" "0"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestChain33ToEthAssetsKill() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
if [ "${tokenAddrBty}" == "" ]; then
# token4chain33 在 以太坊 上先有 bty
result=$(${CLIA} relayer ethereum token4chain33 -s coins.bty)
tokenAddrBty=$(cli_ret "${result}" "token4chain33" ".addr")
fi
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
kill_ebrelayerC
kill_ebrelayerD
# chain33 lock bty
hash=$(${Chain33Cli} send x2ethereum lock -a 5 -t coins.bty -r ${ethReceiverAddr2} -q "${tokenAddrBty}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 2))
check_tx "${Chain33Cli}" "${hash}"
eth_block_wait $((maturityDegree + 2))
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
start_ebrelayerC
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "5"
# eth burn
result=$(${CLIA} relayer ethereum burn -m 5 -k "${ethReceiverAddrKey2}" -r "${chain33Validator1}" -t "${tokenAddrBty}")
cli_ret "${result}" "burn"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddrBty}")
cli_ret "${result}" "balance" ".balance" "0"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 2))
result=$(${Chain33Cli} account balance -a "${chain33Validator1}" -e x2ethereum)
balance_ret "${result}" "0"
start_ebrelayerD
result=$(${Chain33Cli} account balance -a "${chain33Validator1}" -e x2ethereum)
balance_ret "${result}" "5"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
# eth to chain33
# 在以太坊上锁定资产,然后在 chain33 上铸币,针对 eth 资产
function TestETH2Chain33AssetsKill() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0"
kill_ebrelayerC
kill_ebrelayerD
# eth lock 0.1
result=$(${CLIA} relayer ethereum lock -m 0.1 -k "${ethReceiverAddrKey1}" -r 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0.1"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 2))
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
start_ebrelayerC
start_ebrelayerD
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0.1"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
balance=$(cli_ret "${result}" "balance" ".balance")
kill_ebrelayerC
kill_ebrelayerD
hash=$(${Chain33Cli} send x2ethereum burn -a 0.1 -t eth -r ${ethReceiverAddr2} -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
block_wait "${Chain33Cli}" $((maturityDegree + 2))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}")
cli_ret "${result}" "balance" ".balance" "0.1"
start_ebrelayerC
start_ebrelayerD
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}")
cli_ret "${result}" "balance" ".balance" "$(echo "${balance}+0.1" | bc)"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function TestETH2Chain33Erc20Kill() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
${CLIA} relayer unlock -p 123456hzj
# token4erc20 在 chain33 上先有 token,同时 mint
tokenSymbol="testcc"
result=$(${CLIA} relayer ethereum token4erc20 -s "${tokenSymbol}")
tokenAddr2=$(cli_ret "${result}" "token4erc20" ".addr")
# 先铸币 1000
result=$(${CLIA} relayer ethereum mint -m 1000 -o "${ethReceiverAddr1}" -t "${tokenAddr2}")
cli_ret "${result}" "mint"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr2}")
cli_ret "${result}" "balance" ".balance" "1000"
result=$(${CLIA} relayer ethereum bridgeBankAddr)
bridgeBankAddr=$(cli_ret "${result}" "bridgeBankAddr" ".addr")
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr2}")
cli_ret "${result}" "balance" ".balance" "0"
kill_ebrelayerC
kill_ebrelayerD
# lock 100
result=$(${CLIA} relayer ethereum lock -m 100 -k "${ethReceiverAddrKey1}" -r "${chain33Validator1}" -t "${tokenAddr2}")
cli_ret "${result}" "lock"
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr1}" -t "${tokenAddr2}")
cli_ret "${result}" "balance" ".balance" "900"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr2}")
cli_ret "${result}" "balance" ".balance" "100"
# eth 等待 10 个区块
eth_block_wait $((maturityDegree + 2))
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr2}" | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
start_ebrelayerC
start_ebrelayerD
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr2}" | jq ".res" | jq ".[]")
balance_ret "${result}" "100"
kill_ebrelayerC
kill_ebrelayerD
# chain33 burn 100
hash=$(${Chain33Cli} send x2ethereum burn -a 100 -t "${tokenSymbol}" -r ${ethReceiverAddr2} -q "${tokenAddr2}" -k "${chain33Validator1}")
block_wait "${Chain33Cli}" $((maturityDegree + 2))
check_tx "${Chain33Cli}" "${hash}"
result=$(${Chain33Cli} x2ethereum balance -s "${chain33Validator1}" -t "${tokenSymbol}" -a "${tokenAddr2}" | jq ".res" | jq ".[]")
balance_ret "${result}" "0"
eth_block_wait 2
start_ebrelayerC
start_ebrelayerD
result=$(${CLIA} relayer ethereum balance -o "${ethReceiverAddr2}" -t "${tokenAddr2}")
cli_ret "${result}" "balance" ".balance" "100"
result=$(${CLIA} relayer ethereum balance -o "${bridgeBankAddr}" -t "${tokenAddr2}")
cli_ret "${result}" "balance" ".balance" "0"
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
function AllRelayerMainTest() {
set +e
docker_chain33_ip=$(docker inspect "${NODE3}" | jq ".[].NetworkSettings.Networks" | grep "IPAddress" | awk '{ print $2}' | sed 's/\"//g' | sed 's/,//g')
Chain33Cli="$GOPATH/src/github.com/33cn/plugin/build/chain33-cli --rpc_laddr http://${docker_chain33_ip}:8801"
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
if [[ ${1} != "" ]]; then
maturityDegree=${1}
echo -e "${GRE}maturityDegree is ${maturityDegree} ${NOC}"
fi
# init
StartRelayerAndDeploy
InitChain33Vilators
EthImportKey
# test
TestChain33ToEthAssets
TestETH2Chain33Assets
TestETH2Chain33Erc20
# kill relayer and start relayer
TestChain33ToEthAssetsKill
TestETH2Chain33AssetsKill
TestETH2Chain33Erc20Kill
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
version: '3'
#services:
# ganachetest:
# build:
# context: .
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
# shellcheck disable=SC2178
set -x
source "./publicTest.sh"
source "./allRelayerTest.sh"
CLIA="./ebcli_A"
Chain33_CLI=""
Ethsender="0xa4ea64a583f6e51c3799335b28a8f0529570a635"
privateKeys[0]="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
privateKeys[1]="3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
privateKeys[2]="1385016736f7379884763f4a39811d1391fa156a7ca017be6afffa52bb327695"
privateKeys[3]="4ae589fe3837dcfc90d1c85b8423dc30841525cbebc41dfb537868b0f8376bbf"
privateKeys[4]="62ca4122aac0e6f35bed02fc15c7ddbdaa07f2f2a1821c8b8210b891051e3ee9"
privateKeys[5]="355b876d7cbcb930d5dfab767f66336ce327e082cbaa1877210c1bae89b1df71"
privateKeys[6]="9dc6df3a8ab139a54d8a984f54958ae0661f880229bf3bdbb886b87d58b56a08"
ethAddress[0]="0x8AFDADFC88a1087c9A1D6c0F5Dd04634b87F303a"
ethAddress[1]="0x92C8b16aFD6d423652559C6E266cBE1c29Bfd84f"
ethAddress[2]="0xdb15E7327aDc83F2878624bBD6307f5Af1B477b4"
ethAddress[3]="0x9cBA1fF8D0b0c9Bc95d5762533F8CddBE795f687"
ethAddress[4]="0x1919203bA8b325278d28Fb8fFeac49F2CD881A4e"
ethAddress[5]="0xA4Ea64a583F6e51C3799335b28a8F0529570A635"
ethAddress[6]="0x0C05bA5c230fDaA503b53702aF1962e08D0C60BF"
maturityDegree=10
tokenAddr=""
tokenAddrBty=""
loop_send_lock_eth() {
# while 遍历数组
echo -e "${GRE}=========== Ethereum Lock begin ===========${NOC}"
preChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
preEthBalance[$i]=$(curl -ksd '{"jsonrpc":"2.0","method":"eth_getBalance","params":["'${ethAddress[i]}'", "latest"],"id":1}' http://localhost:7545 | jq -r ".result")
ethTxHash=$(${CLIA} relayer ethereum lock-async -m 1 -k "${privateKeys[i]}" -r 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
echo ${i} "lock-async tx hash:" "${ethTxHash}"
# shellcheck disable=SC2219
let i++
done
eth_block_wait $((maturityDegree + 2))
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
nowEthBalance=$(curl -ksd '{"jsonrpc":"2.0","method":"eth_getBalance","params":["'${ethAddress[i]}'", "latest"],"id":1}' http://localhost:7545 | jq -r ".result")
res=$((preEthBalance[i] - nowEthBalance))
echo ${i} "preBalance" "${preEthBalance[i]}" "nowBalance" "${nowEthBalance}" "diff" ${res}
if [[ $res -le 100000000000000000 ]]; then
echo -e "${RED}error number, expect greater than 100000000000000000, get ${res}${NOC}"
exit 1
fi
# shellcheck disable=SC2219
let i++
done
nowChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
diff=$(echo "$nowChain33Balance - $preChain33Balance" | bc)
check_number "${diff}" 7
}
loop_send_burn_eth() {
echo -e "${GRE}=========== Chain33 Burn begin ===========${NOC}"
preChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
preEthBalance[$i]=$(curl -ksd '{"jsonrpc":"2.0","method":"eth_getBalance","params":["'${ethAddress[i]}'", "latest"],"id":1}' http://localhost:7545 | jq -r ".result")
ethTxHash=$(${Chain33_CLI} send x2ethereum burn -a 1 -r ${ethAddress[i]} -t eth -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
echo ${i} "burn chain33 tx hash:" "${ethTxHash}"
# shellcheck disable=SC2219
let i++
done
eth_block_wait $((maturityDegree + 2))
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
nowEthBalance=$(curl -ksd '{"jsonrpc":"2.0","method":"eth_getBalance","params":["'${ethAddress[i]}'", "latest"],"id":1}' http://localhost:7545 | jq -r ".result")
res=$((nowEthBalance - preEthBalance[i]))
echo ${i} "preBalance" "${preEthBalance[i]}" "nowBalance" "${nowEthBalance}" "diff" ${res}
if [[ $res -gt 1000000000000000000 ]]; then
echo -e "${RED}error number, expect greater than 1000000000000000000, get ${res}${NOC}"
exit 1
fi
# shellcheck disable=SC2219
let i++
done
nowChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t eth | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
diff=$(echo "$preChain33Balance - $nowChain33Balance" | bc)
check_number "${diff}" 7
}
loop_send_lock_bty() {
echo -e "${GRE}=========== Chain33 Lock begin ===========${NOC}"
preChain33Balance=$(${Chain33_CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum | jq -r ".balance" | sed 's/\"//g')
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
preEthBalance[$i]=$(${CLIA} relayer ethereum balance -o "${ethAddress[i]}" -t "${tokenAddrBty}" | jq -r ".balance")
ethTxHash=$(${Chain33_CLI} send x2ethereum lock -q "${tokenAddrBty}" -a 1 -r ${ethAddress[i]} -t coins.bty -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
echo ${i} "lock chain33 tx hash:" "${ethTxHash}"
# shellcheck disable=SC2219
let i++
done
eth_block_wait $((maturityDegree + 2))
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
nowEthBalance=$(${CLIA} relayer ethereum balance -o "${ethAddress[i]}" -t "${tokenAddrBty}" | jq -r ".balance")
res=$((nowEthBalance - preEthBalance[i]))
echo ${i} "preBalance" "${preEthBalance[i]}" "nowBalance" "${nowEthBalance}" "diff" ${res}
check_number "${res}" 1
# shellcheck disable=SC2219
let i++
done
nowChain33Balance=$(${Chain33_CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum | jq -r ".balance" | sed 's/\"//g')
diff=$(echo "$preChain33Balance - $nowChain33Balance" | bc)
check_number "${diff}" 7
}
loop_send_burn_bty() {
echo -e "${GRE}=========== Ethereum Burn begin ===========${NOC}"
preChain33Balance=$(${Chain33_CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum | jq -r ".balance" | sed 's/\"//g')
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
preEthBalance[$i]=$(${CLIA} relayer ethereum balance -o "${ethAddress[i]}" -t "${tokenAddrBty}" | jq -r ".balance")
approveTxHash=$(${CLIA} relayer ethereum approve -m 1 -k "${privateKeys[i]}" -t "${tokenAddrBty}")
ethTxHash=$(${CLIA} relayer ethereum burn-async -m 1 -k "${privateKeys[i]}" -r 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t "${tokenAddrBty}")
echo ${i} "burn-async tx hash:" "${ethTxHash}"
# shellcheck disable=SC2219
let i++
done
eth_block_wait $((maturityDegree + 2))
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
nowEthBalance=$(${CLIA} relayer ethereum balance -o "${ethAddress[i]}" -t "${tokenAddrBty}" | jq -r ".balance")
res=$((preEthBalance[i] - nowEthBalance))
echo ${i} "preBalance" "${preEthBalance[i]}" "nowBalance" "${nowEthBalance}" "diff" ${res}
check_number "${res}" 1
# shellcheck disable=SC2219
let i++
done
nowChain33Balance=$(${Chain33_CLI} account balance -a 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -e x2ethereum | jq -r ".balance" | sed 's/\"//g')
diff=$(echo "$nowChain33Balance - $preChain33Balance" | bc)
check_number "${diff}" 7
}
loop_send_lock_erc20() {
echo -e "${GRE}=========== Ethereum Lock Erc20 begin ===========${NOC}"
preChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t testc | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
preEthBalance=$(${CLIA} relayer ethereum balance -o "${Ethsender}" -t "${tokenAddr}" | jq -r ".balance")
approveTxHash=$(${CLIA} relayer ethereum approve -m 10 -k "${privateKeys[5]}" -t "${tokenAddr}")
i=0
echo ${i} "lock-async erc20 approve tx hash:" "${approveTxHash}"
while [[ i -lt ${#privateKeys[@]} ]]; do
ethTxHash=$(${CLIA} relayer ethereum lock-async -m 1 -k "${privateKeys[5]}" -r 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t "${tokenAddr}")
echo ${i} "lock-async erc20 tx hash:" "${ethTxHash}"
# shellcheck disable=SC2219
let i++
done
eth_block_wait $((maturityDegree + 2))
nowEthBalance=$(${CLIA} relayer ethereum balance -o "${Ethsender}" -t "${tokenAddr}" | jq -r ".balance")
res=$((preEthBalance - nowEthBalance))
echo ${i} "preBalance" "${preEthBalance}" "nowBalance" "${nowEthBalance}" "diff" ${res}
check_number "${diff}" 7
nowChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t testc | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
diff=$((nowChain33Balance - preChain33Balance))
check_number "${diff}" 7
}
loop_send_burn_erc20() {
echo -e "${GRE}=========== Chain33 Burn Erc20 begin ===========${NOC}"
preChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t testc | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
preEthBalance[i]=$(${CLIA} relayer ethereum balance -o "${ethAddress[i]}" -t "${tokenAddr}" | jq -r ".balance")
ethTxHash=$(${Chain33_CLI} send x2ethereum burn -a 1 -r ${ethAddress[i]} -t testc -q "${tokenAddr}" -k 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv)
echo ${i} "burn chain33 tx hash:" "${ethTxHash}"
# shellcheck disable=SC2219
let i++
done
eth_block_wait $((maturityDegree + 2))
i=0
while [[ i -lt ${#privateKeys[@]} ]]; do
nowEthBalance=$(${CLIA} relayer ethereum balance -o "${ethAddress[i]}" -t "${tokenAddr}" | jq -r ".balance")
res=$((nowEthBalance - preEthBalance[i]))
echo ${i} "preBalance" "${preEthBalance[i]}" "nowBalance" "${nowEthBalance}" "diff" ${res}
check_number "${res}" 1
# shellcheck disable=SC2219
let i++
done
nowChain33Balance=$(${Chain33_CLI} x2ethereum balance -s 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv -t testc | jq ".res" | jq ".[]" | jq ".balance" | sed 's/\"//g')
diff=$(echo "$preChain33Balance - $nowChain33Balance" | bc)
check_number "${diff}" 7
}
perf_test_main() {
echo -e "${GRE}=========== $FUNCNAME begin ===========${NOC}"
docker_chain33_ip=$(docker inspect "${NODE3}" | jq ".[].NetworkSettings.Networks" | grep "IPAddress" | awk '{ print $2}' | sed 's/\"//g' | sed 's/,//g')
Chain33_CLI="$GOPATH/src/github.com/33cn/plugin/build/chain33-cli --rpc_laddr http://${docker_chain33_ip}:8801"
if [[ ${1} != "" ]]; then
maturityDegree=${1}
echo -e "${GRE}maturityDegree is ${maturityDegree} ${NOC}"
fi
loop_send_lock_eth
loop_send_burn_eth
loop_send_lock_bty
loop_send_burn_bty
loop_send_lock_erc20
loop_send_burn_erc20
echo -e "${GRE}=========== $FUNCNAME end ===========${NOC}"
}
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
# shellcheck disable=SC2155
set -x
set -e
# 公用测试函数
#color
RED='\033[1;31m'
GRE='\033[1;32m'
NOC='\033[0m'
function kill_all_ebrelayer() {
for name in A B C D; do
local ebrelayer="./../build/$name/ebrelayer"
kill_ebrelayer "${ebrelayer}"
done
}
# 判断结果是否正确
function cli_ret() {
set +x
if [[ $# -lt 2 ]]; then
echo -e "${RED}wrong parameter${NOC}"
exit 1
fi
ok=$(echo "${1}" | jq -r .isOK)
if [[ ${ok} != "true" ]]; then
echo -e "${RED}failed to ${2}${NOC}"
exit 1
fi
local jqMsg=".msg"
if [[ $# -ge 3 ]]; then
jqMsg="${3}"
fi
msg=$(echo "${1}" | jq -r "${jqMsg}")
if [[ $# -eq 4 ]]; then
if [ "$(echo "$msg < $4" | bc)" -eq 1 ] || [ "$(echo "$msg > $4" | bc)" -eq 1 ]; then
echo -e "${RED}The balance is not correct${NOC}"
exit 1
fi
fi
set -x
echo "${msg}"
}
# 判断 chain33 金额是否正确
function balance_ret() {
set +x
if [[ $# -lt 2 ]]; then
echo -e "${RED}wrong parameter${NOC}"
exit 1
fi
local balance=$(echo "${1}" | jq -r ".balance")
if [ "$(echo "$balance < $2" | bc)" -eq 1 ] || [ "$(echo "$balance > $2" | bc)" -eq 1 ]; then
echo -e "${RED}The balance is not correct${NOC}"
exit 1
fi
set -x
echo "${balance}"
}
# 判断结果是否错误
function cli_ret_err() {
#set +x
ok=$(echo "${1}" | jq -r .isOK)
echo "${ok}"
if [[ ${ok} == "true" ]]; then
echo -e "${RED}isOK is true${NOC}"
exit 1
fi
#set -x
}
# 查询关键字所在行然后删除 ${1}文件名称 ${2}关键字
function delete_line() {
line=$(cat -n "${1}" | grep "${2}" | awk '{print $1}')
if [[ ${line} != "" ]]; then
sed -i "${line}"'d' "${1}" # 删除行
fi
}
# 查询关键字所在行然后删除 ${1}文件名称 ${2}关键字
function delete_line_show() {
local line=$(cat -n "${1}" | grep "${2}" | awk '{print $1}')
if [[ ${line} != "" ]]; then
sed -i "${line}"'d' "${1}" # 删除行
line=$((line - 1))
fi
echo "${line}"
}
# 后台启动 ebrelayer 进程 $1进程名称 $2进程信息输出重定向文件
function start_ebrelayer() {
# 参数如果小于 2 直接报错
if [[ $# -lt 2 ]]; then
echo -e "${RED}wrong parameter${NOC}"
exit 1
fi
# 判断可执行文件是否存在
if [ ! -x "${1}" ]; then
echo -e "${RED}${1} not exist${NOC}"
exit 1
fi
# 后台启动程序
nohup "${1}" >"${2}" 2>&1 &
sleep 2
# shellcheck disable=SC2009
pid=$(ps -ef | grep "${1}" | grep -v 'grep' | awk '{print $2}')
local count=0
while [ "${pid}" == "" ]; do
nohup "${1}" >"${2}" 2>&1 &
sleep 2
count=$((count + 1))
if [[ ${count} -ge 20 ]]; then
echo -e "${RED}start ${1} failed${NOC}"
exit 1
fi
# shellcheck disable=SC2009
pid=$(ps -ef | grep "${1}" | grep -v 'grep' | awk '{print $2}')
done
}
# 后台启动 ebrelayer 进程 $1 A B C D
function start_ebrelayer_and_unlock() {
start_ebrelayer "./${1}/ebrelayer" "./${1}/ebrelayer.log"
sleep 2
local CLI="./ebcli_$1"
local count=0
while true; do
result=$(${CLI} relayer unlock -p 123456hzj | jq -r .isOK)
if [[ ${result} == "true" ]]; then
break
fi
count=$((count + 1))
if [[ ${count} == 5 ]]; then
echo -e "${RED}failed to unlock${NOC}"
exit 1
fi
sleep 1
done
}
# 后台启动 ebrelayer 进程 $1 A B C D
function start_ebrelayer_and_setpwd_unlock() {
start_ebrelayer "./${1}/ebrelayer" "./${1}/ebrelayer.log"
sleep 2
local CLI="./ebcli_$1"
local count=0
while true; do
result=$(${CLI} relayer set_pwd -p 123456hzj | jq -r .isOK)
if [[ ${result} == "true" ]]; then
break
fi
count=$((count + 1))
if [[ ${count} == 5 ]]; then
echo -e "${RED}failed to set_pwd${NOC}"
exit 1
fi
sleep 1
done
count=0
while true; do
result=$(${CLI} relayer unlock -p 123456hzj | jq -r .isOK)
if [[ ${result} == "true" ]]; then
break
fi
count=$((count + 1))
if [[ ${count} == 5 ]]; then
echo -e "${RED}failed to unlock${NOC}"
exit 1
fi
sleep 1
done
}
# 杀死进程ebrelayer 进程 $1进程名称
function kill_ebrelayer() {
# shellcheck disable=SC2009
pid=$(ps -ef | grep "${1}" | grep -v 'grep' | awk '{print $2}')
if [ "${pid}" == "" ]; then
echo "not find ${1} pid"
return
fi
kill "${pid}"
# shellcheck disable=SC2009
pid=$(ps -ef | grep "${1}" | grep -v 'grep' | awk '{print $2}')
if [ "${pid}" != "" ]; then
echo "kill ${1} failed"
kill -9 "${pid}"
fi
sleep 1
}
# chain33 区块等待 $1:cli 路径 $2:等待高度
function block_wait() {
set +x
local CLI=${1}
if [[ $# -lt 1 ]]; then
echo -e "${RED}wrong block_wait parameter${NOC}"
exit 1
fi
local cur_height=$(${CLI} block last_header | jq ".height")
local expect=$((cur_height + ${2}))
local count=0
while true; do
new_height=$(${CLI} block last_header | jq ".height")
if [[ ${new_height} -ge ${expect} ]]; then
break
fi
count=$((count + 1))
sleep 1
done
count=$((count + 1))
set -x
echo -e "${GRE}chain33 wait new block $count s, cur height=$expect,old=$cur_height${NOC}"
}
# 检查交易是否执行成功 $1:cli 路径 $2:交易hash
function check_tx() {
set +x
local CLI=${1}
if [[ $# -lt 2 ]]; then
echo -e "${RED}wrong check_tx parameters${NOC}"
exit 1
fi
if [[ ${2} == "" ]]; then
echo -e "${RED}wrong check_tx txHash is empty${NOC}"
exit 1
fi
local count=0
while true; do
ty=$(${CLI} tx query -s "${2}" | jq .receipt.ty)
if [[ ${ty} != "" ]]; then
break
fi
count=$((count + 1))
sleep 1
if [[ ${count} -ge 100 ]]; then
echo "chain33 query tx for too long"
break
fi
done
set -x
ty=$(${CLI} tx query -s "${2}" | jq .receipt.ty)
if [[ ${ty} != 2 ]]; then
echo -e "${RED}check tx error, hash is ${2}${NOC}"
exit 1
fi
}
function check_number() {
if [[ $# -lt 2 ]]; then
echo -e "${RED}wrong check number parameters${NOC}"
exit 1
fi
if [ "$(echo "$1 < $2" | bc)" -eq 1 ] || [ "$(echo "$1 > $2" | bc)" -eq 1 ]; then
echo -e "${RED}error number, expect ${1}, get ${2}${NOC}"
exit 1
fi
}
# 检查地址是否匹配 $1返回结果 $2匹配地址
function check_addr() {
if [[ $# -lt 2 ]]; then
echo -e "${RED}wrong check number parameters${NOC}"
exit 1
fi
addr=$(echo "${1}" | jq -r ".acc.addr")
if [[ ${addr} != "${2}" ]]; then
echo -e "${RED}error addr, expect ${1}, get ${2}${NOC}"
exit 1
fi
}
# 更新配置文件 $1 为 BridgeRegistry 合约地址; $2 等待区块 默认10; $3 relayer.toml 地址
function updata_relayer_toml() {
local BridgeRegistry=${1}
local maturityDegree=${2}
local file=${3}
# local chain33Host=$(docker inspect "${NODE3}" | jq ".[].NetworkSettings.Networks.${PROJ}_default.IPAddress" | sed 's/\"//g')
local chain33Host=$(docker inspect "${NODE3}" | jq ".[].NetworkSettings.Networks" | grep "IPAddress" | awk '{ print $2}' | sed 's/\"//g' | sed 's/,//g')
if [[ ${chain33Host} == "" ]]; then
echo -e "${RED}chain33Host is empty${NOC}"
exit 1
fi
local pushHost=$(ifconfig wlp2s0 | grep "inet " | awk '{ print $2}' | awk -F: '{print $2}')
if [[ ${pushHost} == "" ]]; then
pushHost=$(ifconfig wlp2s0 | grep "inet " | awk '{ print $2}')
if [[ ${pushHost} == "" ]]; then
pushHost=$(ifconfig eth0 | grep "inet " | awk '{ print $2}' | awk -F: '{print $2}')
if [[ ${pushHost} == "" ]]; then
pushHost=$(ifconfig eth0 | grep "inet " | awk '{ print $2}')
if [[ ${pushHost} == "" ]]; then
ip addr show eth0
pushHost=$(ip addr show eth0 | grep "inet " | awk '{ print $2}' | head -c-4)
fi
fi
fi
fi
if [[ ${pushHost} == "" ]]; then
echo -e "${RED}pushHost is empty${NOC}"
exit 1
fi
local line=$(delete_line_show "${file}" "chain33Host")
# 在第 line 行后面 新增合约地址
sed -i ''"${line}"' a chain33Host="http://'"${chain33Host}"':8801"' "${file}"
line=$(delete_line_show "${file}" "pushHost")
sed -i ''"${line}"' a pushHost="http://'"${pushHost}"':20000"' "${file}"
line=$(delete_line_show "${file}" "BridgeRegistry")
sed -i ''"${line}"' a BridgeRegistry="'"${BridgeRegistry}"'"' "${file}"
sed -i 's/EthMaturityDegree=10/'EthMaturityDegree="${maturityDegree}"'/g' "${file}"
sed -i 's/maturityDegree=10/'maturityDegree="${maturityDegree}"'/g' "${file}"
sed -i 's/^EthBlockFetchPeriod=.*/EthBlockFetchPeriod=500/g' "${file}"
sed -i 's/^fetchHeightPeriodMs=.*/fetchHeightPeriodMs=500/g' "${file}"
#sed -i 's/#BridgeRegistry=\"0x40BFE5eD039A9a2Eb42ece2E2CA431bFa7Cf4c42\"/BridgeRegistry=\"'${BridgeRegistry}'\"/g' "../build/relayer.toml"
#sed -i 's/192.168.64.2/'${chain33Host}'/g' "../build/relayer.toml"
#sed -i 's/192.168.3.156/'${pushHost}'/g' "../build/relayer.toml"
}
# 更新配置文件 $1 为 BridgeRegistry 合约地址; $2 等待区块 默认10; $3 relayer.toml 地址
function updata_relayer_toml_ropston() {
local BridgeRegistry=${1}
local maturityDegree=${2}
local file=${3}
local chain33Host=127.0.0.1
local pushHost=127.0.0.1
local line=$(delete_line_show "${file}" "chain33Host")
# 在第 line 行后面 新增合约地址
sed -i ''"${line}"' a chain33Host="http://'${chain33Host}':8801"' "${file}"
line=$(delete_line_show "${file}" "pushHost")
sed -i ''"${line}"' a pushHost="http://'${pushHost}':20000"' "${file}"
line=$(delete_line_show "${file}" "BridgeRegistry")
sed -i ''"${line}"' a BridgeRegistry="'"${BridgeRegistry}"'"' "${file}"
sed -i 's/EthMaturityDegree=10/'EthMaturityDegree="${maturityDegree}"'/g' "${file}"
sed -i 's/maturityDegree=10/'maturityDegree="${maturityDegree}"'/g' "${file}"
#sed -i 's/#BridgeRegistry=\"0x40BFE5eD039A9a2Eb42ece2E2CA431bFa7Cf4c42\"/BridgeRegistry=\"'${BridgeRegistry}'\"/g' "../build/relayer.toml"
#sed -i 's/192.168.64.2/'${chain33Host}'/g' "../build/relayer.toml"
#sed -i 's/192.168.3.156/'${pushHost}'/g' "../build/relayer.toml"
}
# 更新 B C D 的配置文件
function updata_all_relayer_toml() {
local port=9901
local port2=20000
# local dockername=30
for name in B C D; do
local file="../build/$name/relayer.toml"
cp '../build/A/relayer.toml' "${file}"
cp '../build/ebrelayer' "../build/$name/ebrelayer"
# 删除配置文件中不需要的字段
for deleteName in "deployerPrivateKey" "operatorAddr" "validatorsAddr" "initPowers" "deployerPrivateKey" "deploy"; do
delete_line "${file}" "${deleteName}"
done
# 替换端口
port=$((port + 1))
sed -i 's/localhost:9901/localhost:'${port}'/g' "${file}"
port2=$((port2 + 1))
sed -i 's/20000/'${port2}'/g' "${file}"
sed -i 's/x2ethereum/x2ethereum'${name}'/g' "${file}"
# local chain33Host=$(docker inspect build_chain${dockername}_1 | jq ".[].NetworkSettings.Networks.build_default.IPAddress" | sed 's/\"//g')
# if [[ "${chain33Host}" == "" ]]; then
# echo -e "${RED}chain33Host is empty${NOC}"
# exit 1
# fi
# local line=$(delete_line_show ${file} "chain33Host")
# # 在第 line 行后面 新增合约地址
# sed -i ''${line}' a chain33Host="http://'${chain33Host}':8801"' "${file}"
#
# dockername=$((${dockername} + 1))
done
}
# 更新 B C D 的配置文件
function updata_all_relayer_toml2() {
local port=9901
local port2=20000
# local dockername=30
for name in B C D; do
local file="./$name/relayer.toml"
cp './A/relayer.toml' "${file}"
cp './ebrelayer' "./$name/ebrelayer"
# 删除配置文件中不需要的字段
for deleteName in "deployerPrivateKey" "operatorAddr" "validatorsAddr" "initPowers" "deployerPrivateKey" "deploy"; do
delete_line "${file}" "${deleteName}"
done
# 替换端口
port=$((port + 1))
sed -i 's/localhost:9901/localhost:'${port}'/g' "${file}"
port2=$((port2 + 1))
sed -i 's/20000/'${port2}'/g' "${file}"
sed -i 's/x2ethereum/x2ethereum'${name}'/g' "${file}"
# local chain33Host=$(docker inspect build_chain${dockername}_1 | jq ".[].NetworkSettings.Networks.build_default.IPAddress" | sed 's/\"//g')
# if [[ "${chain33Host}" == "" ]]; then
# echo -e "${RED}chain33Host is empty${NOC}"
# exit 1
# fi
# local line=$(delete_line_show ${file} "chain33Host")
# # 在第 line 行后面 新增合约地址
# sed -i ''${line}' a chain33Host="http://'${chain33Host}':8801"' "${file}"
#
# dockername=$((${dockername} + 1))
done
}
# 启动 eth
function start_trufflesuite() {
# 如果原来存在先删除
local ganacheName=ganachetest
#local isExit=$(docker inspect ${ganacheName} | jq ".[]" | jq ".Id")
#if [[ ${isExit} != "" ]]; then
docker stop ${ganacheName}
docker rm ${ganacheName}
#fi
# 启动 eth
docker run -d --name ${ganacheName} -p 7545:8545 -l eth_test trufflesuite/ganache-cli:latest -a 10 --debug -b 2 -m "coast bar giraffe art venue decide symbol law visual crater vital fold"
sleep 1
}
# $1 CLI
function wait_prophecy_finish() {
local CLI=${1}
set +x
local count=0
while true; do
if [[ $# -eq 4 ]]; then
${CLI} relayer ethereum balance -o "${2}" -t "${3}"
balance=$(${CLI} relayer ethereum balance -o "${2}" -t "${3}" | jq -r .balance)
if [[ ${balance} == "${4}" ]]; then
break
fi
fi
if [[ $# -eq 3 ]]; then
${CLI} relayer ethereum balance -o "${2}"
balance=$(${CLI} relayer ethereum balance -o "${2}" | jq -r .balance)
if [[ ${balance} == "${3}" ]]; then
break
fi
fi
count=$((count + 1))
if [[ ${count} == 30 ]]; then
echo -e "${RED}failed to get balance${NOC}"
exit 1
fi
sleep 1
done
set -x
}
# eth 区块等待 $1:等待高度 $2:url地址,默认为 http://localhost:7545,测试网络用 https://ropsten-rpc.linkpool.io/
function eth_block_wait() {
set +x
if [[ $# -lt 0 ]]; then
echo -e "${RED}wrong block_wait parameter${NOC}"
exit 1
fi
local cur_height=""
local new_height=""
local url=${2}
if [ "${url}" == "" ]; then
cur_height=$(curl -ksd '{"id":1,"jsonrpc":"2.0","method":"eth_blockNumber","params":[]}' http://localhost:7545 | jq -r ".result")
else
cur_height=$(curl -H "Content-Type: application/json" -X POST --data '{"id":1,"jsonrpc":"2.0","method":"eth_blockNumber","params":[]}' "${url}" | jq -r ".result")
fi
local expect=$((cur_height + ${1} + 1))
local count=0
while true; do
if [ "${url}" == "" ]; then
new_height=$(curl -ksd '{"id":1,"jsonrpc":"2.0","method":"eth_blockNumber","params":[]}' http://localhost:7545 | jq -r ".result")
else
new_height=$(curl -H "Content-Type: application/json" -X POST --data '{"id":1,"jsonrpc":"2.0","method":"eth_blockNumber","params":[]}' "${url}" | jq -r ".result")
fi
if [[ ${new_height} -ge ${expect} ]]; then
break
fi
count=$((count + 1))
sleep 1
done
count=$((count + 1))
sleep 1
set -x
echo -e "${GRE}eth wait new block $count s, cur height=$expect,old=$((cur_height))${NOC}"
}
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
source "./allRelayerTest.sh"
source "./perf_test.sh"
function x2ethereum() {
if [ "${2}" == "init" ]; then
return
elif [ "${2}" == "config" ]; then
return
elif [ "${2}" == "test" ]; then
echo "========================== x2ethereum test =========================="
set +e
set -x
AllRelayerMainTest 1
perf_test_main 10
echo "========================== x2ethereum test end =========================="
fi
}
#!/usr/bin/env bash
# shellcheck disable=SC2128
# shellcheck source=/dev/null
#source ../dapp-test-common.sh
#
#set -x
#
#MAIN_HTTP=""
#chain33SenderAddr="14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
## validatorsAddr=["0x92c8b16afd6d423652559c6e266cbe1c29bfd84f", "0x0df9a824699bc5878232c9e612fe1a5346a5a368", "0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1", "0xd9dab021e74ecf475788ed7b61356056b2095830"]
#ethValidatorAddrKeyA="3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
#ethValidatorAddrKeyB="a5f3063552f4483cfc20ac4f40f45b798791379862219de9e915c64722c1d400"
#ethValidatorAddrKeyC="bbf5e65539e9af0eb0cfac30bad475111054b09c11d668fc0731d54ea777471e"
#ethValidatorAddrKeyD="c9fa31d7984edf81b8ef3b40c761f1847f6fcd5711ab2462da97dc458f1f896b"
## 新增地址 chain33 需要导入地址 转入 10 bty当收费费
#chain33Validator1="1GTxrmuWiXavhcvsaH5w9whgVxUrWsUMdV"
#chain33Validator2="155ooMPBTF8QQsGAknkK7ei5D78rwDEFe6"
#chain33Validator3="13zBdQwuyDh7cKN79oT2odkxYuDbgQiXFv"
#chain33Validator4="113ZzVamKfAtGt9dq45fX1mNsEoDiN95HG"
#chain33ValidatorKey1="0xd627968e445f2a41c92173225791bae1ba42126ae96c32f28f97ff8f226e5c68"
#chain33ValidatorKey2="0x9d539bc5fd084eb7fe86ad631dba9aa086dba38418725c38d9751459f567da66"
#chain33ValidatorKey3="0x0a6671f101e30a2cc2d79d77436b62cdf2664ed33eb631a9c9e3f3dd348a23be"
#chain33ValidatorKey4="0x3818b257b05ee75b6e43ee0e3cfc2d8502342cf67caed533e3756966690b62a5"
#ethReceiverAddr1="0xa4ea64a583f6e51c3799335b28a8f0529570a635"
#ethReceiverAddrKey1="355b876d7cbcb930d5dfab767f66336ce327e082cbaa1877210c1bae89b1df71"
#ethReceiverAddr2="0x0c05ba5c230fdaa503b53702af1962e08d0c60bf"
#ethReceiverAddrKey2="9dc6df3a8ab139a54d8a984f54958ae0661f880229bf3bdbb886b87d58b56a08"
#
#maturityDegree=10
#
#function init() {
# chain33_ImportPrivkey "${chain33ValidatorKey1}" "${chain33Validator1}" "tokenAddr" "${MAIN_HTTP}"
# chain33_ImportPrivkey "${chain33ValidatorKey2}" "${chain33Validator2}" "tokenAddr" "${MAIN_HTTP}"
# chain33_ImportPrivkey "${chain33ValidatorKey3}" "${chain33Validator3}" "tokenAddr" "${MAIN_HTTP}"
# chain33_ImportPrivkey "${chain33ValidatorKey4}" "${chain33Validator4}" "tokenAddr" "${MAIN_HTTP}"
#
# tx=$(curl -ksd '{"method":"Chain33.CreateTransaction","params":[{"execer":"x2ethereum","actionName":"SetConsensusThreshold","payload":{"consensusThreshold":"80", }}]}' ${MAIN_HTTP} | jq -r ".result")
# chain33_SignAndSendTxWait "$tx" "0x4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01" ${MAIN_HTTP} "$FUNCNAME"
#}
// 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 buildflags
var NodeAddr string
/*Package commands implement dapp client commands*/
package commands
import (
"fmt"
"os"
"strconv"
"github.com/33cn/chain33/rpc/jsonclient"
types2 "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/system/dapp/commands"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebcli/buildflags"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
types3 "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
"github.com/spf13/cobra"
)
/*
* 实现合约对应客户端
*/
// Cmd x2ethereum client command
func Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "x2ethereum",
Short: "x2ethereum command",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
CreateRawWithdrawChain33TxCmd(),
CreateRawChain33ToEthTxCmd(),
CreateRawAddValidatorTxCmd(),
CreateRawRemoveValidatorTxCmd(),
CreateRawModifyValidatorTxCmd(),
CreateRawSetConsensusTxCmd(),
CreateTransferCmd(),
CreateTokenTransferExecCmd(),
CreateTokenWithdrawCmd(),
queryCmd(),
queryRelayerBalanceCmd(),
)
if buildflags.NodeAddr == "" {
buildflags.NodeAddr = "http://127.0.0.1:7545"
}
cmd.PersistentFlags().String("node_addr", buildflags.NodeAddr, "eth node url")
return cmd
}
// Burn
func CreateRawWithdrawChain33TxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "burn",
Short: "Create a burn tx in chain33,withdraw chain33ToEth",
Run: burn,
}
addChain33ToEthFlags(cmd)
return cmd
}
func addChain33ToEthFlags(cmd *cobra.Command) {
cmd.Flags().StringP("contract", "q", "", "token contract address,nil for ETH")
cmd.Flags().StringP("symbol", "t", "", "token symbol in chain33,coins.bty etc.")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().StringP("receiver", "r", "", "ethereum receiver address")
_ = cmd.MarkFlagRequired("cExec")
cmd.Flags().Float64P("amount", "a", float64(0), "the amount of this contract want to lock")
_ = cmd.MarkFlagRequired("amount")
}
func burn(cmd *cobra.Command, args []string) {
contract, _ := cmd.Flags().GetString("contract")
csymbol, _ := cmd.Flags().GetString("symbol")
receiver, _ := cmd.Flags().GetString("receiver")
amount, _ := cmd.Flags().GetFloat64("amount")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
if contract == "" {
contract = "0x0000000000000000000000000000000000000000"
}
decimal, err := utils.GetDecimalsFromNode(contract, nodeAddr)
if err != nil {
fmt.Println("get decimal error")
return
}
params := &types3.Chain33ToEth{
TokenContract: contract,
EthereumReceiver: receiver,
Amount: types3.TrimZeroAndDot(strconv.FormatFloat(amount*1e8, 'f', 4, 64)),
IssuerDotSymbol: csymbol,
Decimals: decimal,
}
payLoad := types.MustPBToJSON(params)
createTx(cmd, payLoad, types3.NameWithdrawChain33Action)
}
// Lock
func CreateRawChain33ToEthTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "lock",
Short: "Create a lock tx in chain33,create a chain33ToEth tx",
Run: lock,
}
addChain33ToEthFlags(cmd)
return cmd
}
func lock(cmd *cobra.Command, args []string) {
contract, _ := cmd.Flags().GetString("contract")
csymbol, _ := cmd.Flags().GetString("symbol")
receiver, _ := cmd.Flags().GetString("receiver")
amount, _ := cmd.Flags().GetFloat64("amount")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
decimal, err := utils.GetDecimalsFromNode(contract, nodeAddr)
if err != nil {
fmt.Println("get decimal error")
return
}
if contract == "" {
fmt.Println("get token address error")
return
}
params := &types3.Chain33ToEth{
TokenContract: contract,
EthereumReceiver: receiver,
Amount: strconv.FormatFloat(amount*1e8, 'f', 4, 64),
IssuerDotSymbol: csymbol,
Decimals: decimal,
}
payLoad := types.MustPBToJSON(params)
createTx(cmd, payLoad, types3.NameChain33ToEthAction)
}
// Transfer
func CreateTransferCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "transfer",
Short: "Create a transfer tx in chain33",
Run: transfer,
}
addTransferFlags(cmd)
return cmd
}
func transfer(cmd *cobra.Command, args []string) {
commands.CreateAssetTransfer(cmd, args, types3.X2ethereumX)
}
func addTransferFlags(cmd *cobra.Command) {
cmd.Flags().StringP("to", "t", "", "receiver account address")
_ = cmd.MarkFlagRequired("to")
cmd.Flags().Float64P("amount", "a", 0, "transaction amount")
_ = cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("note", "n", "", "transaction note info,optional")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
}
// CreateTokenTransferExecCmd create raw transfer tx
func CreateTokenTransferExecCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "send_exec",
Short: "Create a token send to executor transaction",
Run: createTokenSendToExec,
}
addCreateTokenSendToExecFlags(cmd)
return cmd
}
func addCreateTokenSendToExecFlags(cmd *cobra.Command) {
cmd.Flags().StringP("exec", "e", "", "receiver executor address")
cmd.MarkFlagRequired("exec")
cmd.Flags().Float64P("amount", "a", 0, "transaction amount")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("note", "n", "", "transaction note info")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
cmd.MarkFlagRequired("symbol")
}
func createTokenSendToExec(cmd *cobra.Command, args []string) {
commands.CreateAssetSendToExec(cmd, args, types3.X2ethereumX)
}
// CreateTokenWithdrawCmd create raw withdraw tx
func CreateTokenWithdrawCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "withdrawfromexec",
Short: "Create a token withdraw transaction",
Run: createTokenWithdraw,
}
addCreateTokenWithdrawFlags(cmd)
return cmd
}
func addCreateTokenWithdrawFlags(cmd *cobra.Command) {
cmd.Flags().StringP("exec", "e", "", "execer withdrawn from")
cmd.MarkFlagRequired("exec")
cmd.Flags().Float64P("amount", "a", 0, "withdraw amount")
cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("note", "n", "", "transaction note info")
cmd.Flags().StringP("symbol", "s", "", "token symbol")
cmd.MarkFlagRequired("symbol")
}
func createTokenWithdraw(cmd *cobra.Command, args []string) {
commands.CreateAssetWithdraw(cmd, args, types3.X2ethereumX)
}
// AddValidator
func CreateRawAddValidatorTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "Create a add validator tx in chain33",
Run: addValidator,
}
addValidatorFlags(cmd)
cmd.Flags().Int64P("power", "p", 0, "validator power set,must be 1-100")
_ = cmd.MarkFlagRequired("power")
return cmd
}
func addValidatorFlags(cmd *cobra.Command) {
cmd.Flags().StringP("address", "a", "", "the address you want to add/remove/modify as a validator ")
_ = cmd.MarkFlagRequired("address")
}
func addValidator(cmd *cobra.Command, args []string) {
address, _ := cmd.Flags().GetString("address")
power, _ := cmd.Flags().GetInt64("power")
params := &types3.MsgValidator{
Address: address,
Power: power,
}
payLoad := types.MustPBToJSON(params)
createTx(cmd, payLoad, types3.NameAddValidatorAction)
}
// RemoveValidator
func CreateRawRemoveValidatorTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "remove",
Short: "Create a remove validator tx in chain33",
Run: removeValidator,
}
addValidatorFlags(cmd)
return cmd
}
func removeValidator(cmd *cobra.Command, args []string) {
address, _ := cmd.Flags().GetString("address")
params := &types3.MsgValidator{
Address: address,
}
payLoad := types.MustPBToJSON(params)
createTx(cmd, payLoad, types3.NameRemoveValidatorAction)
}
// ModifyValidator
func CreateRawModifyValidatorTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "modify",
Short: "Create a modify validator tx in chain33",
Run: modify,
}
addValidatorFlags(cmd)
cmd.Flags().Int64P("power", "p", 0, "validator power set,must be 1-100")
_ = cmd.MarkFlagRequired("power")
return cmd
}
func modify(cmd *cobra.Command, args []string) {
address, _ := cmd.Flags().GetString("address")
power, _ := cmd.Flags().GetInt64("power")
params := &types3.MsgValidator{
Address: address,
Power: power,
}
payLoad := types.MustPBToJSON(params)
createTx(cmd, payLoad, types3.NameModifyPowerAction)
}
// MsgSetConsensusNeeded
func CreateRawSetConsensusTxCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "setconsensus",
Short: "Create a set consensus threshold tx in chain33",
Run: setConsensus,
}
addSetConsensusFlags(cmd)
return cmd
}
func addSetConsensusFlags(cmd *cobra.Command) {
cmd.Flags().Int64P("power", "p", 0, "the power you want to set consensus need,must be 1-100")
_ = cmd.MarkFlagRequired("power")
}
func setConsensus(cmd *cobra.Command, args []string) {
power, _ := cmd.Flags().GetInt64("power")
params := &types3.MsgConsensusThreshold{
ConsensusThreshold: power,
}
payLoad := types.MustPBToJSON(params)
createTx(cmd, payLoad, types3.NameSetConsensusThresholdAction)
}
func queryRelayerBalanceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "balance",
Short: "query balance of x2ethereum",
Run: queryRelayerBalance,
}
cmd.Flags().StringP("token", "t", "", "token symbol")
_ = cmd.MarkFlagRequired("token")
cmd.Flags().StringP("address", "s", "", "the address you want to query")
_ = cmd.MarkFlagRequired("address")
cmd.Flags().StringP("tokenaddress", "a", "", "token address,nil for all this token symbol")
return cmd
}
func queryRelayerBalance(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
token, _ := cmd.Flags().GetString("token")
address, _ := cmd.Flags().GetString("address")
contract, _ := cmd.Flags().GetString("tokenaddress")
get := &types3.QueryRelayerBalance{
TokenSymbol: token,
Address: address,
TokenAddr: contract,
}
payLoad, err := types.PBToJSON(get)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "ErrPbToJson:"+err.Error())
return
}
query := types2.Query4Jrpc{
Execer: types3.X2ethereumX,
FuncName: types3.FuncQueryRelayerBalance,
Payload: payLoad,
}
channel := &types3.ReceiptQueryRelayerBalance{}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", query, channel)
ctx.Run()
}
func createTx(cmd *cobra.Command, payLoad []byte, action string) {
title, _ := cmd.Flags().GetString("title")
cfg := types.GetCliSysParam(title)
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
pm := &types2.CreateTxIn{
Execer: cfg.ExecName(types3.X2ethereumX),
ActionName: action,
Payload: payLoad,
}
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", pm, &res)
ctx.RunWithoutMarshal()
}
package commands
import (
"fmt"
"os"
"strings"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
types2 "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
"github.com/spf13/cobra"
)
func queryCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "query",
Short: "query x2ethereum",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
queryEthProphecyCmd(),
queryValidatorsCmd(),
queryConsensusCmd(),
queryTotalPowerCmd(),
querySymbolTotalAmountByTxTypeCmd(),
)
return cmd
}
func queryEthProphecyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "prophecy",
Short: "query prophecy",
Run: queryEthProphecy,
}
cmd.Flags().StringP("id", "i", "", "prophecy id")
_ = cmd.MarkFlagRequired("id")
return cmd
}
func queryEthProphecy(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
id, _ := cmd.Flags().GetString("id")
get := &types2.QueryEthProphecyParams{
ID: id,
}
payLoad, err := types.PBToJSON(get)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "ErrPbToJson:"+err.Error())
return
}
query := rpctypes.Query4Jrpc{
Execer: types2.X2ethereumX,
FuncName: types2.FuncQueryEthProphecy,
Payload: payLoad,
}
channel := &types2.ReceiptEthProphecy{}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", query, channel)
ctx.Run()
}
func queryValidatorsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "validators",
Short: "query current validators",
Run: queryValidators,
}
cmd.Flags().StringP("validator", "v", "", "write if you want to check specific validator")
//_ = cmd.MarkFlagRequired("validator")
return cmd
}
func queryValidators(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
validator, _ := cmd.Flags().GetString("validator")
get := &types2.QueryValidatorsParams{
Validator: validator,
}
payLoad, err := types.PBToJSON(get)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "ErrPbToJson:"+err.Error())
return
}
query := rpctypes.Query4Jrpc{
Execer: types2.X2ethereumX,
FuncName: types2.FuncQueryValidators,
Payload: payLoad,
}
channel := &types2.ReceiptQueryValidator{}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", query, channel)
ctx.Run()
}
func queryConsensusCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "consensus",
Short: "query current consensus need",
Run: queryConsensus,
}
return cmd
}
func queryConsensus(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
query := rpctypes.Query4Jrpc{
Execer: types2.X2ethereumX,
FuncName: types2.FuncQueryConsensusThreshold,
}
channel := &types2.ReceiptQueryConsensusThreshold{}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", query, channel)
ctx.Run()
}
func queryTotalPowerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "totalpower",
Short: "query current total power",
Run: queryTotalPower,
}
return cmd
}
func queryTotalPower(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
query := rpctypes.Query4Jrpc{
Execer: types2.X2ethereumX,
FuncName: types2.FuncQueryTotalPower,
}
channel := &types2.ReceiptQueryTotalPower{}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", query, channel)
ctx.Run()
}
func querySymbolTotalAmountByTxTypeCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "lockburnasset",
Short: "query current symbol total amount by tx type lock or withdraw",
Run: querySymbolTotalAmountByTxType,
}
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
cmd.Flags().Int64P("direction", "d", 0, "eth2chain33 = 1,chain33toeth = 2")
_ = cmd.MarkFlagRequired("direction")
cmd.Flags().Int64P("txtype", "t", 0, "lock = 1,burn = 2")
_ = cmd.MarkFlagRequired("txtype")
cmd.Flags().StringP("tokenaddress", "a", "", "token address,nil for all this token symbol,and if you want to query eth,you can also ignore it")
return cmd
}
func querySymbolTotalAmountByTxType(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
symbol, _ := cmd.Flags().GetString("symbol")
direction, _ := cmd.Flags().GetInt64("direction")
txType, _ := cmd.Flags().GetInt64("txtype")
contract, _ := cmd.Flags().GetString("tokenaddress")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
decimal, err := utils.GetDecimalsFromNode(contract, nodeAddr)
if err != nil {
fmt.Println("get decimal error")
return
}
if strings.ToLower(symbol) == "eth" && contract == "" {
contract = "0x0000000000000000000000000000000000000000"
}
var txTypeStr string
if txType == 1 {
txTypeStr = "lock"
} else if txType == 2 {
txTypeStr = "withdraw"
}
get := &types2.QuerySymbolAssetsByTxTypeParams{
TokenSymbol: symbol,
Direction: direction,
TxType: txTypeStr,
TokenAddr: contract,
Decimal: decimal,
}
payLoad, err := types.PBToJSON(get)
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, "ErrPbToJson:"+err.Error())
return
}
query := rpctypes.Query4Jrpc{
Execer: types2.X2ethereumX,
FuncName: types2.FuncQuerySymbolTotalAmountByTxType,
Payload: payLoad,
}
channel := &types2.ReceiptQuerySymbolAssets{}
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.Query", query, channel)
ctx.Run()
}
// 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 buildflags
// RPCAddr rpc address
var RPCAddr string
var NodeAddr string
package main
import (
"fmt"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/spf13/cobra"
)
// RelayerCmd command func
func Chain33RelayerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "chain33 ",
Short: "Chain33 relayer ",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
ImportPrivateKeyCmd(),
ShowValidatorAddrCmd(),
ShowTxsHashCmd(),
)
return cmd
}
// SetPwdCmd set password
func ImportPrivateKeyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "import_privatekey",
Short: "import ethereum private key to sign txs to be submitted to ethereum",
Run: importPrivatekey,
}
addImportPrivateKeyFlags(cmd)
return cmd
}
func addImportPrivateKeyFlags(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "ethereum private key")
cmd.MarkFlagRequired("key")
}
func importPrivatekey(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
privateKey, _ := cmd.Flags().GetString("key")
importKeyReq := ebTypes.ImportKeyReq{
PrivateKey: privateKey,
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ImportChain33RelayerPrivateKey", importKeyReq, &res)
ctx.Run()
}
func ShowValidatorAddrCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "show_validator",
Short: "show me the validator",
Run: showValidatorAddr,
}
return cmd
}
func showValidatorAddr(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowChain33RelayerValidator", nil, &res)
ctx.Run()
}
func ShowTxsHashCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "show_txhashes",
Short: "show me the tx hashes",
Run: showChain33Relayer2EthTxs,
}
return cmd
}
func showChain33Relayer2EthTxs(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res ebTypes.Txhashes
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowChain33Relayer2EthTxs", nil, &res)
if _, err := ctx.RunResult(); nil != err {
errInfo := err.Error()
fmt.Println("errinfo:" + errInfo)
return
}
for _, hash := range res.Txhash {
fmt.Println(hash)
}
}
// 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 main
import (
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
relayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/spf13/cobra"
)
// RelayerCmd command func
func RelayerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "relayer",
Short: "relayer of Chain33 and Ethereum ",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
SetPwdCmd(),
ChangePwdCmd(),
LockCmd(),
UnlockCmd(),
Chain33RelayerCmd(),
EthereumRelayerCmd(),
)
return cmd
}
// SetPwdCmd set password
func SetPwdCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "set_pwd",
Short: "Set password",
Run: setPwd,
}
addSetPwdFlags(cmd)
return cmd
}
func addSetPwdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("password", "p", "", "password,[8-30]letter and digit")
cmd.MarkFlagRequired("password")
}
func setPwd(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
newPwd, _ := cmd.Flags().GetString("password")
params := relayerTypes.ReqSetPasswd{
Passphase: newPwd,
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.SetPassphase", params, &res)
ctx.Run()
}
// ChangePwdCmd set password
func ChangePwdCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "change_pwd",
Short: "Change password",
Run: changePwd,
}
addChangePwdFlags(cmd)
return cmd
}
func addChangePwdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("old", "o", "", "old password")
cmd.MarkFlagRequired("old")
cmd.Flags().StringP("new", "n", "", "new password,[8-30]letter and digit")
cmd.MarkFlagRequired("new")
}
func changePwd(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
oldPwd, _ := cmd.Flags().GetString("old")
newPwd, _ := cmd.Flags().GetString("new")
params := relayerTypes.ReqChangePasswd{
OldPassphase: oldPwd,
NewPassphase: newPwd,
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ChangePassphase", params, &res)
ctx.Run()
}
// LockCmd lock the relayer manager
func LockCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "lock",
Short: "Lock relayer manager",
Run: lock,
}
return cmd
}
func lock(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.Lock", nil, &res)
ctx.Run()
}
// UnlockCmd unlock the wallet
func UnlockCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "unlock",
Short: "Unlock relayer manager",
Run: unLock,
}
addUnlockFlags(cmd)
return cmd
}
func addUnlockFlags(cmd *cobra.Command) {
cmd.Flags().StringP("pwd", "p", "", "password needed to unlock")
cmd.MarkFlagRequired("pwd")
}
func unLock(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
pwd, _ := cmd.Flags().GetString("pwd")
params := pwd
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.Unlock", params, &res)
ctx.Run()
}
package main
import (
"fmt"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
ethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/spf13/cobra"
)
// EthereumRelayerCmd command func
func EthereumRelayerCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "ethereum",
Short: "Ethereum relayer",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
ImportChain33PrivateKeyCmd(),
GenEthPrivateKeyCmd(),
ShowValidatorsAddrCmd(),
ShowChain33TxsHashCmd(),
ShowEthereumTxsHashCmd(),
IsValidatorActiveCmd(),
ShowOperatorCmd(),
DeployContrctsCmd(),
ShowTxReceiptCmd(),
//////auxiliary///////
CreateBridgeTokenCmd(),
CreateEthereumTokenCmd(),
GetBalanceCmd(),
IsProphecyPendingCmd(),
MintErc20Cmd(),
ApproveCmd(),
BurnCmd(),
BurnAsyncCmd(),
LockSyncCmd(),
LockAsyncCmd(),
ShowBridgeBankAddrCmd(),
ShowBridgeRegistryAddrCmd(),
StaticsCmd(),
TransferTokenCmd(),
GetToken2addressCmd(),
)
return cmd
}
func ImportChain33PrivateKeyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "import_chain33privatekey",
Short: "import chain33 private key to sign txs to be submitted to chain33",
Run: importChain33Privatekey,
}
addImportChain33PrivateKeyFlags(cmd)
return cmd
}
func addImportChain33PrivateKeyFlags(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "chain33 private key")
cmd.MarkFlagRequired("key")
}
func importChain33Privatekey(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
privateKey, _ := cmd.Flags().GetString("key")
params := privateKey
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ImportChain33PrivateKey4EthRelayer", params, &res)
ctx.Run()
}
func GenEthPrivateKeyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "create_eth_key",
Short: "create ethereum's private key to sign txs to be submitted to ethereum",
Run: generateEthereumPrivateKey,
}
return cmd
}
func generateEthereumPrivateKey(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res ebTypes.Account4Show
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.GenerateEthereumPrivateKey", nil, &res)
ctx.Run()
}
func ShowValidatorsAddrCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "show_validators",
Short: "show me the validators including ethereum and chain33",
Run: showValidatorsAddr,
}
return cmd
}
func showValidatorsAddr(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res ebTypes.ValidatorAddr4EthRelayer
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowEthRelayerValidator", nil, &res)
ctx.Run()
}
func ShowChain33TxsHashCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "show_chain33_tx",
Short: "show me the chain33 tx hashes",
Run: showChain33Txs,
}
return cmd
}
func showChain33Txs(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res ebTypes.Txhashes
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowEthRelayer2Chain33Txs", nil, &res)
if _, err := ctx.RunResult(); nil != err {
errInfo := err.Error()
fmt.Println("errinfo:" + errInfo)
return
}
for _, hash := range res.Txhash {
fmt.Println(hash)
}
}
func ShowEthereumTxsHashCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "show_eth_tx",
Short: "show me the ethereum tx hashes",
Run: showEthTxs,
}
return cmd
}
func showEthTxs(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res ebTypes.Txhashes
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowEthRelayer2Chain33Txs", nil, &res)
if _, err := ctx.RunResult(); nil != err {
errInfo := err.Error()
fmt.Println("errinfo:" + errInfo)
return
}
for _, hash := range res.Txhash {
fmt.Println(hash)
}
}
func IsValidatorActiveCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "active",
Short: "show whether the validator is active or not",
Run: IsValidatorActive,
}
IsValidatorActiveFlags(cmd)
return cmd
}
func IsValidatorActiveFlags(cmd *cobra.Command) {
cmd.Flags().StringP("addr", "a", "", "validator address")
_ = cmd.MarkFlagRequired("addr")
}
func IsValidatorActive(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
addr, _ := cmd.Flags().GetString("addr")
params := addr
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.IsValidatorActive", params, &res)
ctx.Run()
}
func ShowOperatorCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "operator",
Short: "show me the operator",
Run: ShowOperator,
}
return cmd
}
func ShowOperator(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res string
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowOperator", nil, &res)
ctx.Run()
}
func DeployContrctsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "deploy",
Short: "deploy the corresponding Ethereum contracts",
Run: DeployContrcts,
}
return cmd
}
func DeployContrcts(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.DeployContrcts", nil, &res)
ctx.Run()
}
func ShowTxReceiptCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "receipt",
Short: "show me the tx receipt for Ethereum",
Run: ShowTxReceipt,
}
ShowTxReceiptFlags(cmd)
return cmd
}
func ShowTxReceiptFlags(cmd *cobra.Command) {
cmd.Flags().StringP("hash", "s", "", "tx hash")
_ = cmd.MarkFlagRequired("hash")
}
func ShowTxReceipt(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
txhash, _ := cmd.Flags().GetString("hash")
para := txhash
var res ethTypes.Receipt
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowTxReceipt", para, &res)
ctx.Run()
}
func CreateBridgeTokenCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "token4chain33",
Short: "create new token as chain33 asset on Ethereum",
Run: CreateBridgeToken,
}
CreateBridgeTokenFlags(cmd)
return cmd
}
func CreateBridgeTokenFlags(cmd *cobra.Command) {
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
}
func CreateBridgeToken(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
token, _ := cmd.Flags().GetString("symbol")
para := token
var res ebTypes.ReplyAddr
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.CreateBridgeToken", para, &res)
ctx.Run()
}
func CreateEthereumTokenCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "token4erc20",
Short: "create new erc20 asset on Ethereum",
Run: CreateEthereumTokenToken,
}
CreateEthereumTokenFlags(cmd)
return cmd
}
func CreateEthereumTokenFlags(cmd *cobra.Command) {
cmd.Flags().StringP("symbol", "s", "", "token symbol")
_ = cmd.MarkFlagRequired("symbol")
}
func CreateEthereumTokenToken(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
token, _ := cmd.Flags().GetString("symbol")
para := token
var res ebTypes.ReplyAddr
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.CreateERC20Token", para, &res)
ctx.Run()
}
func MintErc20Cmd() *cobra.Command {
cmd := &cobra.Command{
Use: "mint",
Short: "mint erc20 asset on Ethereum, but only for operator",
Run: MintErc20,
}
MintErc20Flags(cmd)
return cmd
}
func MintErc20Flags(cmd *cobra.Command) {
cmd.Flags().StringP("token", "t", "", "token address")
_ = cmd.MarkFlagRequired("token")
cmd.Flags().StringP("owner", "o", "", "owner address")
_ = cmd.MarkFlagRequired("owner")
cmd.Flags().Float64P("amount", "m", float64(0), "amount")
_ = cmd.MarkFlagRequired("amount")
}
func MintErc20(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
tokenAddr, _ := cmd.Flags().GetString("token")
owner, _ := cmd.Flags().GetString("owner")
amount, _ := cmd.Flags().GetFloat64("amount")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
d, err := utils.GetDecimalsFromNode(tokenAddr, nodeAddr)
if err != nil {
fmt.Println("get decimals error")
return
}
realAmount := types.ToWei(amount, d)
para := ebTypes.MintToken{
Owner: owner,
TokenAddr: tokenAddr,
Amount: realAmount.String(),
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.MintErc20", para, &res)
ctx.Run()
}
func ApproveCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "approve",
Short: "approve the allowance to bridgebank by the owner",
Run: ApproveAllowance,
}
ApproveAllowanceFlags(cmd)
return cmd
}
func ApproveAllowanceFlags(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "owner private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("token", "t", "", "token address")
_ = cmd.MarkFlagRequired("token")
cmd.Flags().Float64P("amount", "m", float64(0), "amount")
_ = cmd.MarkFlagRequired("amount")
}
func ApproveAllowance(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
key, _ := cmd.Flags().GetString("key")
tokenAddr, _ := cmd.Flags().GetString("token")
amount, _ := cmd.Flags().GetFloat64("amount")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
d, err := utils.GetDecimalsFromNode(tokenAddr, nodeAddr)
if err != nil {
fmt.Println("get decimals error")
return
}
realAmount := types.ToWei(amount, d)
para := ebTypes.ApproveAllowance{
OwnerKey: key,
TokenAddr: tokenAddr,
Amount: realAmount.String(),
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ApproveAllowance", para, &res)
ctx.Run()
}
func BurnCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "burn",
Short: "burn(including approve) the asset to make it unlocked on chain33",
Run: Burn,
}
BurnFlags(cmd)
return cmd
}
func BurnAsyncCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "burn-async",
Short: "async burn the asset to make it unlocked on chain33",
Run: BurnAsync,
}
BurnFlags(cmd)
return cmd
}
func BurnFlags(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "owner private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("token", "t", "", "token address")
_ = cmd.MarkFlagRequired("token")
cmd.Flags().StringP("receiver", "r", "", "receiver address on chain33")
_ = cmd.MarkFlagRequired("receiver")
cmd.Flags().Float64P("amount", "m", float64(0), "amount")
_ = cmd.MarkFlagRequired("amount")
}
func Burn(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
key, _ := cmd.Flags().GetString("key")
tokenAddr, _ := cmd.Flags().GetString("token")
amount, _ := cmd.Flags().GetFloat64("amount")
receiver, _ := cmd.Flags().GetString("receiver")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
d, err := utils.GetDecimalsFromNode(tokenAddr, nodeAddr)
if err != nil {
fmt.Println("get decimals err")
return
}
para := ebTypes.Burn{
OwnerKey: key,
TokenAddr: tokenAddr,
Amount: types.ToWei(amount, d).String(),
Chain33Receiver: receiver,
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.Burn", para, &res)
ctx.Run()
}
func BurnAsync(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
key, _ := cmd.Flags().GetString("key")
tokenAddr, _ := cmd.Flags().GetString("token")
amount, _ := cmd.Flags().GetFloat64("amount")
receiver, _ := cmd.Flags().GetString("receiver")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
d, err := utils.GetDecimalsFromNode(tokenAddr, nodeAddr)
if err != nil {
fmt.Println("get decimals err")
return
}
para := ebTypes.Burn{
OwnerKey: key,
TokenAddr: tokenAddr,
Amount: types.ToWei(amount, d).String(),
Chain33Receiver: receiver,
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.BurnAsync", para, &res)
ctx.Run()
}
func LockSyncCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "lock",
Short: "lock(including approve) eth or erc20 and cross-chain transfer to chain33",
Run: LockEthErc20Asset,
}
LockEthErc20AssetFlags(cmd)
return cmd
}
func LockAsyncCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "lock-async",
Short: "async lock eth or erc20 and cross-chain transfer to chain33",
Run: LockEthErc20AssetAsync,
}
LockEthErc20AssetFlags(cmd)
return cmd
}
func LockEthErc20AssetFlags(cmd *cobra.Command) {
cmd.Flags().StringP("key", "k", "", "owner private key")
_ = cmd.MarkFlagRequired("key")
cmd.Flags().StringP("token", "t", "", "token address, optional, nil for ETH")
cmd.Flags().Float64P("amount", "m", float64(0), "amount")
_ = cmd.MarkFlagRequired("amount")
cmd.Flags().StringP("receiver", "r", "", "chain33 receiver address")
_ = cmd.MarkFlagRequired("receiver")
}
func LockEthErc20Asset(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
key, _ := cmd.Flags().GetString("key")
tokenAddr, _ := cmd.Flags().GetString("token")
amount, _ := cmd.Flags().GetFloat64("amount")
receiver, _ := cmd.Flags().GetString("receiver")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
d, err := utils.GetDecimalsFromNode(tokenAddr, nodeAddr)
if err != nil {
fmt.Println("get decimals err")
return
}
realAmount := types.ToWei(amount, d)
para := ebTypes.LockEthErc20{
OwnerKey: key,
TokenAddr: tokenAddr,
Amount: realAmount.String(),
Chain33Receiver: receiver,
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.LockEthErc20Asset", para, &res)
ctx.Run()
}
func LockEthErc20AssetAsync(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
key, _ := cmd.Flags().GetString("key")
tokenAddr, _ := cmd.Flags().GetString("token")
amount, _ := cmd.Flags().GetFloat64("amount")
receiver, _ := cmd.Flags().GetString("receiver")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
d, err := utils.GetDecimalsFromNode(tokenAddr, nodeAddr)
if err != nil {
fmt.Println("get decimals err")
return
}
realAmount := types.ToWei(amount, d)
para := ebTypes.LockEthErc20{
OwnerKey: key,
TokenAddr: tokenAddr,
Amount: realAmount.String(),
Chain33Receiver: receiver,
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.LockEthErc20AssetAsync", para, &res)
ctx.Run()
}
func ShowBridgeBankAddrCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "bridgeBankAddr",
Short: "show the address of Contract BridgeBank",
Run: ShowBridgeBankAddr,
}
return cmd
}
func ShowBridgeBankAddr(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res ebTypes.ReplyAddr
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowBridgeBankAddr", nil, &res)
ctx.Run()
}
func ShowBridgeRegistryAddrCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "bridgeRegistry",
Short: "show the address of Contract BridgeRegistry",
Run: ShowBridgeRegistryAddr,
}
return cmd
}
func ShowBridgeRegistryAddr(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
var res ebTypes.ReplyAddr
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowBridgeRegistryAddr", nil, &res)
ctx.Run()
}
func GetBalanceCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "balance",
Short: "get owner's balance for ETH or ERC20",
Run: GetBalance,
}
GetBalanceFlags(cmd)
return cmd
}
func GetBalanceFlags(cmd *cobra.Command) {
cmd.Flags().StringP("owner", "o", "", "owner address")
_ = cmd.MarkFlagRequired("owner")
cmd.Flags().StringP("tokenAddr", "t", "", "token address, optional, nil for Eth")
}
func GetBalance(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
owner, _ := cmd.Flags().GetString("owner")
tokenAddr, _ := cmd.Flags().GetString("tokenAddr")
para := ebTypes.BalanceAddr{
Owner: owner,
TokenAddr: tokenAddr,
}
var res ebTypes.ReplyBalance
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.GetBalance", para, &res)
ctx.Run()
}
func IsProphecyPendingCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "ispending",
Short: "check whether the Prophecy is pending or not",
Run: IsProphecyPending,
}
IsProphecyPendingFlags(cmd)
return cmd
}
func IsProphecyPendingFlags(cmd *cobra.Command) {
cmd.Flags().StringP("id", "i", "", "claim prophecy id")
_ = cmd.MarkFlagRequired("id")
}
func IsProphecyPending(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
id, _ := cmd.Flags().GetString("id")
para := common.HexToHash(id)
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.IsProphecyPending", para, &res)
ctx.Run()
}
func TransferTokenCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "transfer",
Short: "create a transfer transaction",
Run: TransferToken,
}
TransferTokenFlags(cmd)
return cmd
}
func TransferTokenFlags(cmd *cobra.Command) {
cmd.Flags().StringP("token", "t", "", "token address")
_ = cmd.MarkFlagRequired("token")
cmd.Flags().StringP("from", "k", "", "from private key")
_ = cmd.MarkFlagRequired("from")
cmd.Flags().StringP("to", "r", "", "to address")
_ = cmd.MarkFlagRequired("to")
cmd.Flags().Float64P("amount", "m", 0, "amount")
_ = cmd.MarkFlagRequired("amount")
}
func TransferToken(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
tokenAddr, _ := cmd.Flags().GetString("token")
from, _ := cmd.Flags().GetString("from")
to, _ := cmd.Flags().GetString("to")
amount, _ := cmd.Flags().GetFloat64("amount")
nodeAddr, _ := cmd.Flags().GetString("node_addr")
d, err := utils.GetDecimalsFromNode(tokenAddr, nodeAddr)
if err != nil {
fmt.Println("get decimals error")
return
}
realAmount := types.ToWei(amount, d)
para := ebTypes.TransferToken{
TokenAddr: tokenAddr,
FromKey: from,
ToAddr: to,
Amount: realAmount.String(),
}
var res rpctypes.Reply
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.TransferToken", para, &res)
ctx.Run()
}
func GetToken2addressCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "tokenaddr",
Short: "get token address by symbol",
Run: GetToken2address,
}
GetToken2addressFlags(cmd)
return cmd
}
func GetToken2addressFlags(cmd *cobra.Command) {
cmd.Flags().StringP("token", "t", "", "token symbol")
_ = cmd.MarkFlagRequired("token")
}
func GetToken2address(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
tokenSymbol, _ := cmd.Flags().GetString("token")
para := ebTypes.TokenStatics{
TokenAddr: tokenSymbol,
}
var res ebTypes.ReplyAddr
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowTokenAddrBySymbol", para, &res)
ctx.Run()
}
// 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 main
import (
"fmt"
"net/http"
"os"
"strings"
"github.com/33cn/chain33/common/log"
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebcli/buildflags"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "chain33xEth-relayer" + "-cli",
Short: "chain33xEth-relayer" + "client tools",
}
func init() {
rootCmd.AddCommand(
RelayerCmd(),
)
}
func testTLS(RPCAddr string) string {
rpcaddr := RPCAddr
if strings.HasPrefix(rpcaddr, "https://") {
return RPCAddr
}
if !strings.HasPrefix(rpcaddr, "http://") {
return RPCAddr
}
//test tls ok
if rpcaddr[len(rpcaddr)-1] != '/' {
rpcaddr += "/"
}
rpcaddr += "test"
resp, err := http.Get(rpcaddr)
if err != nil {
return "https://" + RPCAddr[7:]
}
defer resp.Body.Close()
if resp.StatusCode == 200 {
return RPCAddr
}
return "https://" + RPCAddr[7:]
}
//run :
func run(RPCAddr, NodeAddr string) {
//test tls is enable
RPCAddr = testTLS(RPCAddr)
pluginmgr.AddCmd(rootCmd)
log.SetLogLevel("error")
rootCmd.PersistentFlags().String("rpc_laddr", RPCAddr, "http url")
rootCmd.PersistentFlags().String("node_addr", NodeAddr, "eth node url")
//rootCmd.PersistentFlags().String("rpc_laddr", "", "http url")
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func main() {
if buildflags.RPCAddr == "" {
buildflags.RPCAddr = "http://localhost:9901"
}
if buildflags.NodeAddr == "" {
buildflags.NodeAddr = "http://127.0.0.1:7545"
}
run(buildflags.RPCAddr, buildflags.NodeAddr)
}
package main
import (
"github.com/33cn/chain33/rpc/jsonclient"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/spf13/cobra"
)
func StaticsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "statics",
Short: "statics of lock/unlock Eth or ERC20,or deposit/burn chain33 asset ",
Args: cobra.MinimumNArgs(1),
}
cmd.AddCommand(
ShowLockStaticsCmd(),
ShowDepositStaticsCmd(),
)
return cmd
}
func ShowLockStaticsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "lock",
Short: "show the lock statics of ETH or ERC20",
Run: ShowLockStatics,
}
ShowLockStaticsFlags(cmd)
return cmd
}
func ShowLockStaticsFlags(cmd *cobra.Command) {
cmd.Flags().StringP("token", "t", "", "token address, optional, nil for ETH")
}
func ShowLockStatics(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
tokenAddr, _ := cmd.Flags().GetString("token")
para := ebTypes.TokenStatics{
TokenAddr: tokenAddr,
}
var res ebTypes.StaticsLock
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowLockStatics", para, &res)
ctx.Run()
}
func ShowDepositStaticsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "deposit",
Short: "show the deposit statics of chain33 asset",
Run: ShowDepositStatics,
}
ShowDepositStaticsFlags(cmd)
return cmd
}
func ShowDepositStaticsFlags(cmd *cobra.Command) {
cmd.Flags().StringP("token", "t", "", "token address")
_ = cmd.MarkFlagRequired("token")
}
func ShowDepositStatics(cmd *cobra.Command, args []string) {
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
tokenAddr, _ := cmd.Flags().GetString("token")
para := ebTypes.TokenStatics{
TokenAddr: tokenAddr,
}
var res ebTypes.StaticsDeposit
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Manager.ShowDepositStatics", para, &res)
ctx.Run()
}
##
##编译solidity,并产生bin文件,abi文件,和相应的go文件
SRC_CONTRACT := sol_contracts
#SRC_CONTRACT := github.com/33cn/plugin/plugin/dapp/x2Ethereum/ebrelayer/ethcontract/sol_contracts
GO_OUT := generated
PACKAGE := generated
proj := "build"
.PHONY: default build clean registry bridgeBank setup
default: depends build
build: depends
@abigen --sol $(SRC_CONTRACT)/BridgeRegistry.sol --pkg $(PACKAGE) --out $(GO_OUT)/BridgeRegistry.go
@abigen --sol $(SRC_CONTRACT)/BridgeBank/BridgeBank.sol --pkg $(PACKAGE) --out $(GO_OUT)/BridgeBank.go
#@abigen --sol $(SRC_CONTRACT)/CosmosBridge.sol --pkg $(PACKAGE) --out $(GO_OUT)/CosmosBridge.go
#@abigen --sol $(SRC_CONTRACT)/Oracle.sol --pkg $(PACKAGE) --out $(GO_OUT)/Oracle.go
#@abigen --sol $(SRC_CONTRACT)/Valset.sol --pkg $(PACKAGE) --out $(GO_OUT)/Valset.go
clean:
@rm -fr $(GO_OUT)/*
registry:
@abigen --sol $(SRC_CONTRACT)/BridgeRegistry.sol --pkg $(PACKAGE) --out $(GO_OUT)/BridgeRegistry.go
bridgeBank:
@abigen --sol $(SRC_CONTRACT)/BridgeBank/BridgeBank.sol --pkg $(PACKAGE) --out $(GO_OUT)/BridgeBank.go
depends:
if ! [ -d openzeppelin-solidity ]; then \
echo "not exist openzeppelin-solidity and going to get" ; \
go get github.com/OpenZeppelin/openzeppelin-contracts@v2.5 ; \
mkdir openzeppelin-solidity ;\
cp -r ${GOPATH}/pkg/mod/github.com/\!open\!zeppelin/openzeppelin-contracts@v2.5.0+incompatible/contracts openzeppelin-solidity ; \
fi; \
This source diff could not be displayed because it is too large. You can view the blob instead.
// Code generated - DO NOT EDIT.
// This file is a generated binding and any manual changes will be lost.
package generated
import (
"math/big"
"strings"
ethereum "github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
)
// Reference imports to suppress errors if they are not otherwise used.
var (
_ = big.NewInt
_ = strings.NewReader
_ = ethereum.NotFound
_ = abi.U256
_ = bind.Bind
_ = common.Big1
_ = types.BloomLookup
_ = event.NewSubscription
)
// BridgeRegistryABI is the input ABI used to generate the binding from.
const BridgeRegistryABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"bridgeBank\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"deployHeight\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"valset\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"chain33Bridge\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"name\":\"_chain33Bridge\",\"type\":\"address\"},{\"name\":\"_bridgeBank\",\"type\":\"address\"},{\"name\":\"_oracle\",\"type\":\"address\"},{\"name\":\"_valset\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"_chain33Bridge\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_bridgeBank\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_oracle\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_valset\",\"type\":\"address\"}],\"name\":\"LogContractsRegistered\",\"type\":\"event\"}]"
// BridgeRegistryFuncSigs maps the 4-byte function signature to its string representation.
var BridgeRegistryFuncSigs = map[string]string{
"0e41f373": "bridgeBank()",
"eb355352": "chain33Bridge()",
"53d953b5": "deployHeight()",
"7dc0d1d0": "oracle()",
"7f54af0c": "valset()",
}
// BridgeRegistryBin is the compiled bytecode used for deploying new contracts.
var BridgeRegistryBin = "0x608060405234801561001057600080fd5b506040516080806102b78339810180604052608081101561003057600080fd5b50805160208083015160408085015160609586015160008054600160a060020a03808916600160a060020a031992831617928390556001805482891690841617908190556002805483881690851617908190556003805484881695169490941793849055436004558751948316855290821698840198909852968716828601529095169685019690965290519394919390927f039b733f31259b106f1d278c726870d5b28c7db22957d63df8dbaa70bd3a032a919081900360800190a1505050506101b7806101006000396000f3fe60806040526004361061006c5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416630e41f373811461007157806353d953b5146100af5780637dc0d1d0146100d65780637f54af0c146100eb578063eb35535214610100575b600080fd5b34801561007d57600080fd5b50610086610115565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b3480156100bb57600080fd5b506100c4610131565b60408051918252519081900360200190f35b3480156100e257600080fd5b50610086610137565b3480156100f757600080fd5b50610086610153565b34801561010c57600080fd5b5061008661016f565b60015473ffffffffffffffffffffffffffffffffffffffff1681565b60045481565b60025473ffffffffffffffffffffffffffffffffffffffff1681565b60035473ffffffffffffffffffffffffffffffffffffffff1681565b60005473ffffffffffffffffffffffffffffffffffffffff168156fea165627a7a72305820bb308a31657002b318d16d39a635d309141c0cc5aef32e8c33b53192d1df4cbc0029"
// DeployBridgeRegistry deploys a new Ethereum contract, binding an instance of BridgeRegistry to it.
func DeployBridgeRegistry(auth *bind.TransactOpts, backend bind.ContractBackend, _chain33Bridge common.Address, _bridgeBank common.Address, _oracle common.Address, _valset common.Address) (common.Address, *types.Transaction, *BridgeRegistry, error) {
parsed, err := abi.JSON(strings.NewReader(BridgeRegistryABI))
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(BridgeRegistryBin), backend, _chain33Bridge, _bridgeBank, _oracle, _valset)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &BridgeRegistry{BridgeRegistryCaller: BridgeRegistryCaller{contract: contract}, BridgeRegistryTransactor: BridgeRegistryTransactor{contract: contract}, BridgeRegistryFilterer: BridgeRegistryFilterer{contract: contract}}, nil
}
// BridgeRegistry is an auto generated Go binding around an Ethereum contract.
type BridgeRegistry struct {
BridgeRegistryCaller // Read-only binding to the contract
BridgeRegistryTransactor // Write-only binding to the contract
BridgeRegistryFilterer // Log filterer for contract events
}
// BridgeRegistryCaller is an auto generated read-only Go binding around an Ethereum contract.
type BridgeRegistryCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// BridgeRegistryTransactor is an auto generated write-only Go binding around an Ethereum contract.
type BridgeRegistryTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// BridgeRegistryFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
type BridgeRegistryFilterer struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// BridgeRegistrySession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type BridgeRegistrySession struct {
Contract *BridgeRegistry // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// BridgeRegistryCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type BridgeRegistryCallerSession struct {
Contract *BridgeRegistryCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// BridgeRegistryTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type BridgeRegistryTransactorSession struct {
Contract *BridgeRegistryTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// BridgeRegistryRaw is an auto generated low-level Go binding around an Ethereum contract.
type BridgeRegistryRaw struct {
Contract *BridgeRegistry // Generic contract binding to access the raw methods on
}
// BridgeRegistryCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type BridgeRegistryCallerRaw struct {
Contract *BridgeRegistryCaller // Generic read-only contract binding to access the raw methods on
}
// BridgeRegistryTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type BridgeRegistryTransactorRaw struct {
Contract *BridgeRegistryTransactor // Generic write-only contract binding to access the raw methods on
}
// NewBridgeRegistry creates a new instance of BridgeRegistry, bound to a specific deployed contract.
func NewBridgeRegistry(address common.Address, backend bind.ContractBackend) (*BridgeRegistry, error) {
contract, err := bindBridgeRegistry(address, backend, backend, backend)
if err != nil {
return nil, err
}
return &BridgeRegistry{BridgeRegistryCaller: BridgeRegistryCaller{contract: contract}, BridgeRegistryTransactor: BridgeRegistryTransactor{contract: contract}, BridgeRegistryFilterer: BridgeRegistryFilterer{contract: contract}}, nil
}
// NewBridgeRegistryCaller creates a new read-only instance of BridgeRegistry, bound to a specific deployed contract.
func NewBridgeRegistryCaller(address common.Address, caller bind.ContractCaller) (*BridgeRegistryCaller, error) {
contract, err := bindBridgeRegistry(address, caller, nil, nil)
if err != nil {
return nil, err
}
return &BridgeRegistryCaller{contract: contract}, nil
}
// NewBridgeRegistryTransactor creates a new write-only instance of BridgeRegistry, bound to a specific deployed contract.
func NewBridgeRegistryTransactor(address common.Address, transactor bind.ContractTransactor) (*BridgeRegistryTransactor, error) {
contract, err := bindBridgeRegistry(address, nil, transactor, nil)
if err != nil {
return nil, err
}
return &BridgeRegistryTransactor{contract: contract}, nil
}
// NewBridgeRegistryFilterer creates a new log filterer instance of BridgeRegistry, bound to a specific deployed contract.
func NewBridgeRegistryFilterer(address common.Address, filterer bind.ContractFilterer) (*BridgeRegistryFilterer, error) {
contract, err := bindBridgeRegistry(address, nil, nil, filterer)
if err != nil {
return nil, err
}
return &BridgeRegistryFilterer{contract: contract}, nil
}
// bindBridgeRegistry binds a generic wrapper to an already deployed contract.
func bindBridgeRegistry(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(BridgeRegistryABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor, filterer), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_BridgeRegistry *BridgeRegistryRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _BridgeRegistry.Contract.BridgeRegistryCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_BridgeRegistry *BridgeRegistryRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _BridgeRegistry.Contract.BridgeRegistryTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_BridgeRegistry *BridgeRegistryRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _BridgeRegistry.Contract.BridgeRegistryTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_BridgeRegistry *BridgeRegistryCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _BridgeRegistry.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_BridgeRegistry *BridgeRegistryTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _BridgeRegistry.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_BridgeRegistry *BridgeRegistryTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _BridgeRegistry.Contract.contract.Transact(opts, method, params...)
}
// BridgeBank is a free data retrieval call binding the contract method 0x0e41f373.
//
// Solidity: function bridgeBank() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCaller) BridgeBank(opts *bind.CallOpts) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _BridgeRegistry.contract.Call(opts, out, "bridgeBank")
return *ret0, err
}
// BridgeBank is a free data retrieval call binding the contract method 0x0e41f373.
//
// Solidity: function bridgeBank() constant returns(address)
func (_BridgeRegistry *BridgeRegistrySession) BridgeBank() (common.Address, error) {
return _BridgeRegistry.Contract.BridgeBank(&_BridgeRegistry.CallOpts)
}
// BridgeBank is a free data retrieval call binding the contract method 0x0e41f373.
//
// Solidity: function bridgeBank() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCallerSession) BridgeBank() (common.Address, error) {
return _BridgeRegistry.Contract.BridgeBank(&_BridgeRegistry.CallOpts)
}
// Chain33Bridge is a free data retrieval call binding the contract method 0xeb355352.
//
// Solidity: function chain33Bridge() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCaller) Chain33Bridge(opts *bind.CallOpts) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _BridgeRegistry.contract.Call(opts, out, "chain33Bridge")
return *ret0, err
}
// Chain33Bridge is a free data retrieval call binding the contract method 0xeb355352.
//
// Solidity: function chain33Bridge() constant returns(address)
func (_BridgeRegistry *BridgeRegistrySession) Chain33Bridge() (common.Address, error) {
return _BridgeRegistry.Contract.Chain33Bridge(&_BridgeRegistry.CallOpts)
}
// Chain33Bridge is a free data retrieval call binding the contract method 0xeb355352.
//
// Solidity: function chain33Bridge() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCallerSession) Chain33Bridge() (common.Address, error) {
return _BridgeRegistry.Contract.Chain33Bridge(&_BridgeRegistry.CallOpts)
}
// DeployHeight is a free data retrieval call binding the contract method 0x53d953b5.
//
// Solidity: function deployHeight() constant returns(uint256)
func (_BridgeRegistry *BridgeRegistryCaller) DeployHeight(opts *bind.CallOpts) (*big.Int, error) {
var (
ret0 = new(*big.Int)
)
out := ret0
err := _BridgeRegistry.contract.Call(opts, out, "deployHeight")
return *ret0, err
}
// DeployHeight is a free data retrieval call binding the contract method 0x53d953b5.
//
// Solidity: function deployHeight() constant returns(uint256)
func (_BridgeRegistry *BridgeRegistrySession) DeployHeight() (*big.Int, error) {
return _BridgeRegistry.Contract.DeployHeight(&_BridgeRegistry.CallOpts)
}
// DeployHeight is a free data retrieval call binding the contract method 0x53d953b5.
//
// Solidity: function deployHeight() constant returns(uint256)
func (_BridgeRegistry *BridgeRegistryCallerSession) DeployHeight() (*big.Int, error) {
return _BridgeRegistry.Contract.DeployHeight(&_BridgeRegistry.CallOpts)
}
// Oracle is a free data retrieval call binding the contract method 0x7dc0d1d0.
//
// Solidity: function oracle() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCaller) Oracle(opts *bind.CallOpts) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _BridgeRegistry.contract.Call(opts, out, "oracle")
return *ret0, err
}
// Oracle is a free data retrieval call binding the contract method 0x7dc0d1d0.
//
// Solidity: function oracle() constant returns(address)
func (_BridgeRegistry *BridgeRegistrySession) Oracle() (common.Address, error) {
return _BridgeRegistry.Contract.Oracle(&_BridgeRegistry.CallOpts)
}
// Oracle is a free data retrieval call binding the contract method 0x7dc0d1d0.
//
// Solidity: function oracle() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCallerSession) Oracle() (common.Address, error) {
return _BridgeRegistry.Contract.Oracle(&_BridgeRegistry.CallOpts)
}
// Valset is a free data retrieval call binding the contract method 0x7f54af0c.
//
// Solidity: function valset() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCaller) Valset(opts *bind.CallOpts) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _BridgeRegistry.contract.Call(opts, out, "valset")
return *ret0, err
}
// Valset is a free data retrieval call binding the contract method 0x7f54af0c.
//
// Solidity: function valset() constant returns(address)
func (_BridgeRegistry *BridgeRegistrySession) Valset() (common.Address, error) {
return _BridgeRegistry.Contract.Valset(&_BridgeRegistry.CallOpts)
}
// Valset is a free data retrieval call binding the contract method 0x7f54af0c.
//
// Solidity: function valset() constant returns(address)
func (_BridgeRegistry *BridgeRegistryCallerSession) Valset() (common.Address, error) {
return _BridgeRegistry.Contract.Valset(&_BridgeRegistry.CallOpts)
}
// BridgeRegistryLogContractsRegisteredIterator is returned from FilterLogContractsRegistered and is used to iterate over the raw logs and unpacked data for LogContractsRegistered events raised by the BridgeRegistry contract.
type BridgeRegistryLogContractsRegisteredIterator struct {
Event *BridgeRegistryLogContractsRegistered // Event containing the contract specifics and raw log
contract *bind.BoundContract // Generic contract to use for unpacking event data
event string // Event name to use for unpacking event data
logs chan types.Log // Log channel receiving the found contract events
sub ethereum.Subscription // Subscription for errors, completion and termination
done bool // Whether the subscription completed delivering logs
fail error // Occurred error to stop iteration
}
// Next advances the iterator to the subsequent event, returning whether there
// are any more events found. In case of a retrieval or parsing error, false is
// returned and Error() can be queried for the exact failure.
func (it *BridgeRegistryLogContractsRegisteredIterator) Next() bool {
// If the iterator failed, stop iterating
if it.fail != nil {
return false
}
// If the iterator completed, deliver directly whatever's available
if it.done {
select {
case log := <-it.logs:
it.Event = new(BridgeRegistryLogContractsRegistered)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
default:
return false
}
}
// Iterator still in progress, wait for either a data or an error event
select {
case log := <-it.logs:
it.Event = new(BridgeRegistryLogContractsRegistered)
if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
it.fail = err
return false
}
it.Event.Raw = log
return true
case err := <-it.sub.Err():
it.done = true
it.fail = err
return it.Next()
}
}
// Error returns any retrieval or parsing error occurred during filtering.
func (it *BridgeRegistryLogContractsRegisteredIterator) Error() error {
return it.fail
}
// Close terminates the iteration process, releasing any pending underlying
// resources.
func (it *BridgeRegistryLogContractsRegisteredIterator) Close() error {
it.sub.Unsubscribe()
return nil
}
// BridgeRegistryLogContractsRegistered represents a LogContractsRegistered event raised by the BridgeRegistry contract.
type BridgeRegistryLogContractsRegistered struct {
Chain33Bridge common.Address
BridgeBank common.Address
Oracle common.Address
Valset common.Address
Raw types.Log // Blockchain specific contextual infos
}
// FilterLogContractsRegistered is a free log retrieval operation binding the contract event 0x039b733f31259b106f1d278c726870d5b28c7db22957d63df8dbaa70bd3a032a.
//
// Solidity: event LogContractsRegistered(address _chain33Bridge, address _bridgeBank, address _oracle, address _valset)
func (_BridgeRegistry *BridgeRegistryFilterer) FilterLogContractsRegistered(opts *bind.FilterOpts) (*BridgeRegistryLogContractsRegisteredIterator, error) {
logs, sub, err := _BridgeRegistry.contract.FilterLogs(opts, "LogContractsRegistered")
if err != nil {
return nil, err
}
return &BridgeRegistryLogContractsRegisteredIterator{contract: _BridgeRegistry.contract, event: "LogContractsRegistered", logs: logs, sub: sub}, nil
}
// WatchLogContractsRegistered is a free log subscription operation binding the contract event 0x039b733f31259b106f1d278c726870d5b28c7db22957d63df8dbaa70bd3a032a.
//
// Solidity: event LogContractsRegistered(address _chain33Bridge, address _bridgeBank, address _oracle, address _valset)
func (_BridgeRegistry *BridgeRegistryFilterer) WatchLogContractsRegistered(opts *bind.WatchOpts, sink chan<- *BridgeRegistryLogContractsRegistered) (event.Subscription, error) {
logs, sub, err := _BridgeRegistry.contract.WatchLogs(opts, "LogContractsRegistered")
if err != nil {
return nil, err
}
return event.NewSubscription(func(quit <-chan struct{}) error {
defer sub.Unsubscribe()
for {
select {
case log := <-logs:
// New log arrived, parse the event and forward to the user
event := new(BridgeRegistryLogContractsRegistered)
if err := _BridgeRegistry.contract.UnpackLog(event, "LogContractsRegistered", log); err != nil {
return err
}
event.Raw = log
select {
case sink <- event:
case err := <-sub.Err():
return err
case <-quit:
return nil
}
case err := <-sub.Err():
return err
case <-quit:
return nil
}
}
}), nil
}
// ParseLogContractsRegistered is a log parse operation binding the contract event 0x039b733f31259b106f1d278c726870d5b28c7db22957d63df8dbaa70bd3a032a.
//
// Solidity: event LogContractsRegistered(address _chain33Bridge, address _bridgeBank, address _oracle, address _valset)
func (_BridgeRegistry *BridgeRegistryFilterer) ParseLogContractsRegistered(log types.Log) (*BridgeRegistryLogContractsRegistered, error) {
event := new(BridgeRegistryLogContractsRegistered)
if err := _BridgeRegistry.contract.UnpackLog(event, "LogContractsRegistered", log); err != nil {
return nil, err
}
return event, nil
}
pragma solidity ^0.5.0;
import "./Chain33Bank.sol";
import "./EthereumBank.sol";
import "../Oracle.sol";
import "../Chain33Bridge.sol";
/**
* @title BridgeBank
* @dev Bank contract which coordinates asset-related functionality.
* Chain33Bank manages the minting and burning of tokens which
* represent Chain33 based assets, while EthereumBank manages
* the locking and unlocking of Ethereum and ERC20 token assets
* based on Ethereum.
**/
contract BridgeBank is Chain33Bank, EthereumBank {
using SafeMath for uint256;
address public operator;
Oracle public oracle;
Chain33Bridge public chain33Bridge;
/*
* @dev: Constructor, sets operator
*/
constructor (
address _operatorAddress,
address _oracleAddress,
address _chain33BridgeAddress
)
public
{
operator = _operatorAddress;
oracle = Oracle(_oracleAddress);
chain33Bridge = Chain33Bridge(_chain33BridgeAddress);
}
/*
* @dev: Modifier to restrict access to operator
*/
modifier onlyOperator() {
require(
msg.sender == operator,
'Must be BridgeBank operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to the oracle
*/
modifier onlyOracle()
{
require(
msg.sender == address(oracle),
"Access restricted to the oracle"
);
_;
}
/*
* @dev: Modifier to restrict access to the chain33 bridge
*/
modifier onlyChain33Bridge()
{
require(
msg.sender == address(chain33Bridge),
"Access restricted to the chain33 bridge"
);
_;
}
/*
* @dev: Fallback function allows operator to send funds to the bank directly
* This feature is used for testing and is available at the operator's own risk.
*/
function() external payable onlyOperator {}
/*
* @dev: Creates a new BridgeToken
*
* @param _symbol: The new BridgeToken's symbol
* @return: The new BridgeToken contract's address
*/
function createNewBridgeToken(
string memory _symbol
)
public
onlyOperator
returns(address)
{
return deployNewBridgeToken(_symbol);
}
/*
* @dev: Mints new BankTokens
*
* @param _chain33Sender: The sender's Chain33 address in bytes.
* @param _ethereumRecipient: The intended recipient's Ethereum address.
* @param _chain33TokenAddress: The currency type
* @param _symbol: chain33 token symbol
* @param _amount: number of chain33 tokens to be minted
*/
function mintBridgeTokens(
bytes memory _chain33Sender,
address payable _intendedRecipient,
address _bridgeTokenAddress,
string memory _symbol,
uint256 _amount
)
public
onlyChain33Bridge
{
return mintNewBridgeTokens(
_chain33Sender,
_intendedRecipient,
_bridgeTokenAddress,
_symbol,
_amount
);
}
/*
* @dev: Burns bank tokens
*
* @param _chain33Receiver: The _chain33 receiver address in bytes.
* @param _chain33TokenAddress: The currency type
* @param _amount: number of chain33 tokens to be burned
*/
function burnBridgeTokens(
bytes memory _chain33Receiver,
address _chain33TokenAddress,
uint256 _amount
)
public
{
return burnChain33Tokens(
msg.sender,
_chain33Receiver,
_chain33TokenAddress,
_amount
);
}
/*
* @dev: Locks received Ethereum funds.
*
* @param _recipient: bytes representation of destination address.
* @param _token: token address in origin chain (0x0 if ethereum)
* @param _amount: value of deposit
*/
function lock(
bytes memory _recipient,
address _token,
uint256 _amount
)
public
availableNonce()
payable
{
string memory symbol;
// Ethereum deposit
if (msg.value > 0) {
require(
_token == address(0),
"Ethereum deposits require the 'token' address to be the null address"
);
require(
msg.value == _amount,
"The transactions value must be equal the specified amount (in wei)"
);
// Set the the symbol to ETH
symbol = "ETH";
// ERC20 deposit
} else {
require(
BridgeToken(_token).transferFrom(msg.sender, address(this), _amount),
"Contract token allowances insufficient to complete this lock request"
);
// Set symbol to the ERC20 token's symbol
symbol = BridgeToken(_token).symbol();
}
lockFunds(
msg.sender,
_recipient,
_token,
symbol,
_amount
);
}
/*
* @dev: Unlocks Ethereum and ERC20 tokens held on the contract.
*
* @param _recipient: recipient's Ethereum address
* @param _token: token contract address
* @param _symbol: token symbol
* @param _amount: wei amount or ERC20 token count
\ */
function unlock(
address payable _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
public
onlyChain33Bridge
hasLockedFunds(
_token,
_amount
)
canDeliver(
_token,
_amount
)
{
unlockFunds(
_recipient,
_token,
_symbol,
_amount
);
}
/*
* @dev: Exposes an item's current status.
*
* @param _id: The item in question.
* @return: Boolean indicating the lock status.
*/
function getChain33DepositStatus(
bytes32 _id
)
public
view
returns(bool)
{
return isLockedChain33Deposit(_id);
}
/*
* @dev: Allows access to a Chain33 deposit's information via its unique identifier.
*
* @param _id: The deposit to be viewed.
* @return: Original sender's Ethereum address.
* @return: Intended Chain33 recipient's address in bytes.
* @return: The lock deposit's currency, denoted by a token address.
* @return: The amount locked in the deposit.
* @return: The deposit's unique nonce.
*/
function viewChain33Deposit(
bytes32 _id
)
public
view
returns(bytes memory, address payable, address, uint256)
{
return getChain33Deposit(_id);
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Burnable.sol";
import "../../openzeppelin-solidity/contracts/token/ERC20/ERC20Detailed.sol";
/**
* @title BridgeToken
* @dev Mintable, ERC20 compatible BankToken for use by BridgeBank
**/
contract BridgeToken is ERC20Mintable, ERC20Burnable, ERC20Detailed {
constructor(
string memory _symbol
)
public
ERC20Detailed(
_symbol,
_symbol,
8
)
{
// Intentionally left blank
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./BridgeToken.sol";
/**
* @title Chain33Bank
* @dev Manages the deployment and minting of ERC20 compatible BridgeTokens
* which represent assets based on the Chain33 blockchain.
**/
contract Chain33Bank {
using SafeMath for uint256;
uint256 public bridgeTokenCount;
mapping(address => bool) public bridgeTokenWhitelist;
mapping(bytes32 => bool) public bridgeTokenCreated;
mapping(bytes32 => Chain33Deposit) chain33Deposits;
mapping(bytes32 => Chain33Burn) chain33Burns;
mapping(address => DepositBurnCount) depositBurnCounts;
mapping(bytes32 => address) public token2address;
struct Chain33Deposit {
bytes chain33Sender;
address payable ethereumRecipient;
address bridgeTokenAddress;
uint256 amount;
bool exist;
uint256 nonce;
}
struct DepositBurnCount {
uint256 depositCount;
uint256 burnCount;
}
struct Chain33Burn {
bytes chain33Sender;
address payable ethereumOwner;
address bridgeTokenAddress;
uint256 amount;
uint256 nonce;
}
/*
* @dev: Event declarations
*/
event LogNewBridgeToken(
address _token,
string _symbol
);
event LogBridgeTokenMint(
address _token,
string _symbol,
uint256 _amount,
address _beneficiary
);
event LogChain33TokenBurn(
address _token,
string _symbol,
uint256 _amount,
address _ownerFrom,
bytes _chain33Receiver,
uint256 _nonce
);
/*
* @dev: Modifier to make sure this symbol not created now
*/
modifier notCreated(string memory _symbol)
{
require(
!hasBridgeTokenCreated(_symbol),
"The symbol has been created already"
);
_;
}
/*
* @dev: Modifier to make sure this symbol not created now
*/
modifier created(string memory _symbol)
{
require(
hasBridgeTokenCreated(_symbol),
"The symbol has not been created yet"
);
_;
}
/*
* @dev: Constructor, sets bridgeTokenCount
*/
constructor () public {
bridgeTokenCount = 0;
}
/*
* @dev: check whether this symbol has been created yet or not
*
* @param _symbol: token symbol
* @return: true or false
*/
function hasBridgeTokenCreated(string memory _symbol) public view returns(bool) {
bytes32 symHash = keccak256(abi.encodePacked(_symbol));
return bridgeTokenCreated[symHash];
}
/*
* @dev: Creates a new Chain33Deposit with a unique ID
*
* @param _chain33Sender: The sender's Chain33 address in bytes.
* @param _ethereumRecipient: The intended recipient's Ethereum address.
* @param _token: The currency type
* @param _amount: The amount in the deposit.
* @return: The newly created Chain33Deposit's unique id.
*/
function newChain33Deposit(
bytes memory _chain33Sender,
address payable _ethereumRecipient,
address _token,
uint256 _amount
)
internal
returns(bytes32)
{
DepositBurnCount memory depositBurnCount = depositBurnCounts[_token];
depositBurnCount.depositCount = depositBurnCount.depositCount.add(1);
depositBurnCounts[_token] = depositBurnCount;
bytes32 depositID = keccak256(
abi.encodePacked(
_chain33Sender,
_ethereumRecipient,
_token,
_amount,
depositBurnCount.depositCount
)
);
chain33Deposits[depositID] = Chain33Deposit(
_chain33Sender,
_ethereumRecipient,
_token,
_amount,
true,
depositBurnCount.depositCount
);
return depositID;
}
/*
* @dev: Creates a new Chain33Burn with a unique ID
*
* @param _chain33Sender: The sender's Chain33 address in bytes.
* @param _ethereumOwner: The owner's Ethereum address.
* @param _token: The token Address
* @param _amount: The amount to be burned.
* @param _nonce: The nonce indicates the burn count for this token
* @return: The newly created Chain33Burn's unique id.
*/
function newChain33Burn(
bytes memory _chain33Sender,
address payable _ethereumOwner,
address _token,
uint256 _amount,
uint256 nonce
)
internal
returns(bytes32)
{
bytes32 burnID = keccak256(
abi.encodePacked(
_chain33Sender,
_ethereumOwner,
_token,
_amount,
nonce
)
);
chain33Burns[burnID] = Chain33Burn(
_chain33Sender,
_ethereumOwner,
_token,
_amount,
nonce
);
return burnID;
}
/*
* @dev: Deploys a new BridgeToken contract
*
* @param _symbol: The BridgeToken's symbol
*/
function deployNewBridgeToken(
string memory _symbol
)
internal
notCreated(_symbol)
returns(address)
{
bridgeTokenCount = bridgeTokenCount.add(1);
// Deploy new bridge token contract
BridgeToken newBridgeToken = (new BridgeToken)(_symbol);
// Set address in tokens mapping
address newBridgeTokenAddress = address(newBridgeToken);
bridgeTokenWhitelist[newBridgeTokenAddress] = true;
bytes32 symHash = keccak256(abi.encodePacked(_symbol));
bridgeTokenCreated[symHash] = true;
depositBurnCounts[newBridgeTokenAddress] = DepositBurnCount(
uint256(0),
uint256(0));
token2address[symHash] = newBridgeTokenAddress;
emit LogNewBridgeToken(
newBridgeTokenAddress,
_symbol
);
return newBridgeTokenAddress;
}
/*
* @dev: Mints new chain33 tokens
*
* @param _chain33Sender: The sender's Chain33 address in bytes.
* @param _ethereumRecipient: The intended recipient's Ethereum address.
* @param _chain33TokenAddress: The currency type
* @param _symbol: chain33 token symbol
* @param _amount: number of chain33 tokens to be minted
*/
function mintNewBridgeTokens(
bytes memory _chain33Sender,
address payable _intendedRecipient,
address _bridgeTokenAddress,
string memory _symbol,
uint256 _amount
)
internal
{
// Must be whitelisted bridge token
require(
bridgeTokenWhitelist[_bridgeTokenAddress],
"Token must be a whitelisted bridge token"
);
// Mint bridge tokens
require(
BridgeToken(_bridgeTokenAddress).mint(
_intendedRecipient,
_amount
),
"Attempted mint of bridge tokens failed"
);
newChain33Deposit(
_chain33Sender,
_intendedRecipient,
_bridgeTokenAddress,
_amount
);
emit LogBridgeTokenMint(
_bridgeTokenAddress,
_symbol,
_amount,
_intendedRecipient
);
}
/*
* @dev: Burn chain33 tokens
*
* @param _from: The address to be burned from
* @param _chain33Receiver: The receiver's Chain33 address in bytes.
* @param _chain33TokenAddress: The token address of chain33 asset issued on ethereum
* @param _amount: number of chain33 tokens to be minted
*/
function burnChain33Tokens(
address payable _from,
bytes memory _chain33Receiver,
address _chain33TokenAddress,
uint256 _amount
)
internal
{
// Must be whitelisted bridge token
require(
bridgeTokenWhitelist[_chain33TokenAddress],
"Token must be a whitelisted bridge token"
);
// burn bridge tokens
BridgeToken bridgeTokenInstance = BridgeToken(_chain33TokenAddress);
bridgeTokenInstance.burnFrom(_from, _amount);
DepositBurnCount memory depositBurnCount = depositBurnCounts[_chain33TokenAddress];
require(
depositBurnCount.burnCount + 1 > depositBurnCount.burnCount,
"burn nonce is not available"
);
depositBurnCount.burnCount = depositBurnCount.burnCount.add(1);
depositBurnCounts[_chain33TokenAddress] = depositBurnCount;
newChain33Burn(
_chain33Receiver,
_from,
_chain33TokenAddress,
_amount,
depositBurnCount.burnCount
);
emit LogChain33TokenBurn(
_chain33TokenAddress,
bridgeTokenInstance.symbol(),
_amount,
_from,
_chain33Receiver,
depositBurnCount.burnCount
);
}
/*
* @dev: Checks if an individual Chain33Deposit exists.
*
* @param _id: The unique Chain33Deposit's id.
* @return: Boolean indicating if the Chain33Deposit exists in memory.
*/
function isLockedChain33Deposit(
bytes32 _id
)
internal
view
returns(bool)
{
return(chain33Deposits[_id].exist);
}
/*
* @dev: Gets an item's information
*
* @param _Id: The item containing the desired information.
* @return: Sender's address.
* @return: Recipient's address in bytes.
* @return: Token address.
* @return: Amount of ethereum/erc20 in the item.
* @return: Unique nonce of the item.
*/
function getChain33Deposit(
bytes32 _id
)
internal
view
returns(bytes memory, address payable, address, uint256)
{
Chain33Deposit memory deposit = chain33Deposits[_id];
return(
deposit.chain33Sender,
deposit.ethereumRecipient,
deposit.bridgeTokenAddress,
deposit.amount
);
}
function getToken2address(string memory _symbol)
created(_symbol)
public view returns(address)
{
bytes32 symHash = keccak256(abi.encodePacked(_symbol));
return token2address[symHash];
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./BridgeToken.sol";
/*
* @title: EthereumBank
* @dev: Ethereum bank which locks Ethereum/ERC20 token deposits, and unlocks
* Ethereum/ERC20 tokens once the prophecy has been successfully processed.
*/
contract EthereumBank {
using SafeMath for uint256;
uint256 public lockNonce;
mapping(address => uint256) public lockedFunds;
/*
* @dev: Event declarations
*/
event LogLock(
address _from,
bytes _to,
address _token,
string _symbol,
uint256 _value,
uint256 _nonce
);
event LogUnlock(
address _to,
address _token,
string _symbol,
uint256 _value
);
/*
* @dev: Modifier declarations
*/
modifier hasLockedFunds(
address _token,
uint256 _amount
) {
require(
lockedFunds[_token] >= _amount,
"The Bank does not hold enough locked tokens to fulfill this request."
);
_;
}
modifier canDeliver(
address _token,
uint256 _amount
)
{
if(_token == address(0)) {
require(
address(this).balance >= _amount,
'Insufficient ethereum balance for delivery.'
);
} else {
require(
BridgeToken(_token).balanceOf(address(this)) >= _amount,
'Insufficient ERC20 token balance for delivery.'
);
}
_;
}
modifier availableNonce() {
require(
lockNonce + 1 > lockNonce,
'No available nonces.'
);
_;
}
/*
* @dev: Constructor which sets the lock nonce
*/
constructor()
public
{
lockNonce = 0;
}
/*
* @dev: Creates a new Ethereum deposit with a unique id.
*
* @param _sender: The sender's ethereum address.
* @param _recipient: The intended recipient's chain33 address.
* @param _token: The currency type, either erc20 or ethereum.
* @param _amount: The amount of erc20 tokens/ ethereum (in wei) to be itemized.
*/
function lockFunds(
address payable _sender,
bytes memory _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
internal
{
// Incerment the lock nonce
lockNonce = lockNonce.add(1);
// Increment locked funds by the amount of tokens to be locked
lockedFunds[_token] = lockedFunds[_token].add(_amount);
emit LogLock(
_sender,
_recipient,
_token,
_symbol,
_amount,
lockNonce
);
}
/*
* @dev: Unlocks funds held on contract and sends them to the
* intended recipient
*
* @param _recipient: recipient's Ethereum address
* @param _token: token contract address
* @param _symbol: token symbol
* @param _amount: wei amount or ERC20 token count
*/
function unlockFunds(
address payable _recipient,
address _token,
string memory _symbol,
uint256 _amount
)
internal
{
// Decrement locked funds mapping by the amount of tokens to be unlocked
lockedFunds[_token] = lockedFunds[_token].sub(_amount);
// Transfer funds to intended recipient
if (_token == address(0)) {
_recipient.transfer(_amount);
} else {
require(
BridgeToken(_token).transfer(_recipient, _amount),
"Token transfer failed"
);
}
emit LogUnlock(
_recipient,
_token,
_symbol,
_amount
);
}
}
pragma solidity ^0.5.0;
contract BridgeRegistry {
address public chain33Bridge;
address public bridgeBank;
address public oracle;
address public valset;
uint256 public deployHeight;
event LogContractsRegistered(
address _chain33Bridge,
address _bridgeBank,
address _oracle,
address _valset
);
constructor(
address _chain33Bridge,
address _bridgeBank,
address _oracle,
address _valset
)
public
{
chain33Bridge = _chain33Bridge;
bridgeBank = _bridgeBank;
oracle = _oracle;
valset = _valset;
deployHeight = block.number;
emit LogContractsRegistered(
chain33Bridge,
bridgeBank,
oracle,
valset
);
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./Valset.sol";
import "./BridgeBank/BridgeBank.sol";
contract Chain33Bridge {
using SafeMath for uint256;
/*
* @dev: Public variable declarations
*/
address public operator;
Valset public valset;
address public oracle;
bool public hasOracle;
BridgeBank public bridgeBank;
bool public hasBridgeBank;
uint256 public prophecyClaimCount;
mapping(bytes32 => ProphecyClaim) public prophecyClaims;
enum Status {
Null,
Pending,
Success,
Failed
}
enum ClaimType {
Unsupported,
Burn,
Lock
}
struct ProphecyClaim {
ClaimType claimType;
bytes chain33Sender;
address payable ethereumReceiver;
address originalValidator;
address tokenAddress;
string symbol;
uint256 amount;
Status status;
}
/*
* @dev: Event declarations
*/
event LogOracleSet(
address _oracle
);
event LogBridgeBankSet(
address _bridgeBank
);
event LogNewProphecyClaim(
uint256 _prophecyID,
ClaimType _claimType,
bytes _chain33Sender,
address payable _ethereumReceiver,
address _validatorAddress,
address _tokenAddress,
string _symbol,
uint256 _amount
);
event LogProphecyCompleted(
bytes32 _claimID,
ClaimType _claimType
);
/*
* @dev: Modifier which only allows access to currently pending prophecies
*/
modifier isPending(
bytes32 _claimID
)
{
require(
isProphecyClaimActive(_claimID),
"Prophecy claim is not active"
);
_;
}
/*
* @dev: Modifier to restrict access to the operator.
*/
modifier onlyOperator()
{
require(
msg.sender == operator,
'Must be the operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to the oracle.
*/
modifier onlyOracle()
{
require(
msg.sender == oracle,
'Must be the oracle.'
);
_;
}
/*
* @dev: The bridge is not active until oracle and bridge bank are set
*/
modifier isActive()
{
require(
hasOracle == true && hasBridgeBank == true,
"The Operator must set the oracle and bridge bank for bridge activation"
);
_;
}
/*
* @dev: Modifier to make sure the claim type is valid
*/
modifier validClaimType(
ClaimType _claimType
)
{
require(
_claimType == ClaimType.Burn || _claimType == ClaimType.Lock,
"The claim type must be ClaimType.Burn or ClaimType.Lock"
);
_;
}
/*
* @dev: Constructor
*/
constructor(
address _operator,
address _valset
)
public
{
prophecyClaimCount = 0;
operator = _operator;
valset = Valset(_valset);
hasOracle = false;
hasBridgeBank = false;
}
/*
* @dev: setOracle
*/
function setOracle(
address _oracle
)
public
onlyOperator
{
require(
!hasOracle,
"The Oracle cannot be updated once it has been set"
);
hasOracle = true;
oracle = _oracle;
emit LogOracleSet(
oracle
);
}
/*
* @dev: setBridgeBank
*/
function setBridgeBank(
address payable _bridgeBank
)
public
onlyOperator
{
require(
!hasBridgeBank,
"The Bridge Bank cannot be updated once it has been set"
);
hasBridgeBank = true;
bridgeBank = BridgeBank(_bridgeBank);
emit LogBridgeBankSet(
address(bridgeBank)
);
}
/*
* @dev: setNewProphecyClaim
* Sets a new burn or lock prophecy claim, adding it to the prophecyClaims mapping.
* Lock claims can only be created for BridgeTokens on BridgeBank's whitelist. The operator
* is responsible for adding them, and lock claims will fail until the operator has done so.
*/
function setNewProphecyClaim(
bytes32 _claimID,
uint8 _claimType,
bytes memory _chain33Sender,
address payable _ethereumReceiver,
address _originalValidator,
address _tokenAddress,
string memory _symbol,
uint256 _amount
)
public
isActive
onlyOracle
{
// Increment the prophecy claim count
prophecyClaimCount = prophecyClaimCount.add(1);
ClaimType claimType = ClaimType(_claimType);
//overwrite the token address in case of lock
if (claimType == ClaimType.Lock) {
_tokenAddress = bridgeBank.getToken2address(_symbol);
}
// Create the new ProphecyClaim
ProphecyClaim memory prophecyClaim = ProphecyClaim(
claimType,
_chain33Sender,
_ethereumReceiver,
_originalValidator,
_tokenAddress,
_symbol,
_amount,
Status.Pending
);
// Add the new ProphecyClaim to the mapping
prophecyClaims[_claimID] = prophecyClaim;
emit LogNewProphecyClaim(
prophecyClaimCount,
claimType,
_chain33Sender,
_ethereumReceiver,
_originalValidator,
_tokenAddress,
_symbol,
_amount
);
}
/*
* @dev: completeClaim
* Allows for the completion of ProphecyClaims once processed by the Oracle.
* Burn claims unlock tokens stored by BridgeBank.
* Lock claims mint BridgeTokens on BridgeBank's token whitelist.
*/
function completeClaim(
bytes32 _claimID
)
public
isPending(_claimID)
{
require(
msg.sender == oracle,
"Only the Oracle may complete prophecies"
);
prophecyClaims[_claimID].status = Status.Success;
ClaimType claimType = prophecyClaims[_claimID].claimType;
if(claimType == ClaimType.Burn) {
unlockTokens(_claimID);
} else {
issueBridgeTokens(_claimID);
}
emit LogProphecyCompleted(
_claimID,
claimType
);
}
/*
* @dev: issueBridgeTokens
* Issues a request for the BridgeBank to mint new BridgeTokens
*/
function issueBridgeTokens(
bytes32 _claimID
)
internal
{
ProphecyClaim memory prophecyClaim = prophecyClaims[_claimID];
bridgeBank.mintBridgeTokens(
prophecyClaim.chain33Sender,
prophecyClaim.ethereumReceiver,
prophecyClaim.tokenAddress,
prophecyClaim.symbol,
prophecyClaim.amount
);
}
/*
* @dev: unlockTokens
* Issues a request for the BridgeBank to unlock funds held on contract
*/
function unlockTokens(
bytes32 _claimID
)
internal
{
ProphecyClaim memory prophecyClaim = prophecyClaims[_claimID];
bridgeBank.unlock(
prophecyClaim.ethereumReceiver,
prophecyClaim.tokenAddress,
prophecyClaim.symbol,
prophecyClaim.amount
);
}
/*
* @dev: isProphecyClaimActive
* Returns boolean indicating if the ProphecyClaim is active
*/
function isProphecyClaimActive(
bytes32 _claimID
)
public
view
returns(bool)
{
return prophecyClaims[_claimID].status == Status.Pending;
}
/*
* @dev: isProphecyValidatorActive
* Returns boolean indicating if the validator that originally
* submitted the ProphecyClaim is still an active validator
*/
function isProphecyClaimValidatorActive(
bytes32 _claimID
)
public
view
returns(bool)
{
return valset.isActiveValidator(
prophecyClaims[_claimID].originalValidator
);
}
/*
* @dev: Modifier to make sure the claim type is valid
*/
function isValidClaimType(uint8 _claimType) public pure returns(bool)
{
ClaimType claimType = ClaimType(_claimType);
if (claimType == ClaimType.Burn || claimType == ClaimType.Lock) {
return true;
}
return false;
}
}
pragma solidity ^0.5.0;
contract Migrations {
address public owner;
// A function with the signature `last_completed_migration()`, returning a uint, is required.
uint public last_completed_migration;
modifier restricted() {
if (msg.sender == owner) _;
}
constructor() public {
owner = msg.sender;
}
// A function with the signature `setCompleted(uint)` is required.
function setCompleted(uint completed) public restricted {
last_completed_migration = completed;
}
function upgrade(address new_address) public restricted {
Migrations upgraded = Migrations(new_address);
upgraded.setCompleted(last_completed_migration);
}
}
pragma solidity ^0.5.0;
import "../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./Valset.sol";
import "./Chain33Bridge.sol";
contract Oracle {
using SafeMath for uint256;
/*
* @dev: Public variable declarations
*/
Chain33Bridge public chain33Bridge;
Valset public valset;
address public operator;
// Tracks the number of OracleClaims made on an individual BridgeClaim
mapping(bytes32 => address[]) public oracleClaimValidators;
mapping(bytes32 => mapping(address => bool)) public hasMadeClaim;
enum ClaimType {
Unsupported,
Burn,
Lock
}
/*
* @dev: Event declarations
*/
event LogNewOracleClaim(
bytes32 _claimID,
address _validatorAddress,
bytes _signature
);
event LogProphecyProcessed(
bytes32 _claimID,
uint256 _weightedSignedPower,
uint256 _weightedTotalPower,
address _submitter
);
/*
* @dev: Modifier to restrict access to the operator.
*/
modifier onlyOperator()
{
require(
msg.sender == operator,
'Must be the operator.'
);
_;
}
/*
* @dev: Modifier to restrict access to current ValSet validators
*/
modifier onlyValidator()
{
require(
valset.isActiveValidator(msg.sender),
"Must be an active validator"
);
_;
}
/*
* @dev: Modifier to restrict access to current ValSet validators
*/
modifier isPending(
bytes32 _claimID
)
{
require(
chain33Bridge.isProphecyClaimActive(
_claimID
) == true,
"The prophecy must be pending for this operation"
);
_;
}
/*
* @dev: Modifier to restrict the claim type must be burn or lock
*/
modifier isValidClaimType(
ClaimType _claimType
)
{
require(
chain33Bridge.isValidClaimType(
uint8(_claimType)
) == true,
"The claim type must be burn or lock"
);
_;
}
/*
* @dev: Constructor
*/
constructor(
address _operator,
address _valset,
address _chain33Bridge
)
public
{
operator = _operator;
chain33Bridge = Chain33Bridge(_chain33Bridge);
valset = Valset(_valset);
}
/*
* @dev: newOracleClaim
* Allows validators to make new OracleClaims on chain33 lock/burn prophecy,
* if the required vote power reached,just make it processed
* @param _claimType: burn or lock,
* @param _chain33Sender: chain33 sender,
* @param _ethereumReceiver: receiver on ethereum
* @param _tokenAddress: token address
* @param _symbol: token symbol
* @param _amount: amount
* @param _claimID: claim id
* @param _message: message for verifying
* @param _signature: need to recover sender
*/
function newOracleClaim(
ClaimType _claimType,
bytes memory _chain33Sender,
address payable _ethereumReceiver,
address _tokenAddress,
string memory _symbol,
uint256 _amount,
bytes32 _claimID,
bytes memory _signature
)
public
onlyValidator
isValidClaimType(_claimType)
{
address validatorAddress = msg.sender;
// Validate the msg.sender's signature
require(
validatorAddress == valset.recover(
_claimID,
_signature
),
"Invalid _claimID signature."
);
// Confirm that this address has not already made an oracle claim on this _ClaimID
require(
!hasMadeClaim[_claimID][validatorAddress],
"Cannot make duplicate oracle claims from the same address."
);
if (oracleClaimValidators[_claimID].length == 0) {
chain33Bridge.setNewProphecyClaim(
_claimID,
uint8(_claimType),
_chain33Sender,
_ethereumReceiver,
validatorAddress,
_tokenAddress,
_symbol,
_amount);
}
hasMadeClaim[_claimID][validatorAddress] = true;
oracleClaimValidators[_claimID].push(validatorAddress);
emit LogNewOracleClaim(
_claimID,
validatorAddress,
_signature
);
(bool valid, uint256 weightedSignedPower, uint256 weightedTotalPower ) = getClaimThreshold(_claimID);
if (true == valid) {
//if processed already,just emit an event
if (chain33Bridge.isProphecyClaimActive(_claimID) == true) {
completeClaim(_claimID);
}
emit LogProphecyProcessed(
_claimID,
weightedSignedPower,
weightedTotalPower,
msg.sender
);
}
}
/*
* @dev: checkBridgeProphecy
* Operator accessor method which checks if a prophecy has passed
* the validity threshold, without actually completing the prophecy.
*/
function checkBridgeProphecy(
bytes32 _claimID
)
public
view
onlyOperator
isPending(_claimID)
returns(bool, uint256, uint256)
{
require(
chain33Bridge.isProphecyClaimActive(
_claimID
) == true,
"Can only check active prophecies"
);
return getClaimThreshold(
_claimID
);
}
/*
* @dev: getClaimThreshold
* Calculates the status of a claim. The claim is considered valid if the
* combined active signatory validator powers pass the validation threshold.
* The hardcoded threshold is (Combined signed power * 2) >= (Total power * 3).
*/
function getClaimThreshold(
bytes32 _claimID
)
internal
view
returns(bool, uint256, uint256)
{
uint256 signedPower = 0;
uint256 totalPower = valset.totalPower();
// Iterate over the signatory addresses
for (uint256 i = 0; i < oracleClaimValidators[_claimID].length; i = i.add(1)) {
address signer = oracleClaimValidators[_claimID][i];
// Only add the power of active validators
if(valset.isActiveValidator(signer)) {
signedPower = signedPower.add(
valset.getValidatorPower(
signer
)
);
}
}
// Calculate if weighted signed power has reached threshold of weighted total power
uint256 weightedSignedPower = signedPower.mul(3);
uint256 weightedTotalPower = totalPower.mul(2);
bool hasReachedThreshold = weightedSignedPower >= weightedTotalPower;
return(
hasReachedThreshold,
weightedSignedPower,
weightedTotalPower
);
}
/*
* @dev: completeClaim
* Completes a claim by completing the corresponding BridgeClaim
* on the Chain33Bridge.
*/
function completeClaim(
bytes32 _claimID
)
internal
{
chain33Bridge.completeClaim(
_claimID
);
}
}
\ No newline at end of file
pragma solidity ^0.5.0;
import "../openzeppelin-solidity/contracts/math/SafeMath.sol";
import "../openzeppelin-solidity/contracts/cryptography/ECDSA.sol";
contract Valset {
using SafeMath for uint256;
using ECDSA for bytes32;
/*
* @dev: Variable declarations
*/
address public operator;
uint256 public totalPower;
uint256 public currentValsetVersion;
uint256 public validatorCount;
mapping (bytes32 => bool) public validators;
mapping(bytes32 => uint256) public powers;
/*
* @dev: Event declarations
*/
event LogValidatorAdded(
address _validator,
uint256 _power,
uint256 _currentValsetVersion,
uint256 _validatorCount,
uint256 _totalPower
);
event LogValidatorPowerUpdated(
address _validator,
uint256 _power,
uint256 _currentValsetVersion,
uint256 _validatorCount,
uint256 _totalPower
);
event LogValidatorRemoved(
address _validator,
uint256 _power,
uint256 _currentValsetVersion,
uint256 _validatorCount,
uint256 _totalPower
);
event LogValsetReset(
uint256 _newValsetVersion,
uint256 _validatorCount,
uint256 _totalPower
);
event LogValsetUpdated(
uint256 _newValsetVersion,
uint256 _validatorCount,
uint256 _totalPower
);
/*
* @dev: Modifier which restricts access to the operator.
*/
modifier onlyOperator()
{
require(
msg.sender == operator,
'Must be the operator.'
);
_;
}
/*
* @dev: Constructor
*/
constructor(
address _operator,
address[] memory _initValidators,
uint256[] memory _initPowers
)
public
{
operator = _operator;
currentValsetVersion = 0;
updateValset(
_initValidators,
_initPowers
);
}
function recover(
bytes32 _message,
bytes memory _signature
)
public
pure
returns (address)
{
bytes32 message = ethMessageHash(_message);
return verify(message, _signature);
}
/*
* @dev: addValidator
*/
function addValidator(
address _validatorAddress,
uint256 _validatorPower
)
public
onlyOperator
{
addValidatorInternal(
_validatorAddress,
_validatorPower
);
}
/*
* @dev: updateValidatorPower
*/
function updateValidatorPower(
address _validatorAddress,
uint256 _newValidatorPower
)
public
onlyOperator
{
// Create a unique key which for this validator's position in the current version of the mapping
bytes32 key = keccak256(
abi.encodePacked(
currentValsetVersion,
_validatorAddress
)
);
require(
validators[key],
"Can only update the power of active valdiators"
);
// Adjust total power by new validator power
uint256 priorPower = powers[key];
totalPower = totalPower.sub(priorPower);
totalPower = totalPower.add(_newValidatorPower);
// Set validator's new power
powers[key] = _newValidatorPower;
emit LogValidatorPowerUpdated(
_validatorAddress,
_newValidatorPower,
currentValsetVersion,
validatorCount,
totalPower
);
}
/*
* @dev: removeValidator
*/
function removeValidator(
address _validatorAddress
)
public
onlyOperator
{
// Create a unique key which for this validator's position in the current version of the mapping
bytes32 key = keccak256(
abi.encodePacked(
currentValsetVersion,
_validatorAddress
)
);
require(
validators[key],
"Can only remove active valdiators"
);
// Update validator count and total power
validatorCount = validatorCount.sub(1);
totalPower = totalPower.sub(powers[key]);
// Delete validator and power
delete validators[key];
delete powers[key];
emit LogValidatorRemoved(
_validatorAddress,
0,
currentValsetVersion,
validatorCount,
totalPower
);
}
/*
* @dev: updateValset
*/
function updateValset(
address[] memory _validators,
uint256[] memory _powers
)
public
onlyOperator
{
require(
_validators.length == _powers.length,
"Every validator must have a corresponding power"
);
resetValset();
for(uint256 i = 0; i < _validators.length; i = i.add(1)) {
addValidatorInternal(_validators[i], _powers[i]);
}
emit LogValsetUpdated(
currentValsetVersion,
validatorCount,
totalPower
);
}
/*
* @dev: isActiveValidator
*/
function isActiveValidator(
address _validatorAddress
)
public
view
returns(bool)
{
// Recreate the unique key for this address given the current mapping version
bytes32 key = keccak256(
abi.encodePacked(
currentValsetVersion,
_validatorAddress
)
);
// Return bool indicating if this address is an active validator
return validators[key];
}
/*
* @dev: getValidatorPower
*/
function getValidatorPower(
address _validatorAddress
)
external
view
returns(uint256)
{
// Recreate the unique key for this address given the current mapping version
bytes32 key = keccak256(
abi.encodePacked(
currentValsetVersion,
_validatorAddress
)
);
return powers[key];
}
/*
* @dev: recoverGas
*/
function recoverGas(
uint256 _valsetVersion,
address _validatorAddress
)
external
onlyOperator
{
require(
_valsetVersion < currentValsetVersion,
"Gas recovery only allowed for previous validator sets"
);
// Recreate the unique key used to identify this validator in the given version
bytes32 key = keccak256(
abi.encodePacked(
_valsetVersion,
_validatorAddress
)
);
// Delete from mappings and recover gas
delete(validators[key]);
delete(powers[key]);
}
/*
* @dev: addValidatorInternal
*/
function addValidatorInternal(
address _validatorAddress,
uint256 _validatorPower
)
internal
{
// Create a unique key which for this validator's position in the current version of the mapping
bytes32 key = keccak256(
abi.encodePacked(
currentValsetVersion,
_validatorAddress
)
);
validatorCount = validatorCount.add(1);
totalPower = totalPower.add(_validatorPower);
// Set validator as active and set their power
validators[key] = true;
powers[key] = _validatorPower;
emit LogValidatorAdded(
_validatorAddress,
_validatorPower,
currentValsetVersion,
validatorCount,
totalPower
);
}
/*
* @dev: resetValset
*/
function resetValset()
internal
{
currentValsetVersion = currentValsetVersion.add(1);
validatorCount = 0;
totalPower = 0;
emit LogValsetReset(
currentValsetVersion,
validatorCount,
totalPower
);
}
/*
* @dev: Verify
*
*/
function verify(
bytes32 h,
bytes memory signature
)
internal
pure
returns (address)
{
bytes32 r;
bytes32 s;
uint8 v;
// Check the signature length
if (signature.length != 65) {
return (address(0));
}
// Divide the signature in r, s and v variables
// ecrecover takes the signature parameters, and the only way to get them
// currently is to use assembly.
// solium-disable-next-line security/no-inline-assembly
assembly {
r := mload(add(signature, 32))
s := mload(add(signature, 64))
v := byte(0, mload(add(signature, 96)))
}
// Version of signature should be 27 or 28, but 0 and 1 are also possible versions
if (v < 27) {
v += 27;
}
// If the version is correct return the signer address
if (v != 27 && v != 28) {
return (address(0));
} else {
// solium-disable-next-line arg-overflow
return ecrecover(h, v, r, s);
}
}
/**
* @dev prefix a bytes32 value with "\x19Ethereum Signed Message:" and hash the result
*/
function ethMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
/**
* @dev debug for pack
*/
function Debug_Packed(bytes32 hash) public pure returns (bytes memory) {
bytes memory info;
info = abi.encodePacked("\x19Ethereum Signed Message:\n32", hash);
return info;
}
/**
* @dev debug for hash
*/
function Debug_ethMessageHash(bytes32 hash) public pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
}
\ No newline at end of file
package test
import (
"encoding/hex"
"fmt"
"math/big"
"strings"
"testing"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)
func TestUnpackEvent(t *testing.T) {
const abiJSON = `[{"constant":false,"inputs":[{"name":"memo","type":"bytes"}],"name":"receive","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"memo","type":"bytes"}],"name":"received","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"}],"name":"receivedAddr","type":"event"}]`
abi, err := abi.JSON(strings.NewReader(abiJSON))
if err != nil {
t.Fatal(err)
}
const hexdata = `000000000000000000000000376c47978271565f56deb45495afa69e59c16ab200000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000158`
data, err := hex.DecodeString(hexdata)
if err != nil {
t.Fatal(err)
}
if len(data)%32 == 0 {
t.Errorf("len(data) is %d, want a non-multiple of 32", len(data))
}
type ReceivedEvent struct {
Sender common.Address
Amount *big.Int
Memo []byte
}
var ev ReceivedEvent
err = abi.Unpack(&ev, "received", data)
if err != nil {
t.Error(err)
}
fmt.Printf("\nReceivedEvent sender:%s", ev.Sender.String())
type ReceivedAddrEvent struct {
Sender common.Address
}
var receivedAddrEv ReceivedAddrEvent
err = abi.Unpack(&receivedAddrEv, "receivedAddr", data)
if err != nil {
t.Error(err)
}
fmt.Printf("\nreceivedAddrEv=%s\n\n\n", receivedAddrEv.Sender.String())
}
package test
import (
"context"
"fmt"
"math/big"
"testing"
"time"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/test/setup"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethtxs"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/require"
)
//"BridgeToken creation (Chain33 assets)"
func TestBrigeTokenCreat(t *testing.T) {
ctx := context.Background()
println("TEST:BridgeToken creation (Chain33 assets)")
//1st部署相关合约
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
//2nd:订阅事件
eventName := "LogNewBridgeToken"
bridgeBankABI := ethtxs.LoadABI(ethtxs.BridgeBankABI)
logNewBridgeTokenSig := bridgeBankABI.Events[eventName].ID().Hex()
query := ethereum.FilterQuery{
Addresses: []common.Address{x2EthDeployInfo.BridgeBank.Address},
}
// We will check logs for new events
logs := make(chan types.Log)
// Filter by contract and event, write results to logs
sub, err := sim.SubscribeFilterLogs(ctx, query, logs)
require.Nil(t, err)
t.Logf("x2EthDeployInfo.BridgeBank.Address is:%s", x2EthDeployInfo.BridgeBank.Address.String())
bridgeBank, err := generated.NewBridgeBank(x2EthDeployInfo.BridgeBank.Address, sim)
require.Nil(t, err)
opts := &bind.CallOpts{
Pending: true,
From: para.Operator,
Context: ctx,
}
BridgeBankAddr, err := x2EthContracts.BridgeRegistry.BridgeBank(opts)
require.Nil(t, err)
t.Logf("BridgeBankAddr is:%s", BridgeBankAddr.String())
tokenCount, err := bridgeBank.BridgeBankCaller.BridgeTokenCount(opts)
require.Nil(t, err)
require.Equal(t, tokenCount.Int64(), int64(0))
//3rd:创建token
auth, err := ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
if nil != err {
t.Fatalf("PrepareAuth failed due to:%s", err.Error())
}
symbol := "BTY"
_, err = x2EthContracts.BridgeBank.BridgeBankTransactor.CreateNewBridgeToken(auth, symbol)
if nil != err {
t.Fatalf("CreateNewBridgeToken failed due to:%s", err.Error())
}
sim.Commit()
timer := time.NewTimer(30 * time.Second)
for {
select {
case <-timer.C:
t.Fatal("failed due to timeout")
// Handle any errors
case err := <-sub.Err():
t.Fatalf("sub error:%s", err.Error())
// vLog is raw event data
case vLog := <-logs:
// Check if the event is a 'LogLock' event
if vLog.Topics[0].Hex() == logNewBridgeTokenSig {
t.Logf("Witnessed new event:%s, Block number:%d, Tx hash:%s", eventName,
vLog.BlockNumber, vLog.TxHash.Hex())
logEvent := &events.LogNewBridgeToken{}
err = bridgeBankABI.Unpack(logEvent, eventName, vLog.Data)
require.Nil(t, err)
t.Logf("token addr:%s, symbol:%s", logEvent.Token.String(), logEvent.Symbol)
require.Equal(t, symbol, logEvent.Symbol)
//tokenCount正确加1
tokenCount, err := x2EthContracts.BridgeBank.BridgeTokenCount(opts)
require.Nil(t, err)
require.Equal(t, tokenCount.Int64(), int64(1))
return
}
}
}
}
//测试在chain33上锁定资产,然后在以太坊上铸币
//发行token="BTY"
//铸币NewOracleClaim
//铸币成功
//Bridge token minting (for locked chain33 assets)
func TestBrigeTokenMint(t *testing.T) {
ctx := context.Background()
println("TEST:BridgeToken creation (Chain33 assets)")
//1st部署相关合约
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
//2nd:订阅事件
eventName := "LogNewBridgeToken"
bridgeBankABI := ethtxs.LoadABI(ethtxs.BridgeBankABI)
logNewBridgeTokenSig := bridgeBankABI.Events[eventName].ID().Hex()
query := ethereum.FilterQuery{
Addresses: []common.Address{x2EthDeployInfo.BridgeBank.Address},
}
// We will check logs for new events
logs := make(chan types.Log)
// Filter by contract and event, write results to logs
sub, err := sim.SubscribeFilterLogs(ctx, query, logs)
require.Nil(t, err)
opts := &bind.CallOpts{
Pending: true,
From: para.Operator,
Context: ctx,
}
tokenCount, err := x2EthContracts.BridgeBank.BridgeTokenCount(opts)
require.Nil(t, err)
require.Equal(t, tokenCount.Int64(), int64(0))
//3rd:创建token
symbol := "BTY"
auth, err := ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
if nil != err {
t.Fatalf("PrepareAuth failed due to:%s", err.Error())
}
_, err = x2EthContracts.BridgeBank.BridgeBankTransactor.CreateNewBridgeToken(auth, symbol)
if nil != err {
t.Fatalf("CreateNewBridgeToken failed due to:%s", err.Error())
}
sim.Commit()
logEvent := &events.LogNewBridgeToken{}
select {
// Handle any errors
case err := <-sub.Err():
t.Fatalf("sub error:%s", err.Error())
// vLog is raw event data
case vLog := <-logs:
// Check if the event is a 'LogLock' event
if vLog.Topics[0].Hex() == logNewBridgeTokenSig {
t.Logf("Witnessed new event:%s, Block number:%d, Tx hash:%s", eventName,
vLog.BlockNumber, vLog.TxHash.Hex())
err = bridgeBankABI.Unpack(logEvent, eventName, vLog.Data)
require.Nil(t, err)
t.Logf("token addr:%s, symbol:%s", logEvent.Token.String(), logEvent.Symbol)
require.Equal(t, symbol, logEvent.Symbol)
//tokenCount正确加1
tokenCount, err = x2EthContracts.BridgeBank.BridgeTokenCount(opts)
require.Nil(t, err)
require.Equal(t, tokenCount.Int64(), int64(1))
break
}
}
///////////newOracleClaim///////////////////////////
balance, _ := sim.BalanceAt(ctx, para.InitValidators[0], nil)
fmt.Println("InitValidators[0] addr,", para.InitValidators[0].String(), "balance =", balance.String())
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
amount := int64(99)
ethReceiver := para.InitValidators[2]
claimID := crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), logEvent.Token.Bytes(), big.NewInt(amount).Bytes())
authOracle, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err := ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
bridgeToken, err := generated.NewBridgeToken(logEvent.Token, sim)
require.Nil(t, err)
opts = &bind.CallOpts{
Pending: true,
Context: ctx,
}
balance, err = bridgeToken.BalanceOf(opts, ethReceiver)
require.Nil(t, err)
require.Equal(t, balance.Int64(), int64(0))
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeLock,
chain33Sender,
ethReceiver,
logEvent.Token,
logEvent.Symbol,
big.NewInt(amount),
claimID,
signature)
require.Nil(t, err)
sim.Commit()
balance, err = bridgeToken.BalanceOf(opts, ethReceiver)
require.Nil(t, err)
require.Equal(t, balance.Int64(), amount)
t.Logf("The minted amount is:%d", balance.Int64())
}
//测试在以太坊上lock数字资产,包括Eth和Erc20
//Bridge deposit locking (deposit erc20/eth assets)
func TestBridgeDepositLock(t *testing.T) {
ctx := context.Background()
println("TEST:Bridge deposit locking (Erc20/Eth assets)")
//1st部署相关合约
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
//创建token
operatorAuth, err := ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
symbol := "USDT"
bridgeTokenAddr, _, bridgeTokenInstance, err := generated.DeployBridgeToken(operatorAuth, sim, symbol)
require.Nil(t, err)
sim.Commit()
t.Logf("The new creaded symbol:%s, address:%s", symbol, bridgeTokenAddr.String())
//创建实例 为userOne铸币 userOne为bridgebank允许allowance设置数额
userOne := para.InitValidators[0]
callopts := &bind.CallOpts{
Pending: true,
From: userOne,
Context: ctx,
}
symQuery, err := bridgeTokenInstance.Symbol(callopts)
require.Equal(t, symQuery, symbol)
t.Logf("symQuery = %s", symQuery)
isMiner, err := bridgeTokenInstance.IsMinter(callopts, para.Operator)
require.Nil(t, err)
require.Equal(t, isMiner, true)
operatorAuth, err = ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
require.Nil(t, err)
mintAmount := int64(1000)
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
_, err = bridgeTokenInstance.Mint(operatorAuth, userOne, big.NewInt(mintAmount))
require.Nil(t, err)
sim.Commit()
userOneAuth, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
allowAmount := int64(100)
_, err = bridgeTokenInstance.Approve(userOneAuth, x2EthDeployInfo.BridgeBank.Address, big.NewInt(allowAmount))
require.Nil(t, err)
sim.Commit()
userOneBalance, err := bridgeTokenInstance.BalanceOf(callopts, userOne)
require.Nil(t, err)
t.Logf("userOneBalance:%d", userOneBalance.Int64())
require.Equal(t, userOneBalance.Int64(), mintAmount)
// 测试子项目:should allow users to lock ERC20 tokens
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
//lock 100
lockAmount := big.NewInt(100)
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, bridgeTokenAddr, lockAmount)
require.Nil(t, err)
sim.Commit()
//balance减少到900
userOneBalance, err = bridgeTokenInstance.BalanceOf(callopts, userOne)
require.Nil(t, err)
expectAmount := int64(900)
require.Equal(t, userOneBalance.Int64(), expectAmount)
t.Logf("userOneBalance changes to:%d", userOneBalance.Int64())
//bridgebank增加了100
bridgeBankBalance, err := bridgeTokenInstance.BalanceOf(callopts, x2EthDeployInfo.BridgeBank.Address)
require.Nil(t, err)
expectAmount = int64(100)
require.Equal(t, bridgeBankBalance.Int64(), expectAmount)
t.Logf("bridgeBankBalance changes to:%d", bridgeBankBalance.Int64())
// 测试子项目:锁定ETH,should allow users to lock Ethereum
bridgeBankBalance, err = sim.BalanceAt(ctx, x2EthDeployInfo.BridgeBank.Address, nil)
require.Nil(t, err)
t.Logf("origin eth bridgeBankBalance is:%d", bridgeBankBalance.Int64())
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
ethAmount := big.NewInt(50)
userOneAuth.Value = ethAmount
//lock 50 eth
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, common.Address{}, ethAmount)
require.Nil(t, err)
sim.Commit()
bridgeBankBalance, err = sim.BalanceAt(ctx, x2EthDeployInfo.BridgeBank.Address, nil)
require.Nil(t, err)
require.Equal(t, bridgeBankBalance.Int64(), ethAmount.Int64())
t.Logf("eth bridgeBankBalance changes to:%d", bridgeBankBalance.Int64())
}
//测试在以太坊上unlock数字资产,包括Eth和Erc20,
//即从chain33取回在eth上发行的的ETH或ERC20数字资产,之前通过lock操作发送到了chain33
//现在则通过NewProphecyClaim 的burn操作将数字资产取回
//Ethereum/ERC20 token unlocking (for burned chain33 assets)
func TestBridgeBankUnlock(t *testing.T) {
ctx := context.Background()
println("TEST:Ethereum/ERC20 token unlocking (for burned chain33 assets)")
//1st部署相关合约
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
//1.lockEth资产
ethAddr := common.Address{}
userOneAuth, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
ethLockAmount := big.NewInt(150)
userOneAuth.Value = ethLockAmount
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
//lock 150 eth
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, common.Address{}, ethLockAmount)
require.Nil(t, err)
sim.Commit()
//2.lockErc20资产
//创建token
operatorAuth, err := ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
symbolUsdt := "USDT"
bridgeTokenAddr, _, bridgeTokenInstance, err := generated.DeployBridgeToken(operatorAuth, sim, symbolUsdt)
require.Nil(t, err)
sim.Commit()
t.Logf("The new creaded symbolUsdt:%s, address:%s", symbolUsdt, bridgeTokenAddr.String())
//创建实例
//为userOne铸币
//userOne为bridgebank允许allowance设置数额
userOne := para.InitValidators[0]
callopts := &bind.CallOpts{
Pending: true,
From: userOne,
Context: ctx,
}
symQuery, err := bridgeTokenInstance.Symbol(callopts)
require.Equal(t, symQuery, symbolUsdt)
t.Logf("symQuery = %s", symQuery)
isMiner, err := bridgeTokenInstance.IsMinter(callopts, para.Operator)
require.Nil(t, err)
require.Equal(t, isMiner, true)
operatorAuth, err = ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
mintAmount := int64(1000)
_, err = bridgeTokenInstance.Mint(operatorAuth, userOne, big.NewInt(mintAmount))
require.Nil(t, err)
sim.Commit()
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
allowAmount := int64(100)
_, err = bridgeTokenInstance.Approve(userOneAuth, x2EthDeployInfo.BridgeBank.Address, big.NewInt(allowAmount))
require.Nil(t, err)
sim.Commit()
userOneBalance, err := bridgeTokenInstance.BalanceOf(callopts, userOne)
require.Nil(t, err)
t.Logf("userOneBalance:%d", userOneBalance.Int64())
require.Equal(t, userOneBalance.Int64(), mintAmount)
//***测试子项目:should allow users to lock ERC20 tokens
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
//lock 100
lockAmount := big.NewInt(100)
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, bridgeTokenAddr, lockAmount)
require.Nil(t, err)
sim.Commit()
// newOracleClaim
newProphecyAmount := int64(55)
ethReceiver := para.InitValidators[2]
ethSym := "eth"
claimID := crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), ethAddr.Bytes(), big.NewInt(newProphecyAmount).Bytes())
authOracle, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err := ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeBurn,
chain33Sender,
ethReceiver,
ethAddr,
ethSym,
big.NewInt(newProphecyAmount),
claimID,
signature)
require.Nil(t, err)
userEthbalance, _ := sim.BalanceAt(ctx, ethReceiver, nil)
t.Logf("userEthbalance for addr:%s balance=%d", ethReceiver.String(), userEthbalance.Int64())
sim.Commit()
userEthbalanceAfter, _ := sim.BalanceAt(ctx, ethReceiver, nil)
t.Logf("userEthbalance after ProcessBridgeProphecy for addr:%s balance=%d", ethReceiver.String(), userEthbalanceAfter.Int64())
require.Equal(t, userEthbalance.Int64()+newProphecyAmount, userEthbalanceAfter.Int64())
//////////////////////////////////////////////////////////////////
///////should unlock and transfer ERC20 tokens upon the processing of a burn prophecy//////
//////////////////////////////////////////////////////////////////
// newOracleClaim
newProphecyAmount = int64(100)
ethReceiver = para.InitValidators[2]
claimID = crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), bridgeTokenAddr.Bytes(), big.NewInt(newProphecyAmount).Bytes())
authOracle, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err = ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeBurn,
chain33Sender,
ethReceiver,
bridgeTokenAddr,
symbolUsdt,
big.NewInt(newProphecyAmount),
claimID,
signature)
require.Nil(t, err)
userUSDTbalance, err := bridgeTokenInstance.BalanceOf(callopts, ethReceiver)
require.Nil(t, err)
t.Logf("userEthbalance for addr:%s balance=%d", ethReceiver.String(), userUSDTbalance.Int64())
require.Equal(t, userUSDTbalance.Int64(), newProphecyAmount)
}
//测试在以太坊上多次unlock数字资产Eth
//Ethereum/ERC20 token second unlocking (for burned chain33 assets)
func TestBridgeBankSecondUnlockEth(t *testing.T) {
ctx := context.Background()
println("TEST:to be unlocked incrementally by successive burn prophecies (for burned chain33 assets)")
//1st部署相关合约
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
//1.lockEth资产
ethAddr := common.Address{}
userOneAuth, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
ethLockAmount := big.NewInt(150)
userOneAuth.Value = ethLockAmount
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
//lock 150 eth
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, common.Address{}, ethLockAmount)
require.Nil(t, err)
sim.Commit()
//2.lockErc20资产
//创建token
operatorAuth, err := ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
symbolUsdt := "USDT"
bridgeTokenAddr, _, bridgeTokenInstance, err := generated.DeployBridgeToken(operatorAuth, sim, symbolUsdt)
require.Nil(t, err)
sim.Commit()
t.Logf("The new creaded symbolUsdt:%s, address:%s", symbolUsdt, bridgeTokenAddr.String())
//创建实例
//为userOne铸币
//userOne为bridgebank允许allowance设置数额
userOne := para.InitValidators[0]
callopts := &bind.CallOpts{
Pending: true,
From: userOne,
Context: ctx,
}
symQuery, err := bridgeTokenInstance.Symbol(callopts)
require.Equal(t, symQuery, symbolUsdt)
t.Logf("symQuery = %s", symQuery)
isMiner, err := bridgeTokenInstance.IsMinter(callopts, para.Operator)
require.Nil(t, err)
require.Equal(t, isMiner, true)
operatorAuth, err = ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
require.Nil(t, err)
mintAmount := int64(1000)
_, err = bridgeTokenInstance.Mint(operatorAuth, userOne, big.NewInt(mintAmount))
require.Nil(t, err)
sim.Commit()
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
allowAmount := int64(100)
_, err = bridgeTokenInstance.Approve(userOneAuth, x2EthDeployInfo.BridgeBank.Address, big.NewInt(allowAmount))
require.Nil(t, err)
sim.Commit()
userOneBalance, err := bridgeTokenInstance.BalanceOf(callopts, userOne)
require.Nil(t, err)
t.Logf("userOneBalance:%d", userOneBalance.Int64())
require.Equal(t, userOneBalance.Int64(), mintAmount)
//***测试子项目:should allow users to lock ERC20 tokens
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
//lock 100
lockAmount := big.NewInt(100)
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, bridgeTokenAddr, lockAmount)
require.Nil(t, err)
sim.Commit()
// newOracleClaim
newProphecyAmount := int64(44)
ethReceiver := para.InitValidators[2]
ethSym := "eth"
claimID := crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), ethAddr.Bytes(), big.NewInt(newProphecyAmount).Bytes())
authOracle, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err := ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeBurn,
chain33Sender,
ethReceiver,
ethAddr,
ethSym,
big.NewInt(newProphecyAmount),
claimID,
signature)
require.Nil(t, err)
userEthbalance, _ := sim.BalanceAt(ctx, ethReceiver, nil)
t.Logf("userEthbalance for addr:%s balance=%d", ethReceiver.String(), userEthbalance.Int64())
sim.Commit()
userEthbalanceAfter, _ := sim.BalanceAt(ctx, ethReceiver, nil)
t.Logf("userEthbalance after ProcessBridgeProphecy for addr:%s balance=%d", ethReceiver.String(), userEthbalanceAfter.Int64())
require.Equal(t, userEthbalance.Int64()+newProphecyAmount, userEthbalanceAfter.Int64())
//第二次 newOracleClaim
newProphecyAmountSecond := int64(33)
claimID = crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), ethAddr.Bytes(), big.NewInt(newProphecyAmountSecond).Bytes())
authOracle, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err = ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeBurn,
chain33Sender,
ethReceiver,
ethAddr,
ethSym,
big.NewInt(newProphecyAmountSecond),
claimID,
signature)
require.Nil(t, err)
userEthbalance, _ = sim.BalanceAt(ctx, ethReceiver, nil)
t.Logf("userEthbalance for addr:%s balance=%d", ethReceiver.String(), userEthbalance.Int64())
sim.Commit()
userEthbalanceAfter, _ = sim.BalanceAt(ctx, ethReceiver, nil)
t.Logf("userEthbalance after ProcessBridgeProphecy for addr:%s balance=%d", ethReceiver.String(), userEthbalanceAfter.Int64())
require.Equal(t, userEthbalance.Int64()+newProphecyAmountSecond, userEthbalanceAfter.Int64())
}
//测试在以太坊上多次unlock数字资产Erc20
//Ethereum/ERC20 token unlocking (for burned chain33 assets)
func TestBridgeBankSedondUnlockErc20(t *testing.T) {
ctx := context.Background()
println("TEST:ERC20 to be unlocked incrementally by successive burn prophecies (for burned chain33 assets))")
//1st部署相关合约
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
//1.lockEth资产
userOneAuth, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
ethLockAmount := big.NewInt(150)
userOneAuth.Value = ethLockAmount
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
//lock 150 eth
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, common.Address{}, ethLockAmount)
require.Nil(t, err)
sim.Commit()
//2.lockErc20资产
//创建token
operatorAuth, err := ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
symbolUsdt := "USDT"
bridgeTokenAddr, _, bridgeTokenInstance, err := generated.DeployBridgeToken(operatorAuth, sim, symbolUsdt)
require.Nil(t, err)
sim.Commit()
t.Logf("The new creaded symbolUsdt:%s, address:%s", symbolUsdt, bridgeTokenAddr.String())
//创建实例 为userOne铸币 userOne为bridgebank允许allowance设置数额
userOne := para.InitValidators[0]
callopts := &bind.CallOpts{
Pending: true,
From: userOne,
Context: ctx,
}
symQuery, err := bridgeTokenInstance.Symbol(callopts)
require.Equal(t, symQuery, symbolUsdt)
t.Logf("symQuery = %s", symQuery)
isMiner, err := bridgeTokenInstance.IsMinter(callopts, para.Operator)
require.Nil(t, err)
require.Equal(t, isMiner, true)
operatorAuth, err = ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
require.Nil(t, err)
mintAmount := int64(1000)
_, err = bridgeTokenInstance.Mint(operatorAuth, userOne, big.NewInt(mintAmount))
require.Nil(t, err)
sim.Commit()
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
allowAmount := int64(100)
_, err = bridgeTokenInstance.Approve(userOneAuth, x2EthDeployInfo.BridgeBank.Address, big.NewInt(allowAmount))
require.Nil(t, err)
sim.Commit()
userOneBalance, err := bridgeTokenInstance.BalanceOf(callopts, userOne)
require.Nil(t, err)
t.Logf("userOneBalance:%d", userOneBalance.Int64())
require.Equal(t, userOneBalance.Int64(), mintAmount)
//测试子项目:should allow users to lock ERC20 tokens
userOneAuth, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
//lock 100
lockAmount := big.NewInt(100)
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, bridgeTokenAddr, lockAmount)
require.Nil(t, err)
sim.Commit()
// newOracleClaim
newProphecyAmount := int64(33)
ethReceiver := para.InitValidators[2]
claimID := crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), bridgeTokenAddr.Bytes(), big.NewInt(newProphecyAmount).Bytes())
userUSDTbalance0, err := bridgeTokenInstance.BalanceOf(callopts, ethReceiver)
require.Nil(t, err)
t.Logf("userEthbalance for addr:%s balance=%d", ethReceiver.String(), userUSDTbalance0.Int64())
require.Equal(t, userUSDTbalance0.Int64(), int64(0))
///////////newOracleClaim///////////////////////////
authOracle, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err := ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeBurn,
chain33Sender,
ethReceiver,
bridgeTokenAddr,
symbolUsdt,
big.NewInt(newProphecyAmount),
claimID,
signature)
require.Nil(t, err)
userUSDTbalance1, err := bridgeTokenInstance.BalanceOf(callopts, ethReceiver)
require.Nil(t, err)
t.Logf("userEthbalance for addr:%s balance=%d", ethReceiver.String(), userUSDTbalance1.Int64())
require.Equal(t, userUSDTbalance1.Int64(), userUSDTbalance0.Int64()+newProphecyAmount)
// newOracleClaim
newProphecyAmountSecond := int64(66)
claimID = crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), bridgeTokenAddr.Bytes(), big.NewInt(newProphecyAmountSecond).Bytes())
authOracle, err = ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err = ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeBurn,
chain33Sender,
ethReceiver,
bridgeTokenAddr,
symbolUsdt,
big.NewInt(newProphecyAmountSecond),
claimID,
signature)
require.Nil(t, err)
userUSDTbalance2, err := bridgeTokenInstance.BalanceOf(callopts, ethReceiver)
require.Nil(t, err)
t.Logf("userEthbalance for addr:%s balance=%d", ethReceiver.String(), userUSDTbalance2.Int64())
require.Equal(t, userUSDTbalance2.Int64(), userUSDTbalance1.Int64()+newProphecyAmountSecond)
}
package setup
import (
"context"
"crypto/ecdsa"
"math/big"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethtxs"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
func PrepareTestEnv() (*ethinterface.SimExtend, *ethtxs.DeployPara) {
genesiskey, _ := crypto.GenerateKey()
alloc := make(core.GenesisAlloc)
genesisAddr := crypto.PubkeyToAddress(genesiskey.PublicKey)
genesisAccount := core.GenesisAccount{
Balance: big.NewInt(10000000000 * 10000),
PrivateKey: crypto.FromECDSA(genesiskey),
}
alloc[genesisAddr] = genesisAccount
var InitValidators []common.Address
var ValidatorPriKey []*ecdsa.PrivateKey
for i := 0; i < 4; i++ {
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
InitValidators = append(InitValidators, addr)
ValidatorPriKey = append(ValidatorPriKey, key)
account := core.GenesisAccount{
Balance: big.NewInt(100000000 * 100),
PrivateKey: crypto.FromECDSA(key),
}
alloc[addr] = account
}
gasLimit := uint64(100000000)
sim := new(ethinterface.SimExtend)
sim.SimulatedBackend = backends.NewSimulatedBackend(alloc, gasLimit)
InitPowers := []*big.Int{big.NewInt(80), big.NewInt(10), big.NewInt(10), big.NewInt(10)}
para := &ethtxs.DeployPara{
DeployPrivateKey: genesiskey,
Deployer: genesisAddr,
Operator: genesisAddr,
InitValidators: InitValidators,
ValidatorPriKey: ValidatorPriKey,
InitPowers: InitPowers,
}
return sim, para
}
func PrepareTestEnvironment(deployerPrivateKey string, ethValidatorAddrKeys []string) (bind.ContractBackend, *ethtxs.DeployPara) {
genesiskey, _ := crypto.HexToECDSA(deployerPrivateKey)
alloc := make(core.GenesisAlloc)
genesisAddr := crypto.PubkeyToAddress(genesiskey.PublicKey)
genesisAccount := core.GenesisAccount{
Balance: big.NewInt(10000000000 * 10000),
PrivateKey: crypto.FromECDSA(genesiskey),
}
alloc[genesisAddr] = genesisAccount
var InitValidators []common.Address
var ValidatorPriKey []*ecdsa.PrivateKey
for _, v := range ethValidatorAddrKeys {
key, _ := crypto.HexToECDSA(v)
addr := crypto.PubkeyToAddress(key.PublicKey)
InitValidators = append(InitValidators, addr)
ValidatorPriKey = append(ValidatorPriKey, key)
account := core.GenesisAccount{
Balance: big.NewInt(100000000 * 100),
PrivateKey: crypto.FromECDSA(key),
}
alloc[addr] = account
}
gasLimit := uint64(100000000)
sim := backends.NewSimulatedBackend(alloc, gasLimit)
InitPowers := []*big.Int{big.NewInt(80), big.NewInt(10), big.NewInt(10), big.NewInt(10)}
para := &ethtxs.DeployPara{
DeployPrivateKey: genesiskey,
Deployer: genesisAddr,
Operator: genesisAddr,
InitValidators: InitValidators,
ValidatorPriKey: ValidatorPriKey,
InitPowers: InitPowers,
}
return sim, para
}
func DeployContracts() (*ethtxs.DeployPara, *ethinterface.SimExtend, *ethtxs.X2EthContracts, *ethtxs.X2EthDeployInfo, error) {
ctx := context.Background()
sim, para := PrepareTestEnv()
callMsg := ethereum.CallMsg{
From: para.Deployer,
Data: common.FromHex(generated.BridgeBankBin),
}
_, err := sim.EstimateGas(ctx, callMsg)
if nil != err {
panic("failed to estimate gas due to:" + err.Error())
}
x2EthContracts, x2EthDeployInfo, err := ethtxs.DeployAndInit(sim, para)
if nil != err {
return nil, nil, nil, nil, err
}
sim.Commit()
return para, sim, x2EthContracts, x2EthDeployInfo, nil
}
package ethinterface
import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type EthClientSpec interface {
bind.ContractBackend
TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error)
BalanceAt(ctx context.Context, account common.Address, blockNumber *big.Int) (*big.Int, error)
HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error)
}
type SimExtend struct {
*backends.SimulatedBackend
}
func (sim *SimExtend) HeaderByNumber(ctx context.Context, number *big.Int) (*types.Header, error) {
return sim.Blockchain().CurrentBlock().Header(), nil
}
//func (sim *SimExtend) TransactionReceipt(ctx context.Context, txHash common.Hash) (*types.Receipt, error) {
// receipt, err := sim.SimulatedBackend.TransactionReceipt(ctx, txHash)
// if receipt == nil {
// err = errors.New("not found")
// }
//
// return receipt, err
//}
package ethtxs
import (
"strings"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/ethereum/go-ethereum/accounts/abi"
)
const (
BridgeBankABI = "BridgeBankABI"
Chain33BankABI = "Chain33BankABI"
Chain33BridgeABI = "Chain33BridgeABI"
EthereumBankABI = "EthereumBankABI"
)
func LoadABI(contractName string) abi.ABI {
var abiJSON string
switch contractName {
case BridgeBankABI:
abiJSON = generated.BridgeBankABI
case Chain33BankABI:
abiJSON = generated.Chain33BankABI
case Chain33BridgeABI:
abiJSON = generated.Chain33BridgeABI
case EthereumBankABI:
abiJSON = generated.EthereumBankABI
default:
panic("No abi matched")
}
// Convert the raw abi into a usable format
contractABI, err := abi.JSON(strings.NewReader(abiJSON))
if err != nil {
panic(err)
}
return contractABI
}
package ethtxs
import (
"context"
"errors"
"fmt"
"math/big"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
type NewProphecyClaimPara struct {
ClaimType uint8
Chain33Sender []byte
TokenAddr common.Address
EthReceiver common.Address
Symbol string
Amount *big.Int
Txhash []byte
}
func CreateBridgeToken(symbol string, client ethinterface.EthClientSpec, para *OperatorInfo, x2EthDeployInfo *X2EthDeployInfo, x2EthContracts *X2EthContracts) (string, error) {
if nil == para {
return "", errors.New("no operator private key configured")
}
//订阅事件
eventName := "LogNewBridgeToken"
bridgeBankABI := LoadABI(BridgeBankABI)
logNewBridgeTokenSig := bridgeBankABI.Events[eventName].ID().Hex()
query := ethereum.FilterQuery{
Addresses: []common.Address{x2EthDeployInfo.BridgeBank.Address},
}
// We will check logs for new events
logs := make(chan types.Log)
// Filter by contract and event, write results to logs
sub, err := client.SubscribeFilterLogs(context.Background(), query, logs)
if nil != err {
txslog.Error("CreateBrigeToken", "failed to SubscribeFilterLogs", err.Error())
return "", err
}
var prepareDone bool
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(para.Address)
}
}()
//创建token
auth, err := PrepareAuth(client, para.PrivateKey, para.Address)
if nil != err {
return "", err
}
prepareDone = true
tx, err := x2EthContracts.BridgeBank.BridgeBankTransactor.CreateNewBridgeToken(auth, symbol)
if nil != err {
return "", err
}
sim, isSim := client.(*ethinterface.SimExtend)
if isSim {
fmt.Println("Use the simulator")
sim.Commit()
}
err = waitEthTxFinished(client, tx.Hash(), "CreateBridgeToken")
if nil != err {
return "", err
}
logEvent := &events.LogNewBridgeToken{}
select {
// Handle any errors
case err := <-sub.Err():
return "", err
// vLog is raw event data
case vLog := <-logs:
// Check if the event is a 'LogLock' event
if vLog.Topics[0].Hex() == logNewBridgeTokenSig {
txslog.Debug("CreateBrigeToken", "Witnessed new event", eventName, "Block number", vLog.BlockNumber)
err = bridgeBankABI.Unpack(logEvent, eventName, vLog.Data)
if nil != err {
return "", err
}
if symbol != logEvent.Symbol {
txslog.Error("CreateBrigeToken", "symbol", symbol, "logEvent.Symbol", logEvent.Symbol)
}
txslog.Info("CreateBrigeToken", "Witnessed new event", eventName, "Block number", vLog.BlockNumber, "token address", logEvent.Token.String())
break
}
}
return logEvent.Token.String(), nil
}
func CreateERC20Token(symbol string, client ethinterface.EthClientSpec, para *OperatorInfo) (string, error) {
if nil == para {
return "", errors.New("no operator private key configured")
}
var prepareDone bool
var err error
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(para.Address)
}
}()
auth, err := PrepareAuth(client, para.PrivateKey, para.Address)
if nil != err {
return "", err
}
prepareDone = true
tokenAddr, tx, _, err := generated.DeployBridgeToken(auth, client, symbol)
if nil != err {
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "CreateERC20Token")
if nil != err {
return "", err
}
return tokenAddr.String(), nil
}
func MintERC20Token(tokenAddr, ownerAddr string, amount *big.Int, client ethinterface.EthClientSpec, para *OperatorInfo) (string, error) {
if nil == para {
return "", errors.New("no operator private key configured")
}
var prepareDone bool
var err error
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(para.Address)
}
}()
operatorAuth, err := PrepareAuth(client, para.PrivateKey, para.Address)
if nil != err {
return "", err
}
prepareDone = true
erc20TokenInstance, err := generated.NewBridgeToken(common.HexToAddress(tokenAddr), client)
if nil != err {
return "", err
}
tx, err := erc20TokenInstance.Mint(operatorAuth, common.HexToAddress(ownerAddr), amount)
if nil != err {
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "MintERC20Token")
if nil != err {
return "", err
}
return tx.Hash().String(), nil
}
func ApproveAllowance(ownerPrivateKeyStr, tokenAddr string, bridgeBank common.Address, amount *big.Int, client ethinterface.EthClientSpec) (string, error) {
ownerPrivateKey, err := crypto.ToECDSA(common.FromHex(ownerPrivateKeyStr))
if nil != err {
return "", err
}
ownerAddr := crypto.PubkeyToAddress(ownerPrivateKey.PublicKey)
var prepareDone bool
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(ownerAddr)
}
}()
auth, err := PrepareAuth(client, ownerPrivateKey, ownerAddr)
if nil != err {
return "", err
}
prepareDone = true
erc20TokenInstance, err := generated.NewBridgeToken(common.HexToAddress(tokenAddr), client)
if nil != err {
return "", err
}
tx, err := erc20TokenInstance.Approve(auth, bridgeBank, amount)
if nil != err {
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "ApproveAllowance")
if nil != err {
return "", err
}
return tx.Hash().String(), nil
}
func Burn(ownerPrivateKeyStr, tokenAddrstr, chain33Receiver string, bridgeBank common.Address, amount *big.Int, bridgeBankIns *generated.BridgeBank, client ethinterface.EthClientSpec) (string, error) {
ownerPrivateKey, err := crypto.ToECDSA(common.FromHex(ownerPrivateKeyStr))
if nil != err {
return "", err
}
ownerAddr := crypto.PubkeyToAddress(ownerPrivateKey.PublicKey)
var prepareDone bool
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(ownerAddr)
}
}()
auth, err := PrepareAuth(client, ownerPrivateKey, ownerAddr)
if nil != err {
return "", err
}
prepareDone = true
tokenAddr := common.HexToAddress(tokenAddrstr)
tokenInstance, err := generated.NewBridgeToken(tokenAddr, client)
if nil != err {
return "", err
}
//chain33bank 是bridgeBank的基类,所以使用bridgeBank的地址
tx, err := tokenInstance.Approve(auth, bridgeBank, amount)
if nil != err {
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "Approve")
if nil != err {
return "", err
}
txslog.Info("Burn", "Approve tx with hash", tx.Hash().String())
prepareDone = false
auth, err = PrepareAuth(client, ownerPrivateKey, ownerAddr)
if nil != err {
return "", err
}
prepareDone = true
tx, err = bridgeBankIns.BurnBridgeTokens(auth, []byte(chain33Receiver), tokenAddr, amount)
if nil != err {
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "Burn")
if nil != err {
return "", err
}
return tx.Hash().String(), nil
}
func BurnAsync(ownerPrivateKeyStr, tokenAddrstr, chain33Receiver string, amount *big.Int, bridgeBankIns *generated.BridgeBank, client ethinterface.EthClientSpec) (string, error) {
ownerPrivateKey, err := crypto.ToECDSA(common.FromHex(ownerPrivateKeyStr))
if nil != err {
return "", err
}
ownerAddr := crypto.PubkeyToAddress(ownerPrivateKey.PublicKey)
var prepareDone bool
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(ownerAddr)
}
}()
auth, err := PrepareAuth(client, ownerPrivateKey, ownerAddr)
if nil != err {
return "", err
}
prepareDone = true
tokenAddr := common.HexToAddress(tokenAddrstr)
tx, err := bridgeBankIns.BurnBridgeTokens(auth, []byte(chain33Receiver), tokenAddr, amount)
if nil != err {
return "", err
}
return tx.Hash().String(), nil
}
func TransferToken(tokenAddr, fromPrivateKeyStr, toAddr string, amount *big.Int, client ethinterface.EthClientSpec) (string, error) {
tokenInstance, err := generated.NewBridgeToken(common.HexToAddress(tokenAddr), client)
if nil != err {
return "", err
}
var prepareDone bool
fromPrivateKey, err := crypto.ToECDSA(common.FromHex(fromPrivateKeyStr))
if nil != err {
return "", err
}
fromAddr := crypto.PubkeyToAddress(fromPrivateKey.PublicKey)
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(fromAddr)
}
}()
auth, err := PrepareAuth(client, fromPrivateKey, fromAddr)
if nil != err {
return "", err
}
prepareDone = true
tx, err := tokenInstance.Transfer(auth, common.HexToAddress(toAddr), amount)
if nil != err {
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "TransferFromToken")
if nil != err {
return "", err
}
return tx.Hash().String(), nil
}
func LockEthErc20Asset(ownerPrivateKeyStr, tokenAddrStr, chain33Receiver string, amount *big.Int, client ethinterface.EthClientSpec, bridgeBank *generated.BridgeBank, bridgeBankAddr common.Address) (string, error) {
var prepareDone bool
txslog.Info("LockEthErc20Asset", "ownerPrivateKeyStr", ownerPrivateKeyStr, "tokenAddrStr", tokenAddrStr, "chain33Receiver", chain33Receiver, "amount", amount.String())
ownerPrivateKey, err := crypto.ToECDSA(common.FromHex(ownerPrivateKeyStr))
if nil != err {
return "", err
}
ownerAddr := crypto.PubkeyToAddress(ownerPrivateKey.PublicKey)
defer func() {
if err != nil && prepareDone {
_, _ = revokeNonce(ownerAddr)
}
}()
//ETH转账,空地址,且设置value
var tokenAddr common.Address
if "" != tokenAddrStr {
//如果是eth以外的erc20,则需要先进行approve操作
tokenAddr = common.HexToAddress(tokenAddrStr)
tokenInstance, err := generated.NewBridgeToken(tokenAddr, client)
if nil != err {
return "", err
}
auth, err := PrepareAuth(client, ownerPrivateKey, ownerAddr)
if nil != err {
txslog.Error("LockEthErc20Asset", "PrepareAuth err", err.Error())
return "", err
}
prepareDone = true
//chain33bank 是bridgeBank的基类,所以使用bridgeBank的地址
tx, err := tokenInstance.Approve(auth, bridgeBankAddr, amount)
if nil != err {
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "Approve")
if nil != err {
return "", err
}
txslog.Info("LockEthErc20Asset", "Approve tx with hash", tx.Hash().String())
}
prepareDone = false
auth, err := PrepareAuth(client, ownerPrivateKey, ownerAddr)
if nil != err {
txslog.Error("LockEthErc20Asset", "PrepareAuth err", err.Error())
return "", err
}
prepareDone = true
if "" == tokenAddrStr {
auth.Value = amount
}
tx, err := bridgeBank.Lock(auth, []byte(chain33Receiver), tokenAddr, amount)
if nil != err {
txslog.Error("LockEthErc20Asset", "lock err", err.Error())
return "", err
}
err = waitEthTxFinished(client, tx.Hash(), "LockEthErc20Asset")
if nil != err {
txslog.Error("LockEthErc20Asset", "waitEthTxFinished err", err.Error())
return "", err
}
return tx.Hash().String(), nil
}
func LockEthErc20AssetAsync(ownerPrivateKeyStr, tokenAddrStr, chain33Receiver string, amount *big.Int, client ethinterface.EthClientSpec, bridgeBank *generated.BridgeBank) (string, error) {
txslog.Info("LockEthErc20AssetAsync", "ownerPrivateKeyStr", ownerPrivateKeyStr, "tokenAddrStr", tokenAddrStr, "chain33Receiver", chain33Receiver, "amount", amount.String())
ownerPrivateKey, err := crypto.ToECDSA(common.FromHex(ownerPrivateKeyStr))
if nil != err {
return "", err
}
ownerAddr := crypto.PubkeyToAddress(ownerPrivateKey.PublicKey)
auth, err := PrepareAuth(client, ownerPrivateKey, ownerAddr)
if nil != err {
txslog.Error("LockEthErc20AssetAsync", "PrepareAuth err", err.Error())
return "", err
}
//ETH转账,空地址,且设置value
var tokenAddr common.Address
if "" == tokenAddrStr {
auth.Value = amount
}
if "" != tokenAddrStr {
tokenAddr = common.HexToAddress(tokenAddrStr)
}
tx, err := bridgeBank.Lock(auth, []byte(chain33Receiver), tokenAddr, amount)
if nil != err {
txslog.Error("LockEthErc20AssetAsync", "lock err", err.Error())
_, err = revokeNonce(ownerAddr)
if err != nil {
return "", err
}
return "", err
}
return tx.Hash().String(), nil
}
package ethtxs
import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"strings"
"testing"
chain33Types "github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
ebrelayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
x2ethTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
)
var (
chain33Addr = "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
ethAddr = "0x92C8b16aFD6d423652559C6E266cBE1c29Bfd84f"
ethTokenAddr = "0x0000000000000000000000000000000000000000"
)
type suiteContracts struct {
suite.Suite
para *DeployPara
sim *ethinterface.SimExtend
x2EthContracts *X2EthContracts
x2EthDeployInfo *X2EthDeployInfo
}
func TestRunSuiteX2Ethereum(t *testing.T) {
log := new(suiteContracts)
suite.Run(t, log)
}
func (c *suiteContracts) SetupSuite() {
var err error
c.para, c.sim, c.x2EthContracts, c.x2EthDeployInfo, err = DeployContracts()
require.Nil(c.T(), err)
}
func (c *suiteContracts) Test_GetOperator() {
operator, err := GetOperator(c.sim, c.para.InitValidators[0], c.x2EthDeployInfo.BridgeBank.Address)
require.Nil(c.T(), err)
assert.Equal(c.T(), operator.String(), c.para.Operator.String())
}
func (c *suiteContracts) Test_IsActiveValidator() {
bret, err := IsActiveValidator(c.para.InitValidators[0], c.x2EthContracts.Valset)
require.Nil(c.T(), err)
assert.Equal(c.T(), bret, true)
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
bret, err = IsActiveValidator(addr, c.x2EthContracts.Valset)
require.Nil(c.T(), err) // ???
assert.Equal(c.T(), bret, false)
}
func (c *suiteContracts) Test_IsProphecyPending() {
claimID := crypto.Keccak256Hash(big.NewInt(50).Bytes())
bret, err := IsProphecyPending(claimID, c.para.InitValidators[0], c.x2EthContracts.Chain33Bridge)
require.Nil(c.T(), err)
assert.Equal(c.T(), bret, false)
}
func (c *suiteContracts) Test_LogLockToEthBridgeClaim() {
to := common.FromHex(chain33Addr)
event := &events.LockEvent{
From: c.para.InitValidators[0],
To: to,
Token: common.HexToAddress(ethTokenAddr),
Symbol: "eth",
Value: big.NewInt(10000 * 10000 * 10000),
Nonce: big.NewInt(1),
}
witnessClaim, err := LogLockToEthBridgeClaim(event, 1, c.x2EthDeployInfo.BridgeBank.Address.String(), 18)
require.Nil(c.T(), err)
assert.NotEmpty(c.T(), witnessClaim)
assert.Equal(c.T(), witnessClaim.EthereumChainID, int64(1))
assert.Equal(c.T(), witnessClaim.BridgeBrankAddr, c.x2EthDeployInfo.BridgeBank.Address.String())
assert.Equal(c.T(), witnessClaim.TokenAddr, ethTokenAddr)
assert.Equal(c.T(), witnessClaim.Symbol, event.Symbol)
assert.Equal(c.T(), witnessClaim.EthereumSender, event.From.String())
assert.Equal(c.T(), witnessClaim.Chain33Receiver, string(event.To))
assert.Equal(c.T(), witnessClaim.Amount, "100")
assert.Equal(c.T(), witnessClaim.Nonce, event.Nonce.Int64())
assert.Equal(c.T(), witnessClaim.Decimal, int64(18))
event.Token = common.HexToAddress("0x0000000000000000000000000000000000000001")
_, err = LogLockToEthBridgeClaim(event, 1, c.x2EthDeployInfo.BridgeBank.Address.String(), 18)
require.NotNil(c.T(), err)
assert.Equal(c.T(), err, ebrelayerTypes.ErrAddress4Eth)
}
func (c *suiteContracts) Test_LogBurnToEthBridgeClaim() {
to := common.FromHex(chain33Addr)
event := &events.BurnEvent{
OwnerFrom: c.para.InitValidators[0],
Chain33Receiver: to,
Token: common.HexToAddress(ethTokenAddr),
Symbol: "bty",
Amount: big.NewInt(100),
Nonce: big.NewInt(2),
}
witnessClaim, err := LogBurnToEthBridgeClaim(event, 1, c.x2EthDeployInfo.BridgeBank.Address.String(), 8)
require.Nil(c.T(), err)
assert.NotEmpty(c.T(), witnessClaim)
assert.Equal(c.T(), witnessClaim.EthereumChainID, int64(1))
assert.Equal(c.T(), witnessClaim.BridgeBrankAddr, c.x2EthDeployInfo.BridgeBank.Address.String())
assert.Equal(c.T(), witnessClaim.TokenAddr, ethTokenAddr)
assert.Equal(c.T(), witnessClaim.Symbol, event.Symbol)
assert.Equal(c.T(), witnessClaim.EthereumSender, event.OwnerFrom.String())
assert.Equal(c.T(), witnessClaim.Chain33Receiver, string(event.Chain33Receiver))
assert.Equal(c.T(), witnessClaim.Amount, "100")
assert.Equal(c.T(), witnessClaim.Nonce, event.Nonce.Int64())
assert.Equal(c.T(), witnessClaim.Decimal, int64(8))
}
func (c *suiteContracts) Test_ParseBurnLockTxReceipt_Chain33MsgToProphecyClaim() {
claimType := events.MsgBurn
chain33ToEth := types.ReceiptChain33ToEth{
Chain33Sender: chain33Addr,
EthereumReceiver: ethAddr,
TokenContract: ethTokenAddr,
IssuerDotSymbol: "bty",
Amount: "100",
Decimals: 8,
}
log := &chain33Types.ReceiptLog{
Ty: types.TyWithdrawChain33Log,
Log: chain33Types.Encode(&chain33ToEth),
}
var logs []*chain33Types.ReceiptLog
logs = append(logs, log)
receipt := &chain33Types.ReceiptData{
Ty: types.TyWithdrawChain33Log,
Logs: logs,
}
chain33Msg := ParseBurnLockTxReceipt(claimType, receipt)
require.NotNil(c.T(), chain33Msg)
assert.Equal(c.T(), chain33Msg.ClaimType, claimType)
assert.Equal(c.T(), chain33Msg.Chain33Sender, []byte(chain33ToEth.Chain33Sender))
assert.Equal(c.T(), chain33Msg.EthereumReceiver, common.HexToAddress(chain33ToEth.EthereumReceiver))
assert.Equal(c.T(), chain33Msg.TokenContractAddress, common.HexToAddress(chain33ToEth.TokenContract))
assert.Equal(c.T(), chain33Msg.Symbol, chain33ToEth.IssuerDotSymbol)
assert.Equal(c.T(), chain33Msg.Amount.String(), "100")
prophecyClaim := Chain33MsgToProphecyClaim(*chain33Msg)
assert.Equal(c.T(), chain33Msg.ClaimType, prophecyClaim.ClaimType)
assert.Equal(c.T(), chain33Msg.Chain33Sender, prophecyClaim.Chain33Sender)
assert.Equal(c.T(), chain33Msg.EthereumReceiver, prophecyClaim.EthereumReceiver)
assert.Equal(c.T(), chain33Msg.TokenContractAddress, prophecyClaim.TokenContractAddress)
assert.Equal(c.T(), strings.ToLower(chain33Msg.Symbol), prophecyClaim.Symbol)
assert.Equal(c.T(), chain33Msg.Amount, prophecyClaim.Amount)
}
func (c *suiteContracts) Test_RecoverContractHandler() {
_, _, err := RecoverContractHandler(c.sim, c.x2EthDeployInfo.BridgeRegistry.Address, c.x2EthDeployInfo.BridgeRegistry.Address)
require.Nil(c.T(), err)
}
func (c *suiteContracts) Test_RecoverOracleInstance() {
oracleInstance, err := RecoverOracleInstance(c.sim, c.x2EthDeployInfo.BridgeRegistry.Address, c.x2EthDeployInfo.BridgeRegistry.Address)
require.Nil(c.T(), err)
require.NotNil(c.T(), oracleInstance)
}
func (c *suiteContracts) Test_GetDeployHeight() {
height, err := GetDeployHeight(c.sim, c.x2EthDeployInfo.BridgeRegistry.Address, c.x2EthDeployInfo.BridgeRegistry.Address)
require.Nil(c.T(), err)
assert.True(c.T(), height > 0)
}
func (c *suiteContracts) Test_CreateBridgeToken() {
operatorInfo := &OperatorInfo{
PrivateKey: c.para.DeployPrivateKey,
Address: crypto.PubkeyToAddress(c.para.DeployPrivateKey.PublicKey),
}
tokenAddr, err := CreateBridgeToken("bty", c.sim, operatorInfo, c.x2EthDeployInfo, c.x2EthContracts)
require.Nil(c.T(), err)
c.sim.Commit()
addr, err := GetToken2address(c.x2EthContracts.BridgeBank, "bty")
require.Nil(c.T(), err)
assert.Equal(c.T(), addr, tokenAddr)
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
amount := int64(100)
ethReceiver := c.para.InitValidators[2]
claimID := crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), big.NewInt(amount).Bytes())
authOracle, err := PrepareAuth(c.sim, c.para.ValidatorPriKey[0], c.para.InitValidators[0])
require.Nil(c.T(), err)
signature, err := SignClaim4Eth(claimID, c.para.ValidatorPriKey[0])
require.Nil(c.T(), err)
_, err = c.x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeLock,
chain33Sender,
ethReceiver,
common.HexToAddress(tokenAddr),
"bty",
big.NewInt(amount),
claimID,
signature)
require.Nil(c.T(), err)
c.sim.Commit()
balanceNew, err := GetBalance(c.sim, tokenAddr, ethReceiver.String())
require.Nil(c.T(), err)
require.Equal(c.T(), balanceNew, "100")
chain33Receiver := "1GTxrmuWiXavhcvsaH5w9whgVxUrWsUMdV"
{
amount := "10"
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
txhash, err := Burn(hexutil.Encode(crypto.FromECDSA(c.para.ValidatorPriKey[2])), tokenAddr, chain33Receiver, c.x2EthDeployInfo.BridgeBank.Address, bn, c.x2EthContracts.BridgeBank, c.sim)
require.NoError(c.T(), err)
c.sim.Commit()
balanceNew, err = GetBalance(c.sim, tokenAddr, ethReceiver.String())
require.Nil(c.T(), err)
require.Equal(c.T(), balanceNew, "90")
status := GetEthTxStatus(c.sim, common.HexToHash(txhash))
fmt.Println()
fmt.Println(status)
}
{
amount := "10"
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
_, err := ApproveAllowance(hexutil.Encode(crypto.FromECDSA(c.para.ValidatorPriKey[2])), tokenAddr, c.x2EthDeployInfo.BridgeBank.Address, bn, c.sim)
require.Nil(c.T(), err)
c.sim.Commit()
_, err = BurnAsync(hexutil.Encode(crypto.FromECDSA(c.para.ValidatorPriKey[2])), tokenAddr, chain33Receiver, bn, c.x2EthContracts.BridgeBank, c.sim)
require.Nil(c.T(), err)
c.sim.Commit()
balanceNew, err = GetBalance(c.sim, tokenAddr, ethReceiver.String())
require.Nil(c.T(), err)
require.Equal(c.T(), balanceNew, "80")
}
}
func (c *suiteContracts) Test_CreateERC20Token() {
operatorInfo := &OperatorInfo{
PrivateKey: c.para.DeployPrivateKey,
Address: crypto.PubkeyToAddress(c.para.DeployPrivateKey.PublicKey),
}
tokenAddr, err := CreateERC20Token("testc", c.sim, operatorInfo)
require.Nil(c.T(), err)
c.sim.Commit()
amount := "10000000000000"
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
_, err = MintERC20Token(tokenAddr, c.para.Deployer.String(), bn, c.sim, operatorInfo)
require.Nil(c.T(), err)
c.sim.Commit()
balance, err := GetDepositFunds(c.sim, tokenAddr)
require.Nil(c.T(), err)
assert.Equal(c.T(), balance, amount)
amount = "100"
bn = big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
txhash, err := TransferToken(tokenAddr, hexutil.Encode(crypto.FromECDSA(c.para.DeployPrivateKey)), c.para.InitValidators[0].String(), bn, c.sim)
require.Nil(c.T(), err)
c.sim.Commit()
_, err = c.sim.TransactionReceipt(context.Background(), common.HexToHash(txhash))
require.Nil(c.T(), err)
balance, err = GetBalance(c.sim, tokenAddr, c.para.InitValidators[0].String())
require.Nil(c.T(), err)
assert.Equal(c.T(), balance, amount)
{
amount = "100"
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
chain33Receiver := "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
_, err = LockEthErc20Asset(hexutil.Encode(crypto.FromECDSA(c.para.DeployPrivateKey)), tokenAddr, chain33Receiver, bn, c.sim, c.x2EthContracts.BridgeBank, c.x2EthDeployInfo.BridgeBank.Address)
require.Nil(c.T(), err)
c.sim.Commit()
balance, err = GetBalance(c.sim, tokenAddr, c.para.Deployer.String())
require.Nil(c.T(), err)
fmt.Println(balance)
assert.Equal(c.T(), balance, "9999999999800")
}
{
amount := "800"
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
_, err = ApproveAllowance(hexutil.Encode(crypto.FromECDSA(c.para.DeployPrivateKey)), tokenAddr, c.x2EthDeployInfo.BridgeBank.Address, bn, c.sim)
require.Nil(c.T(), err)
c.sim.Commit()
chain33Receiver := "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
_, err = LockEthErc20AssetAsync(hexutil.Encode(crypto.FromECDSA(c.para.DeployPrivateKey)), tokenAddr, chain33Receiver, bn, c.sim, c.x2EthContracts.BridgeBank)
require.Nil(c.T(), err)
c.sim.Commit()
balance, err = GetBalance(c.sim, tokenAddr, c.para.Deployer.String())
require.Nil(c.T(), err)
fmt.Println(balance)
assert.Equal(c.T(), balance, "9999999999000")
}
}
func (c *suiteContracts) Test_GetLockedFunds() {
balance, err := GetLockedFunds(c.x2EthContracts.BridgeBank, "")
require.Nil(c.T(), err)
assert.Equal(c.T(), balance, "0")
}
func PrepareTestEnv() (*ethinterface.SimExtend, *DeployPara) {
genesiskey, _ := crypto.GenerateKey()
alloc := make(core.GenesisAlloc)
genesisAddr := crypto.PubkeyToAddress(genesiskey.PublicKey)
genesisAccount := core.GenesisAccount{
Balance: big.NewInt(10000000000 * 10000),
PrivateKey: crypto.FromECDSA(genesiskey),
}
alloc[genesisAddr] = genesisAccount
var InitValidators []common.Address
var ValidatorPriKey []*ecdsa.PrivateKey
for i := 0; i < 4; i++ {
key, _ := crypto.GenerateKey()
addr := crypto.PubkeyToAddress(key.PublicKey)
InitValidators = append(InitValidators, addr)
ValidatorPriKey = append(ValidatorPriKey, key)
account := core.GenesisAccount{
Balance: big.NewInt(100000000 * 100),
PrivateKey: crypto.FromECDSA(key),
}
alloc[addr] = account
}
gasLimit := uint64(100000000)
sim := new(ethinterface.SimExtend)
sim.SimulatedBackend = backends.NewSimulatedBackend(alloc, gasLimit)
InitPowers := []*big.Int{big.NewInt(80), big.NewInt(10), big.NewInt(10), big.NewInt(10)}
para := &DeployPara{
DeployPrivateKey: genesiskey,
Deployer: genesisAddr,
Operator: genesisAddr,
InitValidators: InitValidators,
ValidatorPriKey: ValidatorPriKey,
InitPowers: InitPowers,
}
return sim, para
}
func DeployContracts() (*DeployPara, *ethinterface.SimExtend, *X2EthContracts, *X2EthDeployInfo, error) {
ctx := context.Background()
sim, para := PrepareTestEnv()
callMsg := ethereum.CallMsg{
From: para.Deployer,
Data: common.FromHex(generated.BridgeBankBin),
}
_, err := sim.EstimateGas(ctx, callMsg)
if nil != err {
panic("failed to estimate gas due to:" + err.Error())
}
x2EthContracts, x2EthDeployInfo, err := DeployAndInit(sim, para)
if nil != err {
return nil, nil, nil, nil, err
}
sim.Commit()
return para, sim, x2EthContracts, x2EthDeployInfo, nil
}
package ethtxs
import (
"context"
"crypto/ecdsa"
"fmt"
"math/big"
"time"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
)
var (
deployLog = log15.New("contract deployer", "deployer")
)
type DeployResult struct {
Address common.Address
TxHash string
}
type X2EthContracts struct {
BridgeRegistry *generated.BridgeRegistry
BridgeBank *generated.BridgeBank
Chain33Bridge *generated.Chain33Bridge
Valset *generated.Valset
Oracle *generated.Oracle
}
type X2EthDeployInfo struct {
BridgeRegistry *DeployResult
BridgeBank *DeployResult
Chain33Bridge *DeployResult
Valset *DeployResult
Oracle *DeployResult
}
type DeployPara struct {
DeployPrivateKey *ecdsa.PrivateKey
Deployer common.Address
Operator common.Address
InitValidators []common.Address
ValidatorPriKey []*ecdsa.PrivateKey
InitPowers []*big.Int
}
type OperatorInfo struct {
PrivateKey *ecdsa.PrivateKey
Address common.Address
}
//DeployValset: 部署Valset
func DeployValset(client ethinterface.EthClientSpec, privateKey *ecdsa.PrivateKey, deployer common.Address, operator common.Address, initValidators []common.Address, initPowers []*big.Int) (*generated.Valset, *DeployResult, error) {
auth, err := PrepareAuth(client, privateKey, deployer)
if nil != err {
return nil, nil, err
}
//部署合约
addr, tx, valset, err := generated.DeployValset(auth, client, operator, initValidators, initPowers)
if err != nil {
return nil, nil, err
}
deployResult := &DeployResult{
Address: addr,
TxHash: tx.Hash().String(),
}
return valset, deployResult, nil
}
//DeployChain33Bridge: 部署Chain33Bridge
func DeployChain33Bridge(client ethinterface.EthClientSpec, privateKey *ecdsa.PrivateKey, deployer common.Address, operator, valset common.Address) (*generated.Chain33Bridge, *DeployResult, error) {
auth, err := PrepareAuth(client, privateKey, deployer)
if nil != err {
return nil, nil, err
}
//部署合约
addr, tx, chain33Bridge, err := generated.DeployChain33Bridge(auth, client, operator, valset)
if err != nil {
return nil, nil, err
}
deployResult := &DeployResult{
Address: addr,
TxHash: tx.Hash().String(),
}
return chain33Bridge, deployResult, nil
}
//DeployOracle: 部署Oracle
func DeployOracle(client ethinterface.EthClientSpec, privateKey *ecdsa.PrivateKey, deployer, operator, valset, chain33Bridge common.Address) (*generated.Oracle, *DeployResult, error) {
auth, err := PrepareAuth(client, privateKey, deployer)
if nil != err {
return nil, nil, err
}
//部署合约
addr, tx, oracle, err := generated.DeployOracle(auth, client, operator, valset, chain33Bridge)
if err != nil {
return nil, nil, err
}
deployResult := &DeployResult{
Address: addr,
TxHash: tx.Hash().String(),
}
return oracle, deployResult, nil
}
//DeployBridgeBank: 部署BridgeBank
func DeployBridgeBank(client ethinterface.EthClientSpec, privateKey *ecdsa.PrivateKey, deployer, operator, oracle, chain33Bridge common.Address) (*generated.BridgeBank, *DeployResult, error) {
auth, err := PrepareAuth(client, privateKey, deployer)
if nil != err {
return nil, nil, err
}
//部署合约
addr, tx, bridgeBank, err := generated.DeployBridgeBank(auth, client, operator, oracle, chain33Bridge)
if err != nil {
return nil, nil, err
}
deployResult := &DeployResult{
Address: addr,
TxHash: tx.Hash().String(),
}
return bridgeBank, deployResult, nil
}
//DeployBridgeRegistry: 部署BridgeRegistry
func DeployBridgeRegistry(client ethinterface.EthClientSpec, privateKey *ecdsa.PrivateKey, deployer, chain33BridgeAddr, bridgeBankAddr, oracleAddr, valsetAddr common.Address) (*generated.BridgeRegistry, *DeployResult, error) {
auth, err := PrepareAuth(client, privateKey, deployer)
if nil != err {
return nil, nil, err
}
//部署合约
addr, tx, bridgeRegistry, err := generated.DeployBridgeRegistry(auth, client, chain33BridgeAddr, bridgeBankAddr, oracleAddr, valsetAddr)
if err != nil {
return nil, nil, err
}
deployResult := &DeployResult{
Address: addr,
TxHash: tx.Hash().String(),
}
return bridgeRegistry, deployResult, nil
}
func DeployAndInit(client ethinterface.EthClientSpec, para *DeployPara) (*X2EthContracts, *X2EthDeployInfo, error) {
x2EthContracts := &X2EthContracts{}
deployInfo := &X2EthDeployInfo{}
var err error
/////////////////////////////////////
sim, isSim := client.(*ethinterface.SimExtend)
if isSim {
fmt.Println("Use the simulator")
} else {
fmt.Println("Use the actual Ethereum")
}
x2EthContracts.Valset, deployInfo.Valset, err = DeployValset(client, para.DeployPrivateKey, para.Deployer, para.Operator, para.InitValidators, para.InitPowers)
if nil != err {
deployLog.Error("DeployAndInit", "failed to DeployValset due to:", err.Error())
return nil, nil, err
}
if isSim {
sim.Commit()
} else {
fmt.Println("\nDeployValset tx hash:", deployInfo.Valset.TxHash)
timeout := time.NewTimer(300 * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
panic("DeployValset timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), common.HexToHash(deployInfo.Valset.TxHash))
if err == ethereum.NotFound {
fmt.Println("\n No receipt received yet for DeployValset tx and continue to wait")
continue
} else if err != nil {
panic("DeployValset failed due to" + err.Error())
}
callopts := &bind.CallOpts{
Pending: true,
From: para.Deployer,
Context: context.Background(),
}
operator, err := x2EthContracts.Valset.Operator(callopts)
if nil != err {
panic(err.Error())
}
if operator.String() != para.Operator.String() {
fmt.Printf("operator queried from valset is:%s, and setted is:%s", operator.String(), para.Operator.String())
panic("operator query is not same as setted ")
}
goto deployChain33Bridge
}
}
}
deployChain33Bridge:
x2EthContracts.Chain33Bridge, deployInfo.Chain33Bridge, err = DeployChain33Bridge(client, para.DeployPrivateKey, para.Deployer, para.Operator, deployInfo.Valset.Address)
if nil != err {
deployLog.Error("DeployAndInit", "failed to DeployChain33Bridge due to:", err.Error())
return nil, nil, err
}
if isSim {
sim.Commit()
} else {
fmt.Printf("\n\nGoing to DeployChain33Bridge with valset address:%s", deployInfo.Valset.Address.String())
fmt.Println("\nDeployChain33Bridge tx hash:", deployInfo.Chain33Bridge.TxHash)
timeout := time.NewTimer(300 * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
panic("DeployChain33Bridge timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), common.HexToHash(deployInfo.Chain33Bridge.TxHash))
if err == ethereum.NotFound {
fmt.Println("\n No receipt received for DeployChain33Bridge tx and continue to wait")
continue
} else if err != nil {
panic("DeployChain33Bridge failed due to" + err.Error())
}
callopts := &bind.CallOpts{
Pending: true,
From: para.Deployer,
Context: context.Background(),
}
operator, err := x2EthContracts.Chain33Bridge.Operator(callopts)
if nil != err {
panic(err.Error())
}
if operator.String() != para.Operator.String() {
fmt.Printf("operator queried from valset is:%s, and setted is:%s", operator.String(), para.Operator.String())
panic("operator query is not same as setted ")
}
goto deployOracle
}
}
}
deployOracle:
x2EthContracts.Oracle, deployInfo.Oracle, err = DeployOracle(client, para.DeployPrivateKey, para.Deployer, para.Operator, deployInfo.Valset.Address, deployInfo.Chain33Bridge.Address)
if nil != err {
deployLog.Error("DeployAndInit", "failed to DeployOracle due to:", err.Error())
return nil, nil, err
}
if isSim {
sim.Commit()
} else {
fmt.Println("DeployOracle tx hash:", deployInfo.Oracle.TxHash)
timeout := time.NewTimer(300 * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
panic("DeployOracle timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), common.HexToHash(deployInfo.Oracle.TxHash))
if err == ethereum.NotFound {
fmt.Println("\n No receipt received for DeployOracle tx and continue to wait")
continue
} else if err != nil {
panic("DeployOracle failed due to" + err.Error())
}
callopts := &bind.CallOpts{
Pending: true,
From: para.Deployer,
Context: context.Background(),
}
operator, err := x2EthContracts.Oracle.Operator(callopts)
if nil != err {
panic(err.Error())
}
if operator.String() != para.Operator.String() {
fmt.Printf("operator queried from valset is:%s, and setted is:%s", operator.String(), para.Operator.String())
panic("operator query is not same as setted ")
}
goto deployBridgeBank
}
}
}
/////////////////////////////////////
deployBridgeBank:
x2EthContracts.BridgeBank, deployInfo.BridgeBank, err = DeployBridgeBank(client, para.DeployPrivateKey, para.Deployer, para.Operator, deployInfo.Oracle.Address, deployInfo.Chain33Bridge.Address)
if nil != err {
deployLog.Error("DeployAndInit", "failed to DeployBridgeBank due to:", err.Error())
return nil, nil, err
}
if isSim {
sim.Commit()
} else {
fmt.Println("DeployBridgeBank tx hash:", deployInfo.BridgeBank.TxHash)
timeout := time.NewTimer(300 * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
panic("DeployBridgeBank timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), common.HexToHash(deployInfo.BridgeBank.TxHash))
if err == ethereum.NotFound {
fmt.Println("\n No receipt received for DeployOracle tx and continue to wait")
continue
} else if err != nil {
panic("DeployBridgeBank failed due to" + err.Error())
}
callopts := &bind.CallOpts{
Pending: true,
From: para.Deployer,
Context: context.Background(),
}
operator, err := x2EthContracts.BridgeBank.Operator(callopts)
if nil != err {
panic(err.Error())
}
if operator.String() != para.Operator.String() {
fmt.Printf("operator queried from valset is:%s, and setted is:%s", operator.String(), para.Operator.String())
panic("operator query is not same as setted ")
}
goto settingBridgeBank
}
}
}
settingBridgeBank:
////////////////////////
auth, err := PrepareAuth(client, para.DeployPrivateKey, para.Deployer)
if nil != err {
return nil, nil, err
}
setBridgeBankTx, err := x2EthContracts.Chain33Bridge.SetBridgeBank(auth, deployInfo.BridgeBank.Address)
if nil != err {
deployLog.Error("DeployAndInit", "failed to SetBridgeBank due to:", err.Error())
return nil, nil, err
}
if isSim {
sim.Commit()
} else {
fmt.Println("setBridgeBankTx tx hash:", setBridgeBankTx.Hash().String())
timeout := time.NewTimer(300 * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
panic("setBridgeBankTx timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), setBridgeBankTx.Hash())
if err == ethereum.NotFound {
fmt.Println("\n No receipt received for setBridgeBankTx tx and continue to wait")
continue
} else if err != nil {
panic("setBridgeBankTx failed due to" + err.Error())
}
callopts := &bind.CallOpts{
Pending: true,
From: para.Deployer,
Context: context.Background(),
}
yes, err := x2EthContracts.Chain33Bridge.HasBridgeBank(callopts)
if nil != err {
panic(err.Error())
}
if !yes {
fmt.Printf("BridgeBank doesn't exist")
panic("BridgeBank doesn't exist")
}
goto setOracle
}
}
}
setOracle:
auth, err = PrepareAuth(client, para.DeployPrivateKey, para.Deployer)
if nil != err {
return nil, nil, err
}
setOracleTx, err := x2EthContracts.Chain33Bridge.SetOracle(auth, deployInfo.Oracle.Address)
if nil != err {
deployLog.Error("DeployAndInit", "failed to SetOracle due to:", err.Error())
return nil, nil, err
}
if isSim {
sim.Commit()
} else {
fmt.Println("setOracleTx tx hash:", setOracleTx.Hash().String())
timeout := time.NewTimer(300 * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
panic("setBridgeBankTx timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), setOracleTx.Hash())
if err == ethereum.NotFound {
fmt.Println("\n No receipt received for setOracleTx tx and continue to wait")
continue
} else if err != nil {
panic("setOracleTx failed due to" + err.Error())
}
callopts := &bind.CallOpts{
Pending: true,
From: para.Deployer,
Context: context.Background(),
}
yes, err := x2EthContracts.Chain33Bridge.HasOracle(callopts)
if nil != err {
panic(err.Error())
}
if !yes {
fmt.Printf("oracle doesn't exist")
panic("oracle doesn't exist")
}
goto deployBridgeRegistry
}
}
}
deployBridgeRegistry:
x2EthContracts.BridgeRegistry, deployInfo.BridgeRegistry, err = DeployBridgeRegistry(client, para.DeployPrivateKey, para.Deployer, deployInfo.Chain33Bridge.Address, deployInfo.BridgeBank.Address, deployInfo.Oracle.Address, deployInfo.Valset.Address)
if nil != err {
deployLog.Error("DeployAndInit", "failed to DeployBridgeBank due to:", err.Error())
return nil, nil, err
}
if isSim {
sim.Commit()
} else {
fmt.Println("DeployBridgeRegistry tx hash:", deployInfo.BridgeRegistry.TxHash)
timeout := time.NewTimer(300 * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
panic("DeployBridgeRegistry timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), common.HexToHash(deployInfo.BridgeRegistry.TxHash))
if err == ethereum.NotFound {
fmt.Println("\n No receipt received for DeployOracle tx and continue to wait")
continue
} else if err != nil {
panic("DeployBridgeRegistry failed due to" + err.Error())
}
callopts := &bind.CallOpts{
Pending: true,
From: para.Deployer,
Context: context.Background(),
}
oracleAddr, err := x2EthContracts.BridgeRegistry.Oracle(callopts)
if nil != err {
panic(err.Error())
}
if oracleAddr.String() != deployInfo.Oracle.Address.String() {
fmt.Printf("oracleAddr queried from BridgeRegistry is:%s, and setted is:%s", oracleAddr.String(), deployInfo.Oracle.Address.String())
panic("oracleAddr query is not same as setted ")
}
goto finished
}
}
}
finished:
return x2EthContracts, deployInfo, nil
}
package ethtxs
import (
"context"
"crypto/ecdsa"
"math/big"
"testing"
chain33Common "github.com/33cn/chain33/common"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_LoadABI(t *testing.T) {
abi1 := LoadABI(Chain33BankABI)
abi2 := LoadABI(Chain33BridgeABI)
abi3 := LoadABI(EthereumBankABI)
assert.NotEmpty(t, abi1, abi2, abi3)
}
func Test_isWebsocketURL(t *testing.T) {
bret := isWebsocketURL("ws://127.0.0.1:7545/")
assert.Equal(t, bret, true)
bret = isWebsocketURL("https://127.0.0.1:7545/")
assert.Equal(t, bret, false)
}
func TestContractRegistry_String(t *testing.T) {
assert.Equal(t, Valset.String(), "valset")
assert.Equal(t, Oracle.String(), "oracle")
assert.Equal(t, BridgeBank.String(), "bridgebank")
assert.Equal(t, Chain33Bridge.String(), "chain33bridge")
}
func Test_GetAddressFromBridgeRegistry(t *testing.T) {
genesiskey, _ := crypto.GenerateKey()
alloc := make(core.GenesisAlloc)
genesisAddr := crypto.PubkeyToAddress(genesiskey.PublicKey)
genesisAccount := core.GenesisAccount{
Balance: big.NewInt(10000000000 * 10000),
PrivateKey: crypto.FromECDSA(genesiskey),
}
alloc[genesisAddr] = genesisAccount
gasLimit := uint64(100000000)
sim := new(ethinterface.SimExtend)
sim.SimulatedBackend = backends.NewSimulatedBackend(alloc, gasLimit)
bridgebankTest := ContractRegistry(5)
_, err := GetAddressFromBridgeRegistry(sim, genesisAddr, genesisAddr, bridgebankTest)
require.NotNil(t, err)
}
func Test_RelayOracleClaimToEthereum(t *testing.T) {
para, sim, x2EthContracts, _, err := deployContracts()
require.NoError(t, err)
claimType := events.MsgBurn
privateKeySlice, err := chain33Common.FromHex("0x3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e")
require.Nil(t, err)
privateKey, err := crypto.ToECDSA(privateKeySlice)
require.Nil(t, err)
prophecyClaim := ProphecyClaim{
ClaimType: events.MsgBurn,
Chain33Sender: []byte("12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"),
EthereumReceiver: common.HexToAddress("0x0C05bA5c230fDaA503b53702aF1962e08D0C60BF"),
TokenContractAddress: common.HexToAddress("0x0000000000000000000000000000000000000000"),
Symbol: "eth",
Amount: big.NewInt(100000000000000000),
}
chain33TxHash := common.Hex2Bytes("fd5747c43d1460bb6f8a7a26c66b4ccab5500d05668278efe5c0fd5951dfd909")
txhash, err := RelayOracleClaimToEthereum(x2EthContracts.Oracle, sim, para.InitValidators[0], claimType, prophecyClaim, privateKey, chain33TxHash)
require.Nil(t, err)
assert.Equal(t, txhash, "0x6fa087c7a2a8a4421f6e269fbc6c0838e99fa59d5760155a71cd7eb1c01aafad")
//hash := "0xc0c22aa6198fdde0dbe47ddadbe449f736b82ed4a498871de5d5f4ad9ae122a0"
//status := GetEthTxStatus(sim, common.HexToHash(hash))
//assert.Equal(t, status, EthTxPending.String())
_, err = revokeNonce(para.Operator)
require.Nil(t, err)
}
func Test_revokeNonce(t *testing.T) {
}
func deployContracts() (*DeployPara, *ethinterface.SimExtend, *X2EthContracts, *X2EthDeployInfo, error) {
// 0x8AFDADFC88a1087c9A1D6c0F5Dd04634b87F303a
deployerPrivateKey := "8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
// 0x92C8b16aFD6d423652559C6E266cBE1c29Bfd84f
ethValidatorAddrKeyA := "3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
ethValidatorAddrKeyB := "a5f3063552f4483cfc20ac4f40f45b798791379862219de9e915c64722c1d400"
ethValidatorAddrKeyC := "bbf5e65539e9af0eb0cfac30bad475111054b09c11d668fc0731d54ea777471e"
ethValidatorAddrKeyD := "c9fa31d7984edf81b8ef3b40c761f1847f6fcd5711ab2462da97dc458f1f896b"
ethValidatorAddrKeys := make([]string, 0)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyA)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyB)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyC)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyD)
ctx := context.Background()
//var backend bind.ContractBackend
backend, para := PrepareTestEnvironment(deployerPrivateKey, ethValidatorAddrKeys)
sim := new(ethinterface.SimExtend)
sim.SimulatedBackend = backend.(*backends.SimulatedBackend)
callMsg := ethereum.CallMsg{
From: para.Deployer,
Data: common.FromHex(generated.BridgeBankBin),
}
_, err := sim.EstimateGas(ctx, callMsg)
if nil != err {
panic("failed to estimate gas due to:" + err.Error())
}
x2EthContracts, x2EthDeployInfo, err := DeployAndInit(sim, para)
if nil != err {
return nil, nil, nil, nil, err
}
sim.Commit()
return para, sim, x2EthContracts, x2EthDeployInfo, nil
}
func PrepareTestEnvironment(deployerPrivateKey string, ethValidatorAddrKeys []string) (bind.ContractBackend, *DeployPara) {
genesiskey, _ := crypto.HexToECDSA(deployerPrivateKey)
alloc := make(core.GenesisAlloc)
genesisAddr := crypto.PubkeyToAddress(genesiskey.PublicKey)
genesisAccount := core.GenesisAccount{
Balance: big.NewInt(10000000000 * 10000),
PrivateKey: crypto.FromECDSA(genesiskey),
}
alloc[genesisAddr] = genesisAccount
var InitValidators []common.Address
var ValidatorPriKey []*ecdsa.PrivateKey
for _, v := range ethValidatorAddrKeys {
key, _ := crypto.HexToECDSA(v)
addr := crypto.PubkeyToAddress(key.PublicKey)
InitValidators = append(InitValidators, addr)
ValidatorPriKey = append(ValidatorPriKey, key)
account := core.GenesisAccount{
Balance: big.NewInt(100000000 * 100),
PrivateKey: crypto.FromECDSA(key),
}
alloc[addr] = account
}
gasLimit := uint64(100000000)
sim := backends.NewSimulatedBackend(alloc, gasLimit)
InitPowers := []*big.Int{big.NewInt(80), big.NewInt(10), big.NewInt(10), big.NewInt(10)}
para := &DeployPara{
DeployPrivateKey: genesiskey,
Deployer: genesisAddr,
Operator: genesisAddr,
InitValidators: InitValidators,
ValidatorPriKey: ValidatorPriKey,
InitPowers: InitPowers,
}
return sim, para
}
package ethtxs
// ------------------------------------------------------------
// Network: Validates input and initializes a websocket Ethereum client.
// ------------------------------------------------------------
import (
"fmt"
"net/url"
"strings"
"github.com/ethereum/go-ethereum/ethclient"
log "github.com/golang/glog"
)
// IsWebsocketURL : returns true if the given URL is a websocket URL
func isWebsocketURL(rawurl string) bool {
u, err := url.Parse(rawurl)
if err != nil {
log.Infof("Error while parsing URL: %v", err)
return false
}
return u.Scheme == "ws" || u.Scheme == "wss"
}
// SetupWebsocketEthClient : returns boolean indicating if a URL is valid websocket ethclient
func SetupWebsocketEthClient(ethURL string) (*ethclient.Client, error) {
if strings.TrimSpace(ethURL) == "" {
return nil, nil
}
if !isWebsocketURL(ethURL) {
return nil, fmt.Errorf("invalid websocket eth client URL: %v", ethURL)
}
client, err := ethclient.Dial(ethURL)
if err != nil {
return nil, fmt.Errorf("error dialing websocket client %w", err)
}
return client, nil
}
package ethtxs
// --------------------------------------------------------
// Parser
//
// Parses structs containing event information into
// unsigned transactions for validators to sign, then
// relays the data packets as transactions on the
// chain33 Bridge.
// --------------------------------------------------------
import (
"math/big"
"strings"
chain33Types "github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
ebrelayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
"github.com/ethereum/go-ethereum/common"
)
// LogLockToEthBridgeClaim : parses and packages a LockEvent struct with a validator address in an EthBridgeClaim msg
func LogLockToEthBridgeClaim(event *events.LockEvent, ethereumChainID int64, bridgeBrankAddr string, decimal int64) (*ebrelayerTypes.EthBridgeClaim, error) {
recipient := event.To
if 0 == len(recipient) {
return nil, ebrelayerTypes.ErrEmptyAddress
}
// Symbol formatted to lowercase
symbol := strings.ToLower(event.Symbol)
if symbol == "eth" && event.Token != common.HexToAddress("0x0000000000000000000000000000000000000000") {
return nil, ebrelayerTypes.ErrAddress4Eth
}
witnessClaim := &ebrelayerTypes.EthBridgeClaim{}
witnessClaim.EthereumChainID = ethereumChainID
witnessClaim.BridgeBrankAddr = bridgeBrankAddr
witnessClaim.Nonce = event.Nonce.Int64()
witnessClaim.TokenAddr = event.Token.String()
witnessClaim.Symbol = event.Symbol
witnessClaim.EthereumSender = event.From.String()
witnessClaim.Chain33Receiver = string(recipient)
if decimal > 8 {
event.Value = event.Value.Quo(event.Value, big.NewInt(int64(types.MultiplySpecifyTimes(1, decimal-8))))
} else {
event.Value = event.Value.Mul(event.Value, big.NewInt(int64(types.MultiplySpecifyTimes(1, 8-decimal))))
}
witnessClaim.Amount = event.Value.String()
witnessClaim.ClaimType = types.LockClaimType
witnessClaim.ChainName = types.LockClaim
witnessClaim.Decimal = decimal
return witnessClaim, nil
}
func LogBurnToEthBridgeClaim(event *events.BurnEvent, ethereumChainID int64, bridgeBrankAddr string, decimal int64) (*ebrelayerTypes.EthBridgeClaim, error) {
recipient := event.Chain33Receiver
if 0 == len(recipient) {
return nil, ebrelayerTypes.ErrEmptyAddress
}
witnessClaim := &ebrelayerTypes.EthBridgeClaim{}
witnessClaim.EthereumChainID = ethereumChainID
witnessClaim.BridgeBrankAddr = bridgeBrankAddr
witnessClaim.Nonce = event.Nonce.Int64()
witnessClaim.TokenAddr = event.Token.String()
witnessClaim.Symbol = event.Symbol
witnessClaim.EthereumSender = event.OwnerFrom.String()
witnessClaim.Chain33Receiver = string(recipient)
witnessClaim.Amount = event.Amount.String()
witnessClaim.ClaimType = types.BurnClaimType
witnessClaim.ChainName = types.BurnClaim
witnessClaim.Decimal = decimal
return witnessClaim, nil
}
// ParseBurnLockTxReceipt : parses data from a Burn/Lock event witnessed on chain33 into a Chain33Msg struct
func ParseBurnLockTxReceipt(claimType events.Event, receipt *chain33Types.ReceiptData) *events.Chain33Msg {
// Set up variables
var chain33Sender []byte
var ethereumReceiver, tokenContractAddress common.Address
var symbol string
var amount *big.Int
// Iterate over attributes
for _, log := range receipt.Logs {
if log.Ty == types.TyChain33ToEthLog || log.Ty == types.TyWithdrawChain33Log {
txslog.Debug("ParseBurnLockTxReceipt", "value", string(log.Log))
var chain33ToEth types.ReceiptChain33ToEth
err := chain33Types.Decode(log.Log, &chain33ToEth)
if err != nil {
return nil
}
chain33Sender = []byte(chain33ToEth.Chain33Sender)
ethereumReceiver = common.HexToAddress(chain33ToEth.EthereumReceiver)
tokenContractAddress = common.HexToAddress(chain33ToEth.TokenContract)
symbol = chain33ToEth.IssuerDotSymbol
chain33ToEth.Amount = types.TrimZeroAndDot(chain33ToEth.Amount)
amount = big.NewInt(1)
amount, _ = amount.SetString(chain33ToEth.Amount, 10)
if chain33ToEth.Decimals > 8 {
amount = amount.Mul(amount, big.NewInt(int64(types.MultiplySpecifyTimes(1, chain33ToEth.Decimals-8))))
} else {
amount = amount.Quo(amount, big.NewInt(int64(types.MultiplySpecifyTimes(1, 8-chain33ToEth.Decimals))))
}
txslog.Info("ParseBurnLockTxReceipt", "chain33Sender", chain33Sender, "ethereumReceiver", ethereumReceiver.String(), "tokenContractAddress", tokenContractAddress.String(), "symbol", symbol, "amount", amount.String())
// Package the event data into a Chain33Msg
chain33Msg := events.NewChain33Msg(claimType, chain33Sender, ethereumReceiver, symbol, amount, tokenContractAddress)
return &chain33Msg
}
}
return nil
}
// Chain33MsgToProphecyClaim : parses event data from a Chain33Msg, packaging it as a ProphecyClaim
func Chain33MsgToProphecyClaim(event events.Chain33Msg) ProphecyClaim {
claimType := event.ClaimType
chain33Sender := event.Chain33Sender
ethereumReceiver := event.EthereumReceiver
tokenContractAddress := event.TokenContractAddress
symbol := strings.ToLower(event.Symbol)
amount := event.Amount
prophecyClaim := ProphecyClaim{
ClaimType: claimType,
Chain33Sender: chain33Sender,
EthereumReceiver: ethereumReceiver,
TokenContractAddress: tokenContractAddress,
Symbol: symbol,
Amount: amount,
}
return prophecyClaim
}
package ethtxs
import (
"context"
"errors"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
)
func GetOperator(client ethinterface.EthClientSpec, sender, bridgeBank common.Address) (common.Address, error) {
header, err := client.HeaderByNumber(context.Background(), nil)
if err != nil {
txslog.Error("GetOperator", "Failed to get HeaderByNumber due to:", err.Error())
return common.Address{}, err
}
// Set up CallOpts auth
auth := bind.CallOpts{
Pending: true,
From: sender,
BlockNumber: header.Number,
Context: context.Background(),
}
// Initialize BridgeRegistry instance
bridgeBankInstance, err := generated.NewBridgeBank(bridgeBank, client)
if err != nil {
txslog.Error("GetOperator", "Failed to NewBridgeBank to:", err.Error())
return common.Address{}, err
}
return bridgeBankInstance.Operator(&auth)
}
func IsActiveValidator(validator common.Address, valset *generated.Valset) (bool, error) {
opts := &bind.CallOpts{
Pending: true,
From: validator,
Context: context.Background(),
}
// Initialize BridgeRegistry instance
isActiveValidator, err := valset.IsActiveValidator(opts, validator)
if err != nil {
txslog.Error("IsActiveValidator", "Failed to query IsActiveValidator due to:", err.Error())
return false, err
}
return isActiveValidator, nil
}
func IsProphecyPending(claimID [32]byte, validator common.Address, chain33Bridge *generated.Chain33Bridge) (bool, error) {
opts := &bind.CallOpts{
Pending: true,
From: validator,
Context: context.Background(),
}
// Initialize BridgeRegistry instance
active, err := chain33Bridge.IsProphecyClaimActive(opts, claimID)
if err != nil {
txslog.Error("IsActiveValidatorFromChain33Bridge", "Failed to query IsActiveValidator due to:", err.Error())
return false, err
}
return active, nil
}
func GetBalance(client ethinterface.EthClientSpec, tokenAddr, owner string) (string, error) {
//查询ERC20余额
if tokenAddr != "" {
bridgeToken, err := generated.NewBridgeToken(common.HexToAddress(tokenAddr), client)
if nil != err {
return "", err
}
ownerAddr := common.HexToAddress(owner)
opts := &bind.CallOpts{
Pending: true,
From: ownerAddr,
Context: context.Background(),
}
balance, err := bridgeToken.BalanceOf(opts, ownerAddr)
if nil != err {
return "", err
}
return balance.String(), nil
}
//查询ETH余额
balance, err := client.BalanceAt(context.Background(), common.HexToAddress(owner), nil)
if nil != err {
return "", err
}
return balance.String(), nil
}
func GetLockedFunds(bridgeBank *generated.BridgeBank, tokenAddrStr string) (string, error) {
var tokenAddr common.Address
if tokenAddrStr != "" {
tokenAddr = common.HexToAddress(tokenAddrStr)
}
opts := &bind.CallOpts{
Pending: true,
From: tokenAddr,
Context: context.Background(),
}
balance, err := bridgeBank.LockedFunds(opts, tokenAddr)
if nil != err {
return "", err
}
return balance.String(), nil
}
func GetDepositFunds(client bind.ContractBackend, tokenAddrStr string) (string, error) {
if tokenAddrStr == "" {
return "", errors.New("nil token address")
}
tokenAddr := common.HexToAddress(tokenAddrStr)
bridgeToken, err := generated.NewBridgeToken(tokenAddr, client)
if nil != err {
return "", err
}
opts := &bind.CallOpts{
Pending: true,
From: tokenAddr,
Context: context.Background(),
}
supply, err := bridgeToken.TotalSupply(opts)
if nil != err {
return "", err
}
return supply.String(), nil
}
func GetToken2address(bridgeBank *generated.BridgeBank, tokenSymbol string) (string, error) {
opts := &bind.CallOpts{
Pending: true,
Context: context.Background(),
}
tokenAddr, err := bridgeBank.GetToken2address(opts, tokenSymbol)
if nil != err {
return "", err
}
txslog.Info("GetToken2address", "Name", tokenSymbol, "Address", tokenAddr.String())
return tokenAddr.String(), nil
}
package ethtxs
import (
"errors"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/ethereum/go-ethereum/common"
)
func RecoverContractHandler(client ethinterface.EthClientSpec, sender, registry common.Address) (*X2EthContracts, *X2EthDeployInfo, error) {
bridgeBankAddr, err := GetAddressFromBridgeRegistry(client, sender, registry, BridgeBank)
if nil != err {
return nil, nil, errors.New("failed to get addr for bridgeBank from registry")
}
bridgeBank, err := generated.NewBridgeBank(*bridgeBankAddr, client)
if nil != err {
return nil, nil, errors.New("failed to NewBridgeBank")
}
chain33BridgeAddr, err := GetAddressFromBridgeRegistry(client, sender, registry, Chain33Bridge)
if nil != err {
return nil, nil, errors.New("failed to get addr for chain33BridgeAddr from registry")
}
chain33Bridge, err := generated.NewChain33Bridge(*chain33BridgeAddr, client)
if nil != err {
return nil, nil, errors.New("failed to NewChain33Bridge")
}
oracleAddr, err := GetAddressFromBridgeRegistry(client, sender, registry, Oracle)
if nil != err {
return nil, nil, errors.New("failed to get addr for oracleBridgeAddr from registry")
}
oracle, err := generated.NewOracle(*oracleAddr, client)
if nil != err {
return nil, nil, errors.New("failed to NewOracle")
}
valsetAddr, err := GetAddressFromBridgeRegistry(client, sender, registry, Valset)
if nil != err {
return nil, nil, errors.New("failed to get addr for valset from registry")
}
valset, err := generated.NewValset(*valsetAddr, client)
if nil != err {
return nil, nil, errors.New("failed to NewValset")
}
registryInstance, _ := generated.NewBridgeRegistry(registry, client)
x2EthContracts := &X2EthContracts{
BridgeRegistry: registryInstance,
BridgeBank: bridgeBank,
Chain33Bridge: chain33Bridge,
Oracle: oracle,
Valset: valset,
}
x2EthDeployInfo := &X2EthDeployInfo{
BridgeRegistry: &DeployResult{Address: registry},
BridgeBank: &DeployResult{Address: *bridgeBankAddr},
Chain33Bridge: &DeployResult{Address: *chain33BridgeAddr},
Oracle: &DeployResult{Address: *oracleAddr},
Valset: &DeployResult{Address: *valsetAddr},
}
return x2EthContracts, x2EthDeployInfo, nil
}
func RecoverOracleInstance(client ethinterface.EthClientSpec, sender, registry common.Address) (*generated.Oracle, error) {
oracleAddr, err := GetAddressFromBridgeRegistry(client, sender, registry, Oracle)
if nil != err {
return nil, errors.New("failed to get addr for oracleBridgeAddr from registry")
}
oracle, err := generated.NewOracle(*oracleAddr, client)
if nil != err {
return nil, errors.New("failed to NewOracle")
}
return oracle, nil
}
package ethtxs
import (
"context"
"log"
bridgeRegistry "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
ebrelayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
)
// ContractRegistry :
type ContractRegistry byte
const (
// Valset : valset contract
Valset ContractRegistry = iota + 1
// Oracle : oracle contract
Oracle
// BridgeBank : bridgeBank contract
BridgeBank
// Chain33Bridge : chain33Bridge contract
Chain33Bridge
)
// String : returns the event type as a string
func (d ContractRegistry) String() string {
return [...]string{"valset", "oracle", "bridgebank", "chain33bridge", "notsupport"}[d-1]
}
// GetAddressFromBridgeRegistry : utility method which queries the requested contract address from the BridgeRegistry
func GetAddressFromBridgeRegistry(client ethinterface.EthClientSpec, sender, registry common.Address, target ContractRegistry) (address *common.Address, err error) {
header, err := client.HeaderByNumber(context.Background(), nil)
if err != nil {
txslog.Error("GetAddressFromBridgeRegistry", "Failed to get HeaderByNumber due to:", err.Error())
return nil, err
}
// Set up CallOpts auth
auth := bind.CallOpts{
Pending: true,
From: sender,
BlockNumber: header.Number,
Context: context.Background(),
}
// Initialize BridgeRegistry instance
registryInstance, err := bridgeRegistry.NewBridgeRegistry(registry, client)
if err != nil {
txslog.Error("GetAddressFromBridgeRegistry", "Failed to NewBridgeRegistry to:", err.Error())
return nil, err
}
switch target {
case Valset:
valsetAddress, err := registryInstance.Valset(&auth)
if err != nil {
log.Fatal(err)
}
return &valsetAddress, nil
case Oracle:
oracleAddress, err := registryInstance.Oracle(&auth)
if err != nil {
log.Fatal(err)
}
return &oracleAddress, nil
case BridgeBank:
bridgeBankAddress, err := registryInstance.BridgeBank(&auth)
if err != nil {
log.Fatal(err)
}
return &bridgeBankAddress, nil
case Chain33Bridge:
chain33BridgeAddress, err := registryInstance.Chain33Bridge(&auth)
if err != nil {
log.Fatal(err)
}
return &chain33BridgeAddress, nil
default:
txslog.Error("GetAddressFromBridgeRegistry", "invalid target contract type:", target)
return nil, ebrelayerTypes.ErrInvalidContractAddress
}
}
// GetDeployHeight : 获取合约部署高度
func GetDeployHeight(client ethinterface.EthClientSpec, sender, registry common.Address) (height int64, err error) {
header, err := client.HeaderByNumber(context.Background(), nil)
if err != nil {
txslog.Error("GetAddressFromBridgeRegistry", "Failed to get HeaderByNumber due to:", err.Error())
return 0, err
}
// Set up CallOpts auth
callOpts := &bind.CallOpts{
Pending: true,
From: sender,
BlockNumber: header.Number,
Context: context.Background(),
}
// Initialize BridgeRegistry instance
registryInstance, err := bridgeRegistry.NewBridgeRegistry(registry, client)
if err != nil {
txslog.Error("GetAddressFromBridgeRegistry", "Failed to NewBridgeRegistry to:", err.Error())
return 0, err
}
bgInt, err := registryInstance.DeployHeight(callOpts)
if nil != err {
return 0, err
}
height = bgInt.Int64()
txslog.Info("GetDeployHeight", "deploy height:", height)
return
}
package ethtxs
// ------------------------------------------------------------
// Relay : Builds and encodes EthBridgeClaim Msgs with the
// specified variables, before presenting the unsigned
// transaction to validators for optional signing.
// Once signed, the data packets are sent as transactions
// on the chain33 Bridge.
// ------------------------------------------------------------
import (
"github.com/33cn/chain33/common"
chain33Crypto "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
chain33Types "github.com/33cn/chain33/types"
ebrelayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
// RelayLockToChain33 : RelayLockToChain33 applies validator's signature to an EthBridgeClaim message
// containing information about an event on the Ethereum blockchain before relaying to the Bridge
func RelayLockToChain33(privateKey chain33Crypto.PrivKey, claim *ebrelayerTypes.EthBridgeClaim, rpcURL string) (string, error) {
var res string
params := &types.Eth2Chain33{
EthereumChainID: claim.EthereumChainID,
BridgeContractAddress: claim.BridgeBrankAddr,
Nonce: claim.Nonce,
IssuerDotSymbol: claim.Symbol,
TokenContractAddress: claim.TokenAddr,
EthereumSender: claim.EthereumSender,
Chain33Receiver: claim.Chain33Receiver,
Amount: claim.Amount,
ClaimType: int64(claim.ClaimType),
Decimals: claim.Decimal,
}
pm := rpctypes.CreateTxIn{
Execer: X2Eth,
ActionName: types.NameEth2Chain33Action,
Payload: chain33Types.MustPBToJSON(params),
}
ctx := jsonclient.NewRPCCtx(rpcURL, "Chain33.CreateTransaction", pm, &res)
_, _ = ctx.RunResult()
data, err := common.FromHex(res)
if err != nil {
return "", err
}
var tx chain33Types.Transaction
err = chain33Types.Decode(data, &tx)
if err != nil {
return "", err
}
if tx.Fee == 0 {
tx.Fee, err = tx.GetRealFee(1e5)
if err != nil {
return "", err
}
}
//构建交易,验证人validator用来向chain33合约证明自己验证了该笔从以太坊向chain33跨链转账的交易
tx.Sign(chain33Types.SECP256K1, privateKey)
txData := chain33Types.Encode(&tx)
dataStr := common.ToHex(txData)
pms := rpctypes.RawParm{
Token: "BTY",
Data: dataStr,
}
var txhash string
ctx = jsonclient.NewRPCCtx(rpcURL, "Chain33.SendTransaction", pms, &txhash)
_, err = ctx.RunResult()
return txhash, err
}
func RelayBurnToChain33(privateKey chain33Crypto.PrivKey, claim *ebrelayerTypes.EthBridgeClaim, rpcURL string) (string, error) {
var res string
params := &types.Eth2Chain33{
EthereumChainID: claim.EthereumChainID,
BridgeContractAddress: claim.BridgeBrankAddr,
Nonce: claim.Nonce,
IssuerDotSymbol: claim.Symbol,
TokenContractAddress: claim.TokenAddr,
EthereumSender: claim.EthereumSender,
Chain33Receiver: claim.Chain33Receiver,
Amount: claim.Amount,
ClaimType: int64(claim.ClaimType),
Decimals: claim.Decimal,
}
pm := rpctypes.CreateTxIn{
Execer: X2Eth,
ActionName: types.NameWithdrawEthAction,
Payload: chain33Types.MustPBToJSON(params),
}
ctx := jsonclient.NewRPCCtx(rpcURL, "Chain33.CreateTransaction", pm, &res)
_, _ = ctx.RunResult()
data, err := common.FromHex(res)
if err != nil {
return "", err
}
var tx chain33Types.Transaction
err = chain33Types.Decode(data, &tx)
if err != nil {
return "", err
}
if tx.Fee == 0 {
tx.Fee, err = tx.GetRealFee(1e5)
if err != nil {
return "", err
}
}
//构建交易,验证人validator用来向chain33合约证明自己验证了该笔从以太坊向chain33跨链转账的交易
tx.Sign(chain33Types.SECP256K1, privateKey)
txData := chain33Types.Encode(&tx)
dataStr := common.ToHex(txData)
pms := rpctypes.RawParm{
Token: "BTY",
Data: dataStr,
}
var txhash string
ctx = jsonclient.NewRPCCtx(rpcURL, "Chain33.SendTransaction", pms, &txhash)
_, err = ctx.RunResult()
return txhash, err
}
package ethtxs
import (
"fmt"
"testing"
"github.com/33cn/chain33/client/mocks"
chain33Common "github.com/33cn/chain33/common"
_ "github.com/33cn/chain33/system"
"github.com/33cn/chain33/system/crypto/secp256k1"
chain33Types "github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/testnode"
ebrelayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
var (
chainTestCfg = chain33Types.NewChain33Config(chain33Types.GetDefaultCfgstring())
)
func Test_RelayToChain33(t *testing.T) {
var tx chain33Types.Transaction
var ret chain33Types.Reply
ret.IsOk = true
mockapi := &mocks.QueueProtocolAPI{}
// 这里对需要mock的方法打桩,Close是必须的,其它方法根据需要
mockapi.On("Close").Return()
mockapi.On("AddPushSubscribe", mock.Anything).Return(&ret, nil)
mockapi.On("CreateTransaction", mock.Anything).Return(&tx, nil)
mockapi.On("SendTx", mock.Anything).Return(&ret, nil)
mockapi.On("SendTransaction", mock.Anything).Return(&ret, nil)
mockapi.On("GetConfig", mock.Anything).Return(chainTestCfg, nil)
mock33 := testnode.New("", mockapi)
defer mock33.Close()
rpcCfg := mock33.GetCfg().RPC
// 这里必须设置监听端口,默认的是无效值
rpcCfg.JrpcBindAddr = "127.0.0.1:8801"
mock33.GetRPC().Listen()
chain33PrivateKeyStr := "0xd627968e445f2a41c92173225791bae1ba42126ae96c32f28f97ff8f226e5c68"
var driver secp256k1.Driver
privateKeySli, err := chain33Common.FromHex(chain33PrivateKeyStr)
require.Nil(t, err)
priKey, err := driver.PrivKeyFromBytes(privateKeySli)
require.Nil(t, err)
claim := &ebrelayerTypes.EthBridgeClaim{}
fmt.Println("======================= testRelayLockToChain33 =======================")
_, err = RelayLockToChain33(priKey, claim, "http://127.0.0.1:8801")
require.Nil(t, err)
fmt.Println("======================= testRelayBurnToChain33 =======================")
_, err = RelayBurnToChain33(priKey, claim, "http://127.0.0.1:8801")
require.Nil(t, err)
}
package ethtxs
import (
"crypto/ecdsa"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
)
var (
txslog = log15.New("ethereum relayer", "ethtxs")
)
const (
// GasLimit : the gas limit in Gwei used for transactions sent with TransactOpts
GasLimit = uint64(100 * 10000)
GasLimit4Deploy = uint64(0) //此处需要设置为0,让交易自行估计,否则将会导致部署失败,TODO:其他解决途径后续调研解决
)
// RelayOracleClaimToEthereum : relays the provided burn or lock to Chain33Bridge contract on the Ethereum network
func RelayOracleClaimToEthereum(oracleInstance *generated.Oracle, client ethinterface.EthClientSpec, sender common.Address, event events.Event, claim ProphecyClaim, privateKey *ecdsa.PrivateKey, chain33TxHash []byte) (txhash string, err error) {
txslog.Info("RelayProphecyClaimToEthereum", "sender", sender.String(), "event", event, "chain33Sender", hexutil.Encode(claim.Chain33Sender), "ethereumReceiver", claim.EthereumReceiver.String(), "TokenAddress", claim.TokenContractAddress.String(), "symbol", claim.Symbol, "Amount", claim.Amount.String(), "claimType", claim.ClaimType.String())
auth, err := PrepareAuth(client, privateKey, sender)
if nil != err {
txslog.Error("RelayProphecyClaimToEthereum", "PrepareAuth err", err.Error())
return "", err
}
auth.GasLimit = GasLimit
claimID := crypto.Keccak256Hash(chain33TxHash, claim.Chain33Sender, claim.EthereumReceiver.Bytes(), []byte(claim.Symbol), claim.Amount.Bytes())
// Sign the hash using the active validator's private key
signature, err := SignClaim4Eth(claimID, privateKey)
if nil != err {
return "", err
}
tx, err := oracleInstance.NewOracleClaim(auth, uint8(claim.ClaimType), claim.Chain33Sender, claim.EthereumReceiver, claim.TokenContractAddress, claim.Symbol, claim.Amount, claimID, signature)
if nil != err {
txslog.Error("RelayProphecyClaimToEthereum", "NewOracleClaim failed due to:", err.Error())
return "", err
}
txhash = tx.Hash().Hex()
txslog.Info("RelayProphecyClaimToEthereum", "NewOracleClaim tx hash:", txhash)
return txhash, nil
}
package ethtxs
import (
"math/big"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
"github.com/ethereum/go-ethereum/common"
)
const (
X2Eth = "x2ethereum"
BurnAction = "Chain33ToEthBurn"
LockAction = "Chain33ToEthLock"
)
// OracleClaim : contains data required to make an OracleClaim
type OracleClaim struct {
ProphecyID *big.Int
Message [32]byte
Signature []byte
}
// ProphecyClaim : contains data required to make an ProphecyClaim
type ProphecyClaim struct {
ClaimType events.Event
Chain33Sender []byte
EthereumReceiver common.Address
TokenContractAddress common.Address
Symbol string
Amount *big.Int
}
package ethtxs
import (
"context"
"crypto/ecdsa"
"errors"
"math/big"
"sync"
"time"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
solsha3 "github.com/miguelmota/go-solidity-sha3"
)
type EthTxStatus int32
type nonceMutex struct {
nonce int64
rw *sync.RWMutex
}
var addr2Nonce = make(map[common.Address]nonceMutex)
func (ethTxStatus EthTxStatus) String() string {
return [...]string{"Fail", "Success", "Pending"}[ethTxStatus]
}
const (
PendingDuration4TxExeuction = 300
EthTxPending = EthTxStatus(2)
)
func SignClaim4Eth(hash common.Hash, privateKey *ecdsa.PrivateKey) ([]byte, error) {
rawSignature, _ := prefixMessage(hash, privateKey)
signature := hexutil.Bytes(rawSignature)
return signature, nil
}
func prefixMessage(message common.Hash, key *ecdsa.PrivateKey) ([]byte, []byte) {
prefixed := solsha3.SoliditySHA3WithPrefix(message[:])
sig, err := secp256k1.Sign(prefixed, math.PaddedBigBytes(key.D, 32))
if err != nil {
panic(err)
}
return sig, prefixed
}
func getNonce(sender common.Address, client ethinterface.EthClientSpec) (*big.Int, error) {
if nonceMutex, exist := addr2Nonce[sender]; exist {
nonceMutex.rw.Lock()
defer nonceMutex.rw.Unlock()
nonceMutex.nonce++
addr2Nonce[sender] = nonceMutex
txslog.Debug("getNonce from cache", "address", sender.String(), "nonce", nonceMutex.nonce)
return big.NewInt(nonceMutex.nonce), nil
}
nonce, err := client.PendingNonceAt(context.Background(), sender)
if nil != err {
return nil, err
}
txslog.Debug("getNonce", "address", sender.String(), "nonce", nonce)
n := new(nonceMutex)
n.nonce = int64(nonce)
n.rw = new(sync.RWMutex)
addr2Nonce[sender] = *n
return big.NewInt(int64(nonce)), nil
}
func revokeNonce(sender common.Address) (*big.Int, error) {
if nonceMutex, exist := addr2Nonce[sender]; exist {
nonceMutex.rw.Lock()
defer nonceMutex.rw.Unlock()
nonceMutex.nonce--
addr2Nonce[sender] = nonceMutex
txslog.Debug("revokeNonce", "address", sender.String(), "nonce", nonceMutex.nonce)
return big.NewInt(nonceMutex.nonce), nil
}
return nil, errors.New("address doesn't exist tx")
}
func PrepareAuth(client ethinterface.EthClientSpec, privateKey *ecdsa.PrivateKey, transactor common.Address) (*bind.TransactOpts, error) {
if nil == privateKey || nil == client {
txslog.Error("PrepareAuth", "nil input parameter", "client", client, "privateKey", privateKey)
return nil, errors.New("nil input parameter")
}
ctx := context.Background()
gasPrice, err := client.SuggestGasPrice(ctx)
if err != nil {
txslog.Error("PrepareAuth", "Failed to SuggestGasPrice due to:", err.Error())
return nil, errors.New("failed to get suggest gas price")
}
auth := bind.NewKeyedTransactor(privateKey)
auth.Value = big.NewInt(0) // in wei
auth.GasLimit = GasLimit4Deploy
auth.GasPrice = gasPrice
if auth.Nonce, err = getNonce(transactor, client); err != nil {
return nil, err
}
return auth, nil
}
func waitEthTxFinished(client ethinterface.EthClientSpec, txhash common.Hash, txName string) error {
txslog.Info(txName, "Wait for tx to be finished executing with hash", txhash.String())
timeout := time.NewTimer(PendingDuration4TxExeuction * time.Second)
oneSecondtimeout := time.NewTicker(5 * time.Second)
for {
select {
case <-timeout.C:
return errors.New("eth tx timeout")
case <-oneSecondtimeout.C:
_, err := client.TransactionReceipt(context.Background(), txhash)
if err == ethereum.NotFound {
continue
} else if err != nil {
return err
}
txslog.Info(txName, "Finished executing for tx", txhash.String())
return nil
}
}
}
func GetEthTxStatus(client ethinterface.EthClientSpec, txhash common.Hash) string {
receipt, err := client.TransactionReceipt(context.Background(), txhash)
if nil != err {
return EthTxPending.String()
}
status := EthTxStatus(receipt.Status).String()
if status != EthTxPending.String() {
txslog.Info("GetEthTxStatus", "Eth tx hash", txhash.String(), "status", status, "BlockNum", receipt.BlockNumber.Int64())
}
return status
}
package events
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
)
// Chain33Msg : contains data from MsgBurn and MsgLock events
type Chain33Msg struct {
ClaimType Event
Chain33Sender []byte
EthereumReceiver common.Address
TokenContractAddress common.Address
Symbol string
Amount *big.Int
}
// NewChain33Msg : creates a new Chain33Msg
func NewChain33Msg(
claimType Event,
chain33Sender []byte,
ethereumReceiver common.Address,
symbol string,
amount *big.Int,
tokenContractAddress common.Address,
) Chain33Msg {
// Package data into a Chain33Msg
chain33Msg := Chain33Msg{
ClaimType: claimType,
Chain33Sender: chain33Sender,
EthereumReceiver: ethereumReceiver,
Symbol: symbol,
Amount: amount,
TokenContractAddress: tokenContractAddress,
}
return chain33Msg
}
package events
// -----------------------------------------------------
// ethereumEvent : Creates LockEvents from new events on the
// Ethereum blockchain.
// -----------------------------------------------------
import (
"math/big"
ebrelayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
)
// LockEvent : struct which represents a LogLock event
type LockEvent struct {
From common.Address
To []byte
Token common.Address
Symbol string
Value *big.Int
Nonce *big.Int
}
// BurnEvent : struct which represents a BurnEvent event
type BurnEvent struct {
Token common.Address
Symbol string
Amount *big.Int
OwnerFrom common.Address
Chain33Receiver []byte
Nonce *big.Int
}
// NewProphecyClaimEvent : struct which represents a LogNewProphecyClaim event
type NewProphecyClaimEvent struct {
ProphecyID *big.Int
ClaimType uint8
Chain33Sender []byte
EthereumReceiver common.Address
ValidatorAddress common.Address
TokenAddress common.Address
Symbol string
Amount *big.Int
}
type LogNewBridgeToken struct {
Token common.Address
Symbol string
}
// UnpackLogLock : Handles new LogLock events
func UnpackLogLock(contractAbi abi.ABI, eventName string, eventData []byte) (lockEvent *LockEvent, err error) {
event := &LockEvent{}
// Parse the event's attributes as Ethereum network variables
err = contractAbi.Unpack(event, eventName, eventData)
if err != nil {
eventsLog.Error("UnpackLogLock", "Failed to unpack abi due to:", err.Error())
return nil, ebrelayerTypes.ErrUnpack
}
eventsLog.Info("UnpackLogLock", "value", event.Value.String(), "symbol", event.Symbol,
"token addr", event.Token.Hex(), "sender", event.From.Hex(),
"recipient", string(event.To), "nonce", event.Nonce.String())
return event, nil
}
func UnpackLogBurn(contractAbi abi.ABI, eventName string, eventData []byte) (burnEvent *BurnEvent, err error) {
event := &BurnEvent{}
// Parse the event's attributes as Ethereum network variables
err = contractAbi.Unpack(event, eventName, eventData)
if err != nil {
eventsLog.Error("UnpackLogBurn", "Failed to unpack abi due to:", err.Error())
return nil, ebrelayerTypes.ErrUnpack
}
eventsLog.Info("UnpackLogBurn", "token addr", event.Token.Hex(), "symbol", event.Symbol,
"Amount", event.Amount.String(), "OwnerFrom", event.OwnerFrom.String(),
"Chain33Receiver", string(event.Chain33Receiver), "nonce", event.Nonce.String())
return event, nil
}
package events
// -----------------------------------------------------
// Events: Events maintains a mapping of events to an array
// of claims made by validators.
// -----------------------------------------------------
// EventRecords : map of transaction hashes to LockEvent structs
var EventRecords = make(map[string]LockEvent)
// NewEventWrite : add a validator's address to the official claims list
func NewEventWrite(txHash string, event LockEvent) {
EventRecords[txHash] = event
}
package events
import (
log "github.com/33cn/chain33/common/log/log15"
)
// Event : enum containing supported contract events
type Event int
var eventsLog = log.New("module", "ethereum_relayer")
const (
// Unsupported : unsupported Chain33 or Ethereum event
Unsupported Event = iota
// MsgBurn : Chain33 event 'Chain33Msg' type MsgBurn
MsgBurn
// MsgLock : Chain33 event 'Chain33Msg' type MsgLock
MsgLock
// LogLock : Ethereum event 'LockEvent'
LogLock
// LogChain33TokenBurn : Ethereum event 'LogChain33TokenBurn' in contract chain33Bank
LogChain33TokenBurn
// LogNewProphecyClaim : Ethereum event 'NewProphecyClaimEvent'
LogNewProphecyClaim
)
const (
ClaimTypeBurn = uint8(1)
ClaimTypeLock = uint8(2)
)
// String : returns the event type as a string
func (d Event) String() string {
return [...]string{"unknown-x2ethereum", "Chain33ToEthBurn", "Chain33ToEthLock", "LogLock", "LogChain33TokenBurn", "LogNewProphecyClaim"}[d]
}
// Chain33MsgAttributeKey : enum containing supported attribute keys
type Chain33MsgAttributeKey int
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]
}
package events
import (
"math/big"
"strings"
"testing"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func Test_UnpackLogLock(t *testing.T) {
abiJSON := generated.BridgeBankABI
contractABI, err := abi.JSON(strings.NewReader(abiJSON))
require.Nil(t, err)
eventName := LogLock.String()
eventData := []byte("nil")
_, err = UnpackLogLock(contractABI, eventName, eventData)
require.NotNil(t, err)
_, err = UnpackLogBurn(contractABI, eventName, eventData)
require.NotNil(t, err)
}
func Test_NewEventWrite(t *testing.T) {
event := LockEvent{
Symbol: "bty",
}
NewEventWrite("1", event)
assert.Equal(t, EventRecords["1"].Symbol, "bty")
}
func Test_NewChain33Msg(t *testing.T) {
_ = NewChain33Msg(MsgBurn, []byte("12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"), common.HexToAddress("0x0C05bA5c230fDaA503b53702aF1962e08D0C60BF"),
"eth", big.NewInt(100000000000000000), common.HexToAddress("0x0000000000000000000000000000000000000000"))
}
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")
}
package main
import (
"context"
"flag"
"fmt"
"io"
"net"
"net/http"
"net/rpc"
"net/rpc/jsonrpc"
"os"
"os/signal"
"path/filepath"
"sync"
"syscall"
dbm "github.com/33cn/chain33/common/db"
logf "github.com/33cn/chain33/common/log"
"github.com/33cn/chain33/common/log/log15"
chain33Types "github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/relayer"
chain33Relayer "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/relayer/chain33"
ethRelayer "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/relayer/ethereum"
relayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
tml "github.com/BurntSushi/toml"
"github.com/btcsuite/btcd/limits"
"github.com/prometheus/common/log"
)
var (
configPath = flag.String("f", "", "configfile")
versionCmd = flag.Bool("s", false, "version")
IPWhiteListMap = make(map[string]bool)
mainlog = log15.New("relayer manager", "main")
)
func main() {
flag.Parse()
if *versionCmd {
fmt.Println(relayerTypes.Version4Relayer)
return
}
if *configPath == "" {
*configPath = "relayer.toml"
}
err := os.Chdir(pwd())
if err != nil {
panic(err)
}
d, err := os.Getwd()
if err != nil {
panic(err)
}
log.Info("current dir:", "dir", d)
err = limits.SetLimits()
if err != nil {
panic(err)
}
cfg := initCfg(*configPath)
log.Info("Starting FUZAMEI Chain33-X-Ethereum relayer software:", "\n Name: ", cfg.Title)
logf.SetFileLog(convertLogCfg(cfg.Log))
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
log.Info("db info:", " Dbdriver = ", cfg.SyncTxConfig.Dbdriver, ", DbPath = ", cfg.SyncTxConfig.DbPath, ", DbCache = ", cfg.SyncTxConfig.DbCache)
log.Info("deploy info:", "BridgeRegistry", cfg.BridgeRegistry)
mainlog.Info("db info:", " Dbdriver = ", cfg.SyncTxConfig.Dbdriver, ", DbPath = ", cfg.SyncTxConfig.DbPath, ", DbCache = ", cfg.SyncTxConfig.DbCache)
db := dbm.NewDB("relayer_db_service", cfg.SyncTxConfig.Dbdriver, cfg.SyncTxConfig.DbPath, cfg.SyncTxConfig.DbCache)
chain33RelayerService := chain33Relayer.StartChain33Relayer(ctx, cfg.SyncTxConfig, cfg.BridgeRegistry, cfg.EthProvider, db)
ethRelayerService := ethRelayer.StartEthereumRelayer(cfg.SyncTxConfig.Chain33Host, db, cfg.EthProvider, cfg.BridgeRegistry, cfg.Deploy, cfg.EthMaturityDegree, cfg.EthBlockFetchPeriod)
relayerManager := relayer.NewRelayerManager(chain33RelayerService, ethRelayerService, db)
log.Info("cfg.JrpcBindAddr = ", cfg.JrpcBindAddr)
startRPCServer(cfg.JrpcBindAddr, relayerManager)
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM)
go func() {
<-ch
cancel()
wg.Wait()
os.Exit(0)
}()
}
func convertLogCfg(log *relayerTypes.Log) *chain33Types.Log {
return &chain33Types.Log{
Loglevel: log.Loglevel,
LogConsoleLevel: log.LogConsoleLevel,
LogFile: log.LogFile,
MaxFileSize: log.MaxFileSize,
MaxBackups: log.MaxBackups,
MaxAge: log.MaxAge,
LocalTime: log.LocalTime,
Compress: log.Compress,
CallerFile: log.CallerFile,
CallerFunction: log.CallerFunction,
}
}
func pwd() string {
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
panic(err)
}
return dir
}
func initCfg(path string) *relayerTypes.RelayerConfig {
var cfg relayerTypes.RelayerConfig
if _, err := tml.DecodeFile(path, &cfg); err != nil {
fmt.Println(err)
os.Exit(-1)
}
//fmt.Println(cfg)
return &cfg
}
func IsIPWhiteListEmpty() bool {
return len(IPWhiteListMap) == 0
}
//判断ipAddr是否在ip地址白名单中
func IsInIPWhitelist(ipAddrPort string) bool {
ipAddr, _, err := net.SplitHostPort(ipAddrPort)
if err != nil {
return false
}
ip := net.ParseIP(ipAddr)
if ip.IsLoopback() {
return true
}
if _, ok := IPWhiteListMap[ipAddr]; ok {
return true
}
return false
}
type RPCServer struct {
*rpc.Server
}
func (r *RPCServer) ServeHTTP(w http.ResponseWriter, req *http.Request) {
log.Info("ServeHTTP", "request address", req.RemoteAddr)
if !IsIPWhiteListEmpty() {
if !IsInIPWhitelist(req.RemoteAddr) {
log.Info("ServeHTTP", "refuse connect address", req.RemoteAddr)
w.WriteHeader(401)
return
}
}
r.Server.ServeHTTP(w, req)
}
func (r *RPCServer) HandleHTTP(rpcPath, debugPath string) {
http.Handle(rpcPath, r)
}
type HTTPConn struct {
in io.Reader
out io.Writer
}
func (c *HTTPConn) Read(p []byte) (n int, err error) { return c.in.Read(p) }
func (c *HTTPConn) Write(d []byte) (n int, err error) { return c.out.Write(d) }
func (c *HTTPConn) Close() error { return nil }
func startRPCServer(address string, api interface{}) {
listener, err := net.Listen("tcp", address)
if err != nil {
fmt.Println("监听失败,端口可能已经被占用")
panic(err)
}
srv := &RPCServer{rpc.NewServer()}
_ = srv.Server.Register(api)
srv.HandleHTTP(rpc.DefaultRPCPath, rpc.DefaultDebugPath)
var handler http.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
serverCodec := jsonrpc.NewServerCodec(&HTTPConn{in: r.Body, out: w})
w.Header().Set("Content-type", "application/json")
w.WriteHeader(200)
err := srv.ServeRequest(serverCodec)
if err != nil {
log.Debug("http", "Error while serving JSON request: %v", err)
return
}
}
})
_ = http.Serve(listener, handler)
}
# 本配置文件专门用于33复杂美闪电网络使用,即lns33
title="x2Ethereum_relayer"
#用于cli向该relayer进行配置
JrpcBindAddr="localhost:9901"
EthProvider="ws://127.0.0.1:7545/"
#EthProvider="wss://rinkeby.infura.io/ws/v3/404eb4acc421426ebeb6e92c7ce9a270"
#EthProvider="wss://ropsten.infura.io/ws/v3/404eb4acc421426ebeb6e92c7ce9a270"
EthMaturityDegree=10
EthBlockFetchPeriod=5000
#BridgeRegistry="0x5331F912027057fBE8139D91B225246e8159232f"
[SyncTxConfig]
chain33Host="http://172.18.0.7:8801"
pushHost="http://192.168.0.125:20000"
pushName="x2ethereum"
pushBind="0.0.0.0:20000"
maturityDegree=10
dbdriver="leveldb"
dbPath="datadir"
dbCache=64
fetchHeightPeriodMs=5000
#如果需要配置起始的块的信息,则为了保持一致性,三项缺一不可,或者都不配置
#startSyncHeight=24531
#startSyncSequence=24531
#startSyncHash="0xb96168940ceebc12dcf4a4911ec8f509344f5c8591af37a49f4fb5f433093d2e"
startSyncHeight=0
startSyncSequence=0
startSyncHash=""
[deploy]
#合约部署人员私钥,用于部署合约时签名使用
operatorAddr="0x8afdadfc88a1087c9a1d6c0f5dd04634b87f303a"
#合约部署人员私钥,用于部署合约时签名使用
deployerPrivateKey="8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
#验证人地址,至少配置3个以上,即大于等于3个
validatorsAddr=["0x92c8b16afd6d423652559c6e266cbe1c29bfd84f", "0x0df9a824699bc5878232c9e612fe1a5346a5a368", "0xcb074cb21cdddf3ce9c3c0a7ac4497d633c9d9f1", "0xd9dab021e74ecf475788ed7b61356056b2095830"]
#验证人权重
initPowers=[25, 25, 25, 25]
[log]
# 日志级别,支持debug(dbug)/info/warn/error(eror)/crit
loglevel = "debug"
logConsoleLevel = "debug"
# 日志文件名,可带目录,所有生成的日志文件都放到此目录下
logFile = "logs/x2Ethereum_relayer.log"
# 单个日志文件的最大值(单位:兆)
maxFileSize = 300
# 最多保存的历史日志文件个数
maxBackups = 100
# 最多保存的历史日志消息(单位:天)
maxAge = 28
# 日志文件名是否使用本地事件(否则使用UTC时间)
localTime = true
# 历史日志文件是否压缩(压缩格式为gz)
compress = true
# 是否打印调用源文件和行号
callerFile = false
# 是否打印调用方法
callerFunction = false
\ No newline at end of file
package chain33
import (
chain33Common "github.com/33cn/chain33/common"
"github.com/ethereum/go-ethereum/crypto"
//dbm "github.com/33cn/chain33/common/db"
chain33Types "github.com/33cn/chain33/types"
wcom "github.com/33cn/chain33/wallet/common"
x2ethTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
)
var (
chain33AccountKey = []byte("Chain33Account4Relayer")
start = int(1)
)
func (chain33Relayer *Relayer4Chain33) GetAccount(passphrase string) (privateKey, addr string, err error) {
accountInfo, err := chain33Relayer.db.Get(chain33AccountKey)
if nil != err {
return "", "", err
}
ethAccount := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, ethAccount); nil != err {
return "", "", err
}
decryptered := wcom.CBCDecrypterPrivkey([]byte(passphrase), ethAccount.Privkey)
privateKey = chain33Common.ToHex(decryptered)
addr = ethAccount.Addr
return
}
func (chain33Relayer *Relayer4Chain33) GetAccountAddr() (addr string, err error) {
accountInfo, err := chain33Relayer.db.Get(chain33AccountKey)
if nil != err {
relayerLog.Info("GetValidatorAddr", "Failed to get account from db due to:", err.Error())
return "", err
}
ethAccount := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, ethAccount); nil != err {
relayerLog.Info("GetValidatorAddr", "Failed to decode due to:", err.Error())
return "", err
}
addr = ethAccount.Addr
return
}
func (chain33Relayer *Relayer4Chain33) ImportPrivateKey(passphrase, privateKeyStr string) (addr string, err error) {
privateKeySlice, err := chain33Common.FromHex(privateKeyStr)
if nil != err {
return "", err
}
privateKey, err := crypto.ToECDSA(privateKeySlice)
if nil != err {
return "", err
}
ethSender := crypto.PubkeyToAddress(privateKey.PublicKey)
chain33Relayer.privateKey4Ethereum = privateKey
chain33Relayer.ethSender = ethSender
chain33Relayer.unlock <- start
addr = chain33Common.ToHex(ethSender.Bytes())
encryptered := wcom.CBCEncrypterPrivkey([]byte(passphrase), privateKeySlice)
ethAccount := &x2ethTypes.Account4Relayer{
Privkey: encryptered,
Addr: addr,
}
encodedInfo := chain33Types.Encode(ethAccount)
err = chain33Relayer.db.SetSync(chain33AccountKey, encodedInfo)
return
}
func (chain33Relayer *Relayer4Chain33) StoreAccountWithNewPassphase(newPassphrase, oldPassphrase string) error {
accountInfo, err := chain33Relayer.db.Get(chain33AccountKey)
if nil != err {
relayerLog.Info("StoreAccountWithNewPassphase", "pls check account is created already, err", err)
return err
}
ethAccount := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, ethAccount); nil != err {
return err
}
decryptered := wcom.CBCDecrypterPrivkey([]byte(oldPassphrase), ethAccount.Privkey)
encryptered := wcom.CBCEncrypterPrivkey([]byte(newPassphrase), decryptered)
ethAccount.Privkey = encryptered
encodedInfo := chain33Types.Encode(ethAccount)
return chain33Relayer.db.SetSync(chain33AccountKey, encodedInfo)
}
func (chain33Relayer *Relayer4Chain33) RestorePrivateKeys(passphrase string) error {
accountInfo, err := chain33Relayer.db.Get(chain33AccountKey)
if nil != err {
relayerLog.Info("No private key saved for Relayer4Chain33")
return nil
}
ethAccount := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, ethAccount); nil != err {
relayerLog.Info("RestorePrivateKeys", "Failed to decode due to:", err.Error())
return err
}
decryptered := wcom.CBCDecrypterPrivkey([]byte(passphrase), ethAccount.Privkey)
privateKey, err := crypto.ToECDSA(decryptered)
if nil != err {
relayerLog.Info("RestorePrivateKeys", "Failed to ToECDSA:", err.Error())
return err
}
chain33Relayer.rwLock.Lock()
chain33Relayer.privateKey4Ethereum = privateKey
chain33Relayer.ethSender = crypto.PubkeyToAddress(privateKey.PublicKey)
chain33Relayer.rwLock.Unlock()
chain33Relayer.unlock <- start
return nil
}
//func (chain33Relayer *Relayer4Chain33) UpdatePrivateKey(Passphrase, privateKey string) error {
// return nil
//}
package chain33
import (
"bytes"
"context"
"crypto/ecdsa"
"errors"
"fmt"
"os"
"sync"
"sync/atomic"
"time"
dbm "github.com/33cn/chain33/common/db"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/rpc/jsonclient"
rpctypes "github.com/33cn/chain33/rpc/types"
chain33Types "github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
relayerTx "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethtxs"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
syncTx "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/relayer/chain33/transceiver/sync"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
ethCommon "github.com/ethereum/go-ethereum/common"
)
var relayerLog = log.New("module", "chain33_relayer")
type Relayer4Chain33 struct {
syncTxReceipts *syncTx.TxReceipts
ethClient ethinterface.EthClientSpec
rpcLaddr string //用户向指定的blockchain节点进行rpc调用
fetchHeightPeriodMs int64
db dbm.DB
lastHeight4Tx int64 //等待被处理的具有相应的交易回执的高度
matDegree int32 //成熟度 heightSync2App matDegress height
//passphase string
privateKey4Ethereum *ecdsa.PrivateKey
ethSender ethCommon.Address
bridgeRegistryAddr ethCommon.Address
oracleInstance *generated.Oracle
totalTx4Chain33ToEth int64
statusCheckedIndex int64
ctx context.Context
rwLock sync.RWMutex
unlock chan int
}
// StartChain33Relayer : initializes a relayer which witnesses events on the chain33 network and relays them to Ethereum
func StartChain33Relayer(ctx context.Context, syncTxConfig *ebTypes.SyncTxConfig, registryAddr, provider string, db dbm.DB) *Relayer4Chain33 {
chian33Relayer := &Relayer4Chain33{
rpcLaddr: syncTxConfig.Chain33Host,
fetchHeightPeriodMs: syncTxConfig.FetchHeightPeriodMs,
unlock: make(chan int),
db: db,
ctx: ctx,
bridgeRegistryAddr: ethCommon.HexToAddress(registryAddr),
}
syncCfg := &ebTypes.SyncTxReceiptConfig{
Chain33Host: syncTxConfig.Chain33Host,
PushHost: syncTxConfig.PushHost,
PushName: syncTxConfig.PushName,
PushBind: syncTxConfig.PushBind,
StartSyncHeight: syncTxConfig.StartSyncHeight,
StartSyncSequence: syncTxConfig.StartSyncSequence,
StartSyncHash: syncTxConfig.StartSyncHash,
}
client, err := relayerTx.SetupWebsocketEthClient(provider)
if err != nil {
panic(err)
}
chian33Relayer.ethClient = client
chian33Relayer.totalTx4Chain33ToEth = chian33Relayer.getTotalTxAmount2Eth()
chian33Relayer.statusCheckedIndex = chian33Relayer.getStatusCheckedIndex()
go chian33Relayer.syncProc(syncCfg)
return chian33Relayer
}
func (chain33Relayer *Relayer4Chain33) QueryTxhashRelay2Eth() ebTypes.Txhashes {
txhashs := utils.QueryTxhashes([]byte(chain33ToEthBurnLockTxHashPrefix), chain33Relayer.db)
return ebTypes.Txhashes{Txhash: txhashs}
}
func (chain33Relayer *Relayer4Chain33) syncProc(syncCfg *ebTypes.SyncTxReceiptConfig) {
_, _ = fmt.Fprintln(os.Stdout, "Pls unlock or import private key for Chain33 relayer")
<-chain33Relayer.unlock
_, _ = fmt.Fprintln(os.Stdout, "Chain33 relayer starts to run...")
chain33Relayer.syncTxReceipts = syncTx.StartSyncTxReceipt(syncCfg, chain33Relayer.db)
chain33Relayer.lastHeight4Tx = chain33Relayer.loadLastSyncHeight()
oracleInstance, err := relayerTx.RecoverOracleInstance(chain33Relayer.ethClient, chain33Relayer.bridgeRegistryAddr, chain33Relayer.bridgeRegistryAddr)
if err != nil {
panic(err.Error())
}
chain33Relayer.oracleInstance = oracleInstance
timer := time.NewTicker(time.Duration(chain33Relayer.fetchHeightPeriodMs) * time.Millisecond)
for {
select {
case <-timer.C:
height := chain33Relayer.getCurrentHeight()
relayerLog.Debug("syncProc", "getCurrentHeight", height)
chain33Relayer.onNewHeightProc(height)
case <-chain33Relayer.ctx.Done():
timer.Stop()
return
}
}
}
func (chain33Relayer *Relayer4Chain33) getCurrentHeight() int64 {
var res rpctypes.Header
ctx := jsonclient.NewRPCCtx(chain33Relayer.rpcLaddr, "Chain33.GetLastHeader", nil, &res)
_, err := ctx.RunResult()
if nil != err {
relayerLog.Error("getCurrentHeight", "Failede due to:", err.Error())
}
return res.Height
}
func (chain33Relayer *Relayer4Chain33) onNewHeightProc(currentHeight int64) {
//检查已经提交的交易结果
chain33Relayer.rwLock.Lock()
for chain33Relayer.statusCheckedIndex < chain33Relayer.totalTx4Chain33ToEth {
index := chain33Relayer.statusCheckedIndex + 1
txhash, err := chain33Relayer.getEthTxhash(index)
if nil != err {
relayerLog.Error("onNewHeightProc", "getEthTxhash for index ", index, "error", err.Error())
break
}
status := relayerTx.GetEthTxStatus(chain33Relayer.ethClient, txhash)
//按照提交交易的先后顺序检查交易,只要出现当前交易还在pending状态,就不再检查后续交易,等到下个区块再从该交易进行检查
//TODO:可能会由于网络和打包挖矿的原因,使得交易执行顺序和提交顺序有差别,后续完善该检查逻辑
if status == relayerTx.EthTxPending.String() {
break
}
_ = chain33Relayer.setLastestRelay2EthTxhash(status, txhash.Hex(), index)
atomic.AddInt64(&chain33Relayer.statusCheckedIndex, 1)
_ = chain33Relayer.setStatusCheckedIndex(chain33Relayer.statusCheckedIndex)
}
chain33Relayer.rwLock.Unlock()
//未达到足够的成熟度,不进行处理
// +++++++++||++++++++++++||++++++++++||
// ^ ^ ^
// lastHeight4Tx matDegress currentHeight
for chain33Relayer.lastHeight4Tx+int64(chain33Relayer.matDegree)+1 <= currentHeight {
relayerLog.Info("onNewHeightProc", "currHeight", currentHeight, "lastHeight4Tx", chain33Relayer.lastHeight4Tx)
lastHeight4Tx := chain33Relayer.lastHeight4Tx
TxReceipts, err := chain33Relayer.syncTxReceipts.GetNextValidTxReceipts(lastHeight4Tx)
if nil == TxReceipts || nil != err {
if err != nil {
relayerLog.Error("onNewHeightProc", "Failed to GetNextValidTxReceipts due to:", err.Error())
}
break
}
relayerLog.Debug("onNewHeightProc", "currHeight", currentHeight, "valid tx receipt with height:", TxReceipts.Height)
txs := TxReceipts.Tx
for i, tx := range txs {
//检查是否为lns的交易(包括平行链:user.p.xxx.lns),将闪电网络交易进行收集
if 0 != bytes.Compare(tx.Execer, []byte(relayerTx.X2Eth)) &&
(len(tx.Execer) > 4 && string(tx.Execer[(len(tx.Execer)-4):]) != "."+relayerTx.X2Eth) {
relayerLog.Debug("onNewHeightProc, the tx is not x2ethereum", "Execer", string(tx.Execer), "height:", TxReceipts.Height)
continue
}
var ss types.X2EthereumAction
_ = chain33Types.Decode(tx.Payload, &ss)
actionName := ss.GetActionName()
if relayerTx.BurnAction == actionName || relayerTx.LockAction == actionName {
relayerLog.Debug("^_^ ^_^ Processing chain33 tx receipt", "ActionName", actionName, "fromAddr", tx.From(), "exec", string(tx.Execer))
actionEvent := getOracleClaimType(actionName)
if err := chain33Relayer.handleBurnLockMsg(actionEvent, TxReceipts.ReceiptData[i], tx.Hash()); nil != err {
errInfo := fmt.Sprintf("Failed to handleBurnLockMsg due to:%s", err.Error())
panic(errInfo)
}
}
}
chain33Relayer.lastHeight4Tx = TxReceipts.Height
chain33Relayer.setLastSyncHeight(chain33Relayer.lastHeight4Tx)
}
}
// getOracleClaimType : sets the OracleClaim's claim type based upon the witnessed event type
func getOracleClaimType(eventType string) events.Event {
var claimType events.Event
switch eventType {
case events.MsgBurn.String():
claimType = events.Event(events.ClaimTypeBurn)
case events.MsgLock.String():
claimType = events.Event(events.ClaimTypeLock)
default:
panic(errors.New("eventType invalid"))
}
return claimType
}
// handleBurnLockMsg : parse event data as a Chain33Msg, package it into a ProphecyClaim, then relay tx to the Ethereum Network
func (chain33Relayer *Relayer4Chain33) handleBurnLockMsg(claimEvent events.Event, receipt *chain33Types.ReceiptData, chain33TxHash []byte) error {
relayerLog.Info("handleBurnLockMsg", "Received tx with hash", ethCommon.Bytes2Hex(chain33TxHash))
// Parse the witnessed event's data into a new Chain33Msg
chain33Msg := relayerTx.ParseBurnLockTxReceipt(claimEvent, receipt)
if nil == chain33Msg {
//收到执行失败的交易,直接跳过
relayerLog.Error("handleBurnLockMsg", "Received failed tx with hash", ethCommon.Bytes2Hex(chain33TxHash))
return nil
}
// Parse the Chain33Msg into a ProphecyClaim for relay to Ethereum
prophecyClaim := relayerTx.Chain33MsgToProphecyClaim(*chain33Msg)
// Relay the Chain33Msg to the Ethereum network
txhash, err := relayerTx.RelayOracleClaimToEthereum(chain33Relayer.oracleInstance, chain33Relayer.ethClient, chain33Relayer.ethSender, claimEvent, prophecyClaim, chain33Relayer.privateKey4Ethereum, chain33TxHash)
if nil != err {
return err
}
//保存交易hash,方便查询
atomic.AddInt64(&chain33Relayer.totalTx4Chain33ToEth, 1)
txIndex := atomic.LoadInt64(&chain33Relayer.totalTx4Chain33ToEth)
if err = chain33Relayer.updateTotalTxAmount2Eth(txIndex); nil != err {
relayerLog.Error("handleLogNewProphecyClaimEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
if err = chain33Relayer.setLastestRelay2EthTxhash(relayerTx.EthTxPending.String(), txhash, txIndex); nil != err {
relayerLog.Error("handleLogNewProphecyClaimEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
return nil
}
package chain33
import (
"context"
"encoding/hex"
"flag"
"fmt"
"math/big"
"os"
"os/signal"
"sync"
"syscall"
"testing"
"time"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/testnode"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/test/setup"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethtxs"
relayerTx "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethtxs"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
syncTx "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/relayer/chain33/transceiver/sync"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
relayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
tml "github.com/BurntSushi/toml"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
ethTypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
// 需要显示引用系统插件,以加载系统内置合约
"github.com/33cn/chain33/client/mocks"
_ "github.com/33cn/chain33/system"
"github.com/stretchr/testify/mock"
)
var (
configPath = flag.String("f", "./../../relayer.toml", "configfile")
privateKeyStr = "0x3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
accountAddr = "0x92c8b16afd6d423652559c6e266cbe1c29bfd84f"
passphrase = "123456hzj"
test = "0ac3050aa3020a0a7832657468657265756d126d60671a690a2a3078303030303030303030303030303030303030303030303030303030303030303030303030303030301a2a307830633035626135633233306664616135303362353337303261663139363265303864306336306266220831303030303030302a0365746838121a6e080112210320bbac09528e19c55b0f89cb37ab265e7e856b1a8c388780322dbbfd194b52ba1a473045022100c403d9a6e531292336b44d52e4f4dbb9b8ab1e16335383954583728b909478da022031d8a29efcbcea8df648c4054f3c09ab1ab7a330797cf79fd891a3d9336922e920a08d0628e0f193f60530a1d7ad93e5ebc28e253a22314c7538586d537459765777664e716951336e4e4b33345239466648346b5270425612ce0208021a5e0802125a0a2b10c0d59294bb192222313271796f6361794e46374c7636433971573461767873324537553431664b536676122b10a0c88c94bb192222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a55080f12510a291080ade2042222313271796f6361794e46374c7636433971573461767873324537553431664b53667612242222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a92010867128d010a2a3078303030303030303030303030303030303030303030303030303030303030303030303030303030301222313271796f6361794e46374c7636433971573461767873324537553431664b5366761a2a307830633035626135633233306664616135303362353337303261663139363265303864306336306266220831303030303030302a03657468301220c4092a207a38e1da7de4444f2d34c7488293f3a2e01ce2561e720e9bbef355e83755ad833220e68d8418f69d5f18278a53dca53b101f26f76883337a60a5754d5f6d94e42e3c400148c409"
// 0x8AFDADFC88a1087c9A1D6c0F5Dd04634b87F303a
deployerPrivateKey = "8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
// 0x92C8b16aFD6d423652559C6E266cBE1c29Bfd84f
ethValidatorAddrKeyA = "3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
ethValidatorAddrKeyB = "a5f3063552f4483cfc20ac4f40f45b798791379862219de9e915c64722c1d400"
ethValidatorAddrKeyC = "bbf5e65539e9af0eb0cfac30bad475111054b09c11d668fc0731d54ea777471e"
ethValidatorAddrKeyD = "c9fa31d7984edf81b8ef3b40c761f1847f6fcd5711ab2462da97dc458f1f896b"
)
func TestAll(t *testing.T) {
mock33 := newMock33()
defer mock33.Close()
test_HandleRequest(t)
test_ImportPrivateKey(t)
test_Lockbty(t)
test_restorePrivateKeys(t)
}
func test_HandleRequest(t *testing.T) {
_, sim, _, x2EthDeployInfo, err := deployContracts()
require.NoError(t, err)
chain33Relayer := newChain33Relayer(sim, x2EthDeployInfo, "127.0.0.1:60002", t)
_, err = chain33Relayer.ImportPrivateKey(passphrase, privateKeyStr)
assert.NoError(t, err)
body, err := hex.DecodeString(test)
assert.NoError(t, err)
chain33Relayer.statusCheckedIndex = 1220
err = syncTx.HandleRequest(body)
assert.NoError(t, err)
time.Sleep(200 * time.Millisecond)
ret := chain33Relayer.QueryTxhashRelay2Eth()
assert.NotEmpty(t, ret)
event := getOracleClaimType(events.MsgLock.String())
assert.Equal(t, event, events.Event(events.ClaimTypeLock))
}
func test_ImportPrivateKey(t *testing.T) {
_, sim, _, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
chain33Relayer := newChain33Relayer(sim, x2EthDeployInfo, "127.0.0.1:60000", t)
addr, err := chain33Relayer.ImportPrivateKey(passphrase, privateKeyStr)
assert.NoError(t, err)
assert.Equal(t, addr, accountAddr)
time.Sleep(50 * time.Millisecond)
addr, err = chain33Relayer.GetAccountAddr()
assert.NoError(t, err)
assert.Equal(t, addr, accountAddr)
key, _, _ := chain33Relayer.GetAccount("123")
assert.NotEqual(t, key, privateKeyStr)
key, _, _ = chain33Relayer.GetAccount(passphrase)
assert.Equal(t, key, privateKeyStr)
}
func test_Lockbty(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
chain33Relayer := newChain33Relayer(sim, x2EthDeployInfo, "127.0.0.1:60001", t)
_, err = chain33Relayer.ImportPrivateKey(passphrase, privateKeyStr)
assert.NoError(t, err)
//Test_1_ImportPrivateKey()
ctx := context.Background()
//2nd:订阅事件
eventName := "LogNewBridgeToken"
bridgeBankABI := ethtxs.LoadABI(ethtxs.BridgeBankABI)
logNewBridgeTokenSig := bridgeBankABI.Events[eventName].ID().Hex()
query := ethereum.FilterQuery{
Addresses: []common.Address{x2EthDeployInfo.BridgeBank.Address},
}
// We will check logs for new events
logs := make(chan ethTypes.Log)
// Filter by contract and event, write results to logs
sub, err := sim.SubscribeFilterLogs(ctx, query, logs)
//require.Nil(t, err)
opts := &bind.CallOpts{
Pending: true,
From: para.Operator,
Context: ctx,
}
tokenCount, err := x2EthContracts.BridgeBank.BridgeTokenCount(opts)
require.Nil(t, err)
assert.Equal(t, tokenCount.Int64(), int64(0))
//3rd:创建token
symbol := "BTY"
auth, err := ethtxs.PrepareAuth(sim, para.DeployPrivateKey, para.Operator)
require.Nil(t, err)
_, err = x2EthContracts.BridgeBank.BridgeBankTransactor.CreateNewBridgeToken(auth, symbol)
require.Nil(t, err)
sim.Commit()
logEvent := &events.LogNewBridgeToken{}
select {
// Handle any errors
case err := <-sub.Err():
t.Fatalf("sub error:%s", err.Error())
// vLog is raw event data
case vLog := <-logs:
// Check if the event is a 'LogLock' event
if vLog.Topics[0].Hex() == logNewBridgeTokenSig {
err = bridgeBankABI.Unpack(logEvent, eventName, vLog.Data)
require.Nil(t, err)
require.Equal(t, symbol, logEvent.Symbol)
//tokenCount正确加1
tokenCount, err = x2EthContracts.BridgeBank.BridgeTokenCount(opts)
require.Nil(t, err)
require.Equal(t, tokenCount.Int64(), int64(1))
break
}
}
///////////newOracleClaim///////////////////////////
balance, _ := sim.BalanceAt(ctx, para.InitValidators[0], nil)
fmt.Println("InitValidators[0] addr,", para.InitValidators[0].String(), "balance =", balance.String())
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
amount := int64(99)
ethReceiver := para.InitValidators[2]
claimID := crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), logEvent.Token.Bytes(), big.NewInt(amount).Bytes())
authOracle, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err := ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
bridgeToken, err := generated.NewBridgeToken(logEvent.Token, sim)
require.Nil(t, err)
opts = &bind.CallOpts{
Pending: true,
Context: ctx,
}
balance, err = bridgeToken.BalanceOf(opts, ethReceiver)
require.Nil(t, err)
require.Equal(t, balance.Int64(), int64(0))
tx, err := x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeLock,
chain33Sender,
ethReceiver,
logEvent.Token,
logEvent.Symbol,
big.NewInt(amount),
claimID,
signature)
require.Nil(t, err)
sim.Commit()
balance, err = bridgeToken.BalanceOf(opts, ethReceiver)
require.Nil(t, err)
require.Equal(t, balance.Int64(), amount)
//t.Logf("The minted amount is:%d", balance.Int64())
txhash := tx.Hash().Hex()
chain33Relayer.rwLock.Lock()
chain33Relayer.statusCheckedIndex = 1
chain33Relayer.totalTx4Chain33ToEth = 2
chain33Relayer.rwLock.Unlock()
_ = chain33Relayer.setLastestRelay2EthTxhash(relayerTx.EthTxPending.String(), txhash, 2)
time.Sleep(200 * time.Millisecond)
chain33Relayer.rwLock.Lock()
chain33Relayer.statusCheckedIndex = 9
chain33Relayer.totalTx4Chain33ToEth = 11
chain33Relayer.rwLock.Unlock()
_ = chain33Relayer.setLastestRelay2EthTxhash(relayerTx.EthTxPending.String(), "", 11)
time.Sleep(200 * time.Millisecond)
}
func test_restorePrivateKeys(t *testing.T) {
_, sim, _, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
chain33Relayer := newChain33Relayer(sim, x2EthDeployInfo, "127.0.0.1:60003", t)
_, err = chain33Relayer.ImportPrivateKey(passphrase, privateKeyStr)
assert.NoError(t, err)
go func() {
for range chain33Relayer.unlock {
}
}()
temp := chain33Relayer.ethSender
err = chain33Relayer.RestorePrivateKeys("123")
assert.NotEqual(t, hex.EncodeToString(temp.Bytes()), hex.EncodeToString(chain33Relayer.ethSender.Bytes()))
assert.NoError(t, err)
err = chain33Relayer.RestorePrivateKeys(passphrase)
assert.Equal(t, hex.EncodeToString(temp.Bytes()), hex.EncodeToString(chain33Relayer.ethSender.Bytes()))
assert.NoError(t, err)
err = chain33Relayer.StoreAccountWithNewPassphase("new123", passphrase)
assert.NoError(t, err)
err = chain33Relayer.RestorePrivateKeys("new123")
assert.Equal(t, hex.EncodeToString(temp.Bytes()), hex.EncodeToString(chain33Relayer.ethSender.Bytes()))
assert.NoError(t, err)
time.Sleep(200 * time.Millisecond)
}
func newChain33Relayer(sim *ethinterface.SimExtend, x2EthDeployInfo *ethtxs.X2EthDeployInfo, pushBind string, t *testing.T) *Relayer4Chain33 {
cfg := initCfg(*configPath)
cfg.SyncTxConfig.Chain33Host = "http://127.0.0.1:8801"
cfg.BridgeRegistry = x2EthDeployInfo.BridgeRegistry.Address.String()
cfg.SyncTxConfig.PushBind = pushBind
cfg.SyncTxConfig.FetchHeightPeriodMs = 50
cfg.SyncTxConfig.Dbdriver = "memdb"
db := dbm.NewDB("relayer_db_service", cfg.SyncTxConfig.Dbdriver, cfg.SyncTxConfig.DbPath, cfg.SyncTxConfig.DbCache)
ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup
relayer := &Relayer4Chain33{
rpcLaddr: cfg.SyncTxConfig.Chain33Host,
fetchHeightPeriodMs: cfg.SyncTxConfig.FetchHeightPeriodMs,
unlock: make(chan int),
db: db,
ctx: ctx,
bridgeRegistryAddr: x2EthDeployInfo.BridgeRegistry.Address,
}
err := relayer.setStatusCheckedIndex(1)
assert.NoError(t, err)
relayer.ethClient = sim
relayer.totalTx4Chain33ToEth = relayer.getTotalTxAmount2Eth()
relayer.statusCheckedIndex = relayer.getStatusCheckedIndex()
assert.Equal(t, relayer.statusCheckedIndex, int64(1))
syncCfg := &ebTypes.SyncTxReceiptConfig{
Chain33Host: cfg.SyncTxConfig.Chain33Host,
PushHost: cfg.SyncTxConfig.PushHost,
PushName: cfg.SyncTxConfig.PushName,
PushBind: pushBind,
StartSyncHeight: cfg.SyncTxConfig.StartSyncHeight,
StartSyncSequence: cfg.SyncTxConfig.StartSyncSequence,
StartSyncHash: cfg.SyncTxConfig.StartSyncHash,
}
go relayer.syncProc(syncCfg)
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGTERM)
go func() {
<-ch
cancel()
wg.Wait()
os.Exit(0)
}()
return relayer
}
func deployContracts() (*ethtxs.DeployPara, *ethinterface.SimExtend, *ethtxs.X2EthContracts, *ethtxs.X2EthDeployInfo, error) {
ethValidatorAddrKeys := make([]string, 0)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyA)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyB)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyC)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyD)
ctx := context.Background()
//var backend bind.ContractBackend
backend, para := setup.PrepareTestEnvironment(deployerPrivateKey, ethValidatorAddrKeys)
sim := new(ethinterface.SimExtend)
sim.SimulatedBackend = backend.(*backends.SimulatedBackend)
callMsg := ethereum.CallMsg{
From: para.Deployer,
Data: common.FromHex(generated.BridgeBankBin),
}
_, err := sim.EstimateGas(ctx, callMsg)
if nil != err {
panic("failed to estimate gas due to:" + err.Error())
}
x2EthContracts, x2EthDeployInfo, err := ethtxs.DeployAndInit(sim, para)
if nil != err {
return nil, nil, nil, nil, err
}
sim.Commit()
return para, sim, x2EthContracts, x2EthDeployInfo, nil
}
func initCfg(path string) *relayerTypes.RelayerConfig {
var cfg relayerTypes.RelayerConfig
if _, err := tml.DecodeFile(path, &cfg); err != nil {
fmt.Println(err)
os.Exit(-1)
}
return &cfg
}
func newMock33() *testnode.Chain33Mock {
var ret = types.ReplySubscribePush{IsOk: true, Msg: ""}
var he = types.Header{Height: 10000}
mockapi := &mocks.QueueProtocolAPI{}
// 这里对需要mock的方法打桩,Close是必须的,其它方法根据需要
mockapi.On("Close").Return()
mockapi.On("AddPushSubscribe", mock.Anything).Return(&ret, nil)
mockapi.On("GetLastHeader", mock.Anything).Return(&he, nil)
mock33 := testnode.New("", mockapi)
//defer mock33.Close()
rpcCfg := mock33.GetCfg().RPC
// 这里必须设置监听端口,默认的是无效值
rpcCfg.JrpcBindAddr = "127.0.0.1:8801"
mock33.GetRPC().Listen()
return mock33
}
package chain33
import (
"fmt"
"sync/atomic"
"github.com/33cn/chain33/types"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
"github.com/ethereum/go-ethereum/common"
)
var (
lastSyncHeightPrefix = []byte("lastSyncHeight:")
chain33ToEthBurnLockTxHashPrefix = "chain33ToEthBurnLockTxHash"
chain33ToEthBurnLockTxTotalAmount = []byte("chain33ToEthBurnLockTxTotalAmount")
EthTxStatusCheckedIndex = []byte("EthTxStatusCheckedIndex")
)
func calcRelay2EthTxhash(txindex int64) []byte {
return []byte(fmt.Sprintf("%s-%012d", chain33ToEthBurnLockTxHashPrefix, txindex))
}
func (chain33Relayer *Relayer4Chain33) updateTotalTxAmount2Eth(total int64) error {
totalTx := &types.Int64{
Data: atomic.LoadInt64(&chain33Relayer.totalTx4Chain33ToEth),
}
//更新成功见证的交易数
return chain33Relayer.db.Set(chain33ToEthBurnLockTxTotalAmount, types.Encode(totalTx))
}
func (chain33Relayer *Relayer4Chain33) getTotalTxAmount2Eth() int64 {
totalTx, _ := utils.LoadInt64FromDB(chain33ToEthBurnLockTxTotalAmount, chain33Relayer.db)
return totalTx
}
func (chain33Relayer *Relayer4Chain33) setLastestRelay2EthTxhash(status, txhash string, txIndex int64) error {
key := calcRelay2EthTxhash(txIndex)
ethTxStatus := &ebTypes.EthTxStatus{
Status: status,
Txhash: txhash,
}
data := types.Encode(ethTxStatus)
return chain33Relayer.db.Set(key, data)
}
func (chain33Relayer *Relayer4Chain33) getEthTxhash(txIndex int64) (common.Hash, error) {
key := calcRelay2EthTxhash(txIndex)
ethTxStatus := &ebTypes.EthTxStatus{}
data, err := chain33Relayer.db.Get(key)
if nil != err {
return common.Hash{}, err
}
err = types.Decode(data, ethTxStatus)
if nil != err {
return common.Hash{}, err
}
return common.HexToHash(ethTxStatus.Txhash), nil
}
func (chain33Relayer *Relayer4Chain33) setStatusCheckedIndex(txIndex int64) error {
index := &types.Int64{
Data: txIndex,
}
data := types.Encode(index)
return chain33Relayer.db.Set(EthTxStatusCheckedIndex, data)
}
func (chain33Relayer *Relayer4Chain33) getStatusCheckedIndex() int64 {
index, _ := utils.LoadInt64FromDB(EthTxStatusCheckedIndex, chain33Relayer.db)
return index
}
//获取上次同步到app的高度
func (chain33Relayer *Relayer4Chain33) loadLastSyncHeight() int64 {
height, err := utils.LoadInt64FromDB(lastSyncHeightPrefix, chain33Relayer.db)
if nil != err && err != types.ErrHeightNotExist {
relayerLog.Error("loadLastSyncHeight", "err:", err.Error())
return 0
}
return height
}
func (chain33Relayer *Relayer4Chain33) setLastSyncHeight(syncHeight int64) {
bytes := types.Encode(&types.Int64{Data: syncHeight})
_ = chain33Relayer.db.Set(lastSyncHeightPrefix, bytes)
}
package sync
import (
"fmt"
"math"
"sync/atomic"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
"github.com/pkg/errors"
)
// SeqType
const (
SeqTypeAdd = int32(1)
SeqTypeDel = int32(2)
)
var (
syncLastHeight = []byte("syncLastHeight:")
txReceiptPrefix = []byte("txReceiptPrefix:")
lastSequences = []byte("lastSequences:")
seqOperationType = []string{"SeqTypeAdd", "SeqTypeDel"}
)
var txReceiptCh chan *types.TxReceipts4Subscribe
var resultCh chan error
func init() {
txReceiptCh = make(chan *types.TxReceipts4Subscribe)
resultCh = make(chan error)
}
func txReceiptsKey4Height(height int64) []byte {
return append(txReceiptPrefix, []byte(fmt.Sprintf("%012d", height))...)
}
// pushTxReceipts push block to backend
func pushTxReceipts(txReceipts *types.TxReceipts4Subscribe) error {
txReceiptCh <- txReceipts
err := <-resultCh
return err
}
type TxReceipts struct {
db dbm.DB
seqNum int64 //当前同步的序列号
height int64 //当前区块高度
quit chan struct{}
}
func NewSyncTxReceipts(db dbm.DB) *TxReceipts {
sync := &TxReceipts{
db: db,
}
sync.seqNum, _ = sync.loadBlockLastSequence()
sync.height, _ = sync.LoadLastBlockHeight()
sync.quit = make(chan struct{})
sync.initSyncReceiptDataBase()
return sync
}
//此处添加一个高度为0的空块,只是为了查找下一个比较方便,并不需要使用其信息
func (syncTx *TxReceipts) initSyncReceiptDataBase() {
txblock0, _ := syncTx.GetTxReceipts(0)
if nil != txblock0 {
return
}
txsPerBlock := &types.TxReceipts4SubscribePerBlk{
Height: 0,
}
syncTx.setTxReceiptsPerBlock(txsPerBlock)
}
func (syncTx *TxReceipts) Stop() {
close(syncTx.quit)
}
// SaveAndSyncTxs2Relayer save block to db
func (syncTx *TxReceipts) SaveAndSyncTxs2Relayer() {
for {
select {
case txReceipts := <-txReceiptCh:
log.Info("to deal request", "seq", txReceipts.TxReceipts[0].SeqNum, "count", len(txReceipts.TxReceipts))
syncTx.dealTxReceipts(txReceipts)
case <-syncTx.quit:
return
}
}
}
// 保存区块步骤
// 1. 记录 seqNumber -> seq
// 2. 记录 lastseq
// 3. 更新高度
//
// 重启恢复
// 1. 看高度, 对应高度是已经完成的
// 2. 继续重新下一个高度即可。 重复写, 幂等
// 所以不需要恢复过程, 读出高度即可
// 处理输入流程
func (syncTx *TxReceipts) dealTxReceipts(txReceipts *types.TxReceipts4Subscribe) {
count, start, txReceiptsParsed, err := parseTxReceipts(txReceipts)
if err != nil {
resultCh <- err
}
//正常情况下,本次开始的的seq不能小于上次结束的seq
if start < syncTx.seqNum {
log.Error("dealTxReceipts err: the tx and receipt pushed is old", "start", start, "current_seq", syncTx.seqNum)
resultCh <- errors.New("The tx and receipt pushed is old")
return
}
var height int64
for i := 0; i < count; i++ {
txsPerBlock := txReceiptsParsed[i]
if txsPerBlock.AddDelType == SeqTypeAdd {
syncTx.setTxReceiptsPerBlock(txsPerBlock)
syncTx.setBlockLastSequence(txsPerBlock.SeqNum)
syncTx.setBlockHeight(txsPerBlock.Height)
height = txsPerBlock.Height
} else {
//删除分叉区块处理
syncTx.delTxReceipts(txsPerBlock.Height)
syncTx.setBlockLastSequence(txsPerBlock.SeqNum)
height = txsPerBlock.Height - 1
//删除区块不需要通知新的高度,因为这只会降低未处理区块的成熟度
syncTx.setBlockHeight(height)
}
}
//syncTx.syncReceiptChan <- height
//发送回复,确认接收成功
resultCh <- nil
log.Debug("dealTxReceipts", "seqStart", start, "count", count, "maxBlockHeight", height)
}
func (syncTx *TxReceipts) loadBlockLastSequence() (int64, error) {
return utils.LoadInt64FromDB(lastSequences, syncTx.db)
}
func (syncTx *TxReceipts) LoadLastBlockHeight() (int64, error) {
return utils.LoadInt64FromDB(syncLastHeight, syncTx.db)
}
func (syncTx *TxReceipts) setBlockLastSequence(newSequence int64) {
Sequencebytes := types.Encode(&types.Int64{Data: newSequence})
syncTx.db.Set(lastSequences, Sequencebytes)
//同时更新内存中的seq
syncTx.updateSequence(newSequence)
}
func (syncTx *TxReceipts) setBlockHeight(height int64) {
bytes := types.Encode(&types.Int64{Data: height})
syncTx.db.Set(syncLastHeight, bytes)
atomic.StoreInt64(&syncTx.height, height)
}
func (syncTx *TxReceipts) updateSequence(newSequence int64) {
atomic.StoreInt64(&syncTx.seqNum, newSequence)
}
func (syncTx *TxReceipts) setTxReceiptsPerBlock(txReceipts *types.TxReceipts4SubscribePerBlk) {
key := txReceiptsKey4Height(txReceipts.Height)
value := types.Encode(txReceipts)
if err := syncTx.db.Set(key, value); nil != err {
panic("setTxReceiptsPerBlock failed due to:" + err.Error())
}
}
func (syncTx *TxReceipts) GetTxReceipts(height int64) (*types.TxReceipts4SubscribePerBlk, error) {
key := txReceiptsKey4Height(height)
value, err := syncTx.db.Get(key)
if err != nil {
return nil, err
}
detail := &types.TxReceipts4SubscribePerBlk{}
err = types.Decode(value, detail)
if err != nil {
return nil, err
}
return detail, nil
}
func (syncTx *TxReceipts) GetNextValidTxReceipts(height int64) (*types.TxReceipts4SubscribePerBlk, error) {
key := txReceiptsKey4Height(height)
helper := dbm.NewListHelper(syncTx.db)
TxReceipts := helper.List(txReceiptPrefix, key, 1, dbm.ListASC)
if nil == TxReceipts {
return nil, nil
}
detail := &types.TxReceipts4SubscribePerBlk{}
err := types.Decode(TxReceipts[0], detail)
if err != nil {
return nil, err
}
return detail, nil
}
func (syncTx *TxReceipts) delTxReceipts(height int64) {
key := txReceiptsKey4Height(height)
_ = syncTx.db.Set(key, nil)
}
// 检查输入是否有问题, 并解析输入
func parseTxReceipts(txReceipts *types.TxReceipts4Subscribe) (count int, start int64, txsWithReceipt []*types.TxReceipts4SubscribePerBlk, err error) {
count = len(txReceipts.TxReceipts)
txsWithReceipt = make([]*types.TxReceipts4SubscribePerBlk, 0)
start = math.MaxInt64
for i := 0; i < count; i++ {
if txReceipts.TxReceipts[i].AddDelType != SeqTypeAdd && txReceipts.TxReceipts[i].AddDelType != SeqTypeDel {
log.Error("parseTxReceipts seq op not support", "seq", txReceipts.TxReceipts[i].SeqNum,
"height", txReceipts.TxReceipts[i].Height, "seqOp", txReceipts.TxReceipts[i].AddDelType)
continue
}
txsWithReceipt = append(txsWithReceipt, txReceipts.TxReceipts[i])
if txReceipts.TxReceipts[i].SeqNum < start {
start = txReceipts.TxReceipts[i].SeqNum
}
log.Debug("parseTxReceipts get one block's tx with receipts", "seq", txReceipts.TxReceipts[i].SeqNum,
"height", txReceipts.TxReceipts[i].Height, "seqOpType", seqOperationType[txReceipts.TxReceipts[i].AddDelType-1])
}
if len(txsWithReceipt) != count {
err = errors.New("duplicate block's tx receipt")
return
}
return
}
package sync
func HandleRequest(body []byte) error {
return handleRequest(body)
}
// 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 sync
import (
"compress/gzip"
"fmt"
"io/ioutil"
"net"
"net/http"
"strings"
"github.com/33cn/chain33/blockchain"
dbm "github.com/33cn/chain33/common/db"
l "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/rpc/jsonclient"
"github.com/33cn/chain33/types"
relayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/rs/cors"
)
var (
log = l.New("module", "sync.tx_receipts")
syncTxReceipts *TxReceipts
)
func StartSyncTxReceipt(cfg *relayerTypes.SyncTxReceiptConfig, db dbm.DB) *TxReceipts {
log.Debug("StartSyncTxReceipt, load config", "para:", cfg)
log.Debug("TxReceipts started ")
bindOrResumePush(cfg)
syncTxReceipts = NewSyncTxReceipts(db)
go syncTxReceipts.SaveAndSyncTxs2Relayer()
go startHTTPService(cfg.PushBind, "*")
return syncTxReceipts
}
//func StopSyncTxReceipt() {
// syncTxReceipts.Stop()
//}
func startHTTPService(url string, clientHost string) {
listen, err := net.Listen("tcp", url)
if err != nil {
panic(err)
}
var handler http.Handler = http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
//fmt.Println(r.URL, r.Header, r.Body)
beg := types.Now()
defer func() {
log.Info("handler", "cost", types.Since(beg))
}()
client := strings.Split(r.RemoteAddr, ":")[0]
if !checkClient(client, clientHost) {
log.Error("HandlerFunc", "client", r.RemoteAddr, "expect", clientHost)
_, _ = w.Write([]byte(`{"errcode":"-1","result":null,"msg":"reject"}`))
// unbind 逻辑有问题, 需要的外部处理
// 切换外部服务时, 可能换 name
// 收到一个不是client 的请求,很有可能是以前注册过的, 取消掉
//unbind(client)
return
}
if r.URL.Path == "/" {
w.Header().Set("Content-type", "application/json")
w.WriteHeader(200)
if len(r.Header["Content-Encoding"]) >= 1 && r.Header["Content-Encoding"][0] == "gzip" {
gr, err := gzip.NewReader(r.Body)
//body := make([]byte, r.ContentLength)
body, err := ioutil.ReadAll(gr)
//n, err := r.Body.Read(body)
if err != nil {
log.Debug("Error while serving JSON request: %v", err)
return
}
err = handleRequest(body)
if err == nil {
_, _ = w.Write([]byte("OK"))
} else {
_, _ = w.Write([]byte(err.Error()))
}
}
}
})
co := cors.New(cors.Options{})
handler = co.Handler(handler)
_ = http.Serve(listen, handler)
}
func handleRequest(body []byte) error {
beg := types.Now()
defer func() {
log.Info("handleRequest", "cost", types.Since(beg))
}()
var req types.TxReceipts4Subscribe
err := types.Decode(body, &req)
if err != nil {
log.Error("handleRequest", "DecodeBlockSeqErr", err)
return err
}
err = pushTxReceipts(&req)
return err
}
func checkClient(addr string, expectClient string) bool {
if expectClient == "0.0.0.0" || expectClient == "*" {
return true
}
return addr == expectClient
}
//向chain33节点的注册推送交易回执,AddSubscribeTxReceipt具有2种功能:
//首次注册功能,如果没有进行过注册,则进行首次注册
//如果已经注册,则继续推送
func bindOrResumePush(cfg *relayerTypes.SyncTxReceiptConfig) {
contract := make(map[string]bool)
contract["x2ethereum"] = true
params := types.PushSubscribeReq{
Name: cfg.PushName,
URL: cfg.PushHost,
Encode: "proto",
LastSequence: cfg.StartSyncSequence,
LastHeight: cfg.StartSyncHeight,
LastBlockHash: cfg.StartSyncHash,
Type: blockchain.PushTxReceipt,
Contract: contract,
}
var res types.ReplySubscribePush
ctx := jsonclient.NewRPCCtx(cfg.Chain33Host, "Chain33.AddPushSubscribe", params, &res)
_, err := ctx.RunResult()
if err != nil {
fmt.Println("Failed to AddSubscribeTxReceipt to rpc addr:", cfg.Chain33Host, "ReplySubTxReceipt", res)
panic("bindOrResumePush client failed due to:" + err.Error())
}
if !res.IsOk {
fmt.Println("Failed to AddSubscribeTxReceipt to rpc addr:", cfg.Chain33Host, "ReplySubTxReceipt", res)
panic("bindOrResumePush client failed due to:" + res.Msg)
}
log.Info("bindOrResumePush", "Succeed to AddSubscribeTxReceipt for rpc address:", cfg.Chain33Host)
fmt.Println("Succeed to AddPushSubscribe")
}
package ethereum
import (
"crypto/ecdsa"
crand "crypto/rand"
"crypto/sha256"
"errors"
"fmt"
"io"
chain33Common "github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/crypto/secp256k1"
chain33Types "github.com/33cn/chain33/types"
wcom "github.com/33cn/chain33/wallet/common"
x2ethTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/mr-tron/base58/base58"
"github.com/pborman/uuid"
"golang.org/x/crypto/ripemd160"
)
var (
chain33AccountKey = []byte("Chain33Account4EthRelayer")
start = int(1)
)
type Key struct {
ID uuid.UUID // Version 4 "random" for unique id not derived from key data
// to simplify lookups we also store the address
Address common.Address
// we only store privkey as pubkey/address can be derived from it
// privkey in this struct is always in plaintext
PrivateKey *ecdsa.PrivateKey
}
func (ethRelayer *Relayer4Ethereum) NewAccount(passphrase string) (privateKeystr, addr string, err error) {
_, privateKeystr, addr, err = newKeyAndStore(ethRelayer.db, crand.Reader, passphrase)
if err != nil {
return "", "", err
}
return
}
func (ethRelayer *Relayer4Ethereum) GetAccount(passphrase string) (privateKey, addr string, err error) {
accountInfo, err := ethRelayer.db.Get(chain33AccountKey)
if nil != err {
return "", "", err
}
Chain33Account := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, Chain33Account); nil != err {
return "", "", err
}
decryptered := wcom.CBCDecrypterPrivkey([]byte(passphrase), Chain33Account.Privkey)
privateKey = chain33Common.ToHex(decryptered)
addr = Chain33Account.Addr
return
}
func (ethRelayer *Relayer4Ethereum) GetValidatorAddr() (validators x2ethTypes.ValidatorAddr4EthRelayer, err error) {
var chain33AccountAddr string
accountInfo, err := ethRelayer.db.Get(chain33AccountKey)
if nil == err {
ethAccount := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, ethAccount); nil == err {
chain33AccountAddr = ethAccount.Addr
}
}
if 0 == len(chain33AccountAddr) {
return x2ethTypes.ValidatorAddr4EthRelayer{}, x2ethTypes.ErrNoValidatorConfigured
}
validators = x2ethTypes.ValidatorAddr4EthRelayer{
Chain33Validator: chain33AccountAddr,
}
return
}
func (ethRelayer *Relayer4Ethereum) RestorePrivateKeys(passPhase string) (err error) {
accountInfo, err := ethRelayer.db.Get(chain33AccountKey)
if nil == err {
Chain33Account := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, Chain33Account); nil == err {
decryptered := wcom.CBCDecrypterPrivkey([]byte(passPhase), Chain33Account.Privkey)
var driver secp256k1.Driver
priKey, err := driver.PrivKeyFromBytes(decryptered)
if nil != err {
errInfo := fmt.Sprintf("Failed to PrivKeyFromBytes due to:%s", err.Error())
relayerLog.Info("RestorePrivateKeys", "Failed to PrivKeyFromBytes:", err.Error())
return errors.New(errInfo)
}
ethRelayer.rwLock.Lock()
ethRelayer.privateKey4Chain33 = priKey
ethRelayer.rwLock.Unlock()
}
}
ethRelayer.rwLock.RLock()
if nil != ethRelayer.privateKey4Chain33 {
ethRelayer.unlockchan <- start
}
ethRelayer.rwLock.RUnlock()
return nil
}
func (ethRelayer *Relayer4Ethereum) StoreAccountWithNewPassphase(newPassphrase, oldPassphrase string) error {
accountInfo, err := ethRelayer.db.Get(chain33AccountKey)
if nil != err {
relayerLog.Info("StoreAccountWithNewPassphase", "pls check account is created already, err", err)
return err
}
Chain33Account := &x2ethTypes.Account4Relayer{}
if err := chain33Types.Decode(accountInfo, Chain33Account); nil != err {
return err
}
decryptered := wcom.CBCDecrypterPrivkey([]byte(oldPassphrase), Chain33Account.Privkey)
encryptered := wcom.CBCEncrypterPrivkey([]byte(newPassphrase), decryptered)
Chain33Account.Privkey = encryptered
encodedInfo := chain33Types.Encode(Chain33Account)
return ethRelayer.db.SetSync(chain33AccountKey, encodedInfo)
}
func (ethRelayer *Relayer4Ethereum) ImportChain33PrivateKey(passphrase, privateKeyStr string) error {
var driver secp256k1.Driver
privateKeySli, err := chain33Common.FromHex(privateKeyStr)
if nil != err {
return err
}
priKey, err := driver.PrivKeyFromBytes(privateKeySli)
if nil != err {
return err
}
ethRelayer.rwLock.Lock()
ethRelayer.privateKey4Chain33 = priKey
ethRelayer.rwLock.Unlock()
ethRelayer.unlockchan <- start
addr, err := pubKeyToAddress4Bty(priKey.PubKey().Bytes())
if nil != err {
return err
}
encryptered := wcom.CBCEncrypterPrivkey([]byte(passphrase), privateKeySli)
account := &x2ethTypes.Account4Relayer{
Privkey: encryptered,
Addr: addr,
}
encodedInfo := chain33Types.Encode(account)
return ethRelayer.db.SetSync(chain33AccountKey, encodedInfo)
}
//checksum: first four bytes of double-SHA256.
func checksum(input []byte) (cksum [4]byte) {
h := sha256.New()
_, err := h.Write(input)
if err != nil {
return
}
intermediateHash := h.Sum(nil)
h.Reset()
_, err = h.Write(intermediateHash)
if err != nil {
return
}
finalHash := h.Sum(nil)
copy(cksum[:], finalHash[:])
return
}
func pubKeyToAddress4Bty(pub []byte) (addr string, err error) {
if len(pub) != 33 && len(pub) != 65 { //压缩格式 与 非压缩格式
return "", fmt.Errorf("invalid public key byte")
}
sha256h := sha256.New()
_, err = sha256h.Write(pub)
if err != nil {
return "", err
}
//160hash
ripemd160h := ripemd160.New()
_, err = ripemd160h.Write(sha256h.Sum([]byte("")))
if err != nil {
return "", err
}
//添加版本号
hash160res := append([]byte{0}, ripemd160h.Sum([]byte(""))...)
//添加校验码
cksum := checksum(hash160res)
address := append(hash160res, cksum[:]...)
//地址进行base58编码
addr = base58.Encode(address)
return
}
func newKeyAndStore(db dbm.DB, rand io.Reader, passphrase string) (privateKey *ecdsa.PrivateKey, privateKeyStr, addr string, err error) {
key, err := newKey(rand)
if err != nil {
return nil, "", "", err
}
privateKey = key.PrivateKey
privateKeyBytes := math.PaddedBigBytes(key.PrivateKey.D, 32)
Encryptered := wcom.CBCEncrypterPrivkey([]byte(passphrase), privateKeyBytes)
ethAccount := &x2ethTypes.Account4Relayer{
Privkey: Encryptered,
Addr: key.Address.Hex(),
}
_ = db
privateKeyStr = chain33Common.ToHex(privateKeyBytes)
addr = ethAccount.Addr
return
}
func newKey(rand io.Reader) (*Key, error) {
privateKeyECDSA, err := ecdsa.GenerateKey(crypto.S256(), rand)
if err != nil {
return nil, err
}
return newKeyFromECDSA(privateKeyECDSA), nil
}
func newKeyFromECDSA(privateKeyECDSA *ecdsa.PrivateKey) *Key {
id := uuid.NewRandom()
key := &Key{
ID: id,
Address: crypto.PubkeyToAddress(privateKeyECDSA.PublicKey),
PrivateKey: privateKeyECDSA,
}
return key
}
package ethereum
// -----------------------------------------------------
// Ethereum relayer
//
// Initializes the relayer service, which parses,
// encodes, and packages named events on an Ethereum
// Smart Contract for validator's to sign and send
// to the Chain33 bridge.
// -----------------------------------------------------
import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"regexp"
"sync"
"sync/atomic"
"time"
chain33Crypto "github.com/33cn/chain33/common/crypto"
dbm "github.com/33cn/chain33/common/db"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethtxs"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
x2ethTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
)
type Relayer4Ethereum struct {
provider string
clientChainID *big.Int
bridgeRegistryAddr common.Address
db dbm.DB
rwLock sync.RWMutex
privateKey4Chain33 chain33Crypto.PrivKey
ethValidator common.Address
totalTx4Eth2Chain33 int64
rpcURL2Chain33 string
unlockchan chan int
maturityDegree int32
fetchHeightPeriodMs int32
eventLogIndex ebTypes.EventLogIndex
clientSpec ethinterface.EthClientSpec
bridgeBankAddr common.Address
bridgeBankSub ethereum.Subscription
bridgeBankLog chan types.Log
bridgeBankEventLockSig string
bridgeBankEventBurnSig string
bridgeBankAbi abi.ABI
deployInfo *ebTypes.Deploy
x2EthDeployInfo *ethtxs.X2EthDeployInfo
deployPara *ethtxs.DeployPara
operatorInfo *ethtxs.OperatorInfo
x2EthContracts *ethtxs.X2EthContracts
}
var (
relayerLog = log.New("module", "ethereum_relayer")
)
const (
DefaultBlockPeriod = 5000
)
func StartEthereumRelayer(rpcURL2Chain33 string, db dbm.DB, provider, registryAddress string, deploy *ebTypes.Deploy, degree, blockInterval int32) *Relayer4Ethereum {
if 0 == blockInterval {
blockInterval = DefaultBlockPeriod
}
ethRelayer := &Relayer4Ethereum{
provider: provider,
db: db,
unlockchan: make(chan int, 2),
rpcURL2Chain33: rpcURL2Chain33,
bridgeRegistryAddr: common.HexToAddress(registryAddress),
deployInfo: deploy,
maturityDegree: degree,
fetchHeightPeriodMs: blockInterval,
}
registrAddrInDB, err := ethRelayer.getBridgeRegistryAddr()
//如果输入的registry地址非空,且和数据库保存地址不一致,则直接使用输入注册地址
if registryAddress != "" && nil == err && registrAddrInDB != registryAddress {
relayerLog.Error("StartEthereumRelayer", "BridgeRegistry is setted already with value", registrAddrInDB,
"but now setting to", registryAddress)
_ = ethRelayer.setBridgeRegistryAddr(registryAddress)
} else if registryAddress == "" && registrAddrInDB != "" {
//输入地址为空,且数据库中保存地址不为空,则直接使用数据库中的地址
ethRelayer.bridgeRegistryAddr = common.HexToAddress(registrAddrInDB)
}
ethRelayer.eventLogIndex = ethRelayer.getLastBridgeBankProcessedHeight()
ethRelayer.initBridgeBankTx()
// Start clientSpec with infura ropsten provider
relayerLog.Info("Relayer4Ethereum proc", "Started Ethereum websocket with provider:", ethRelayer.provider, "rpcURL2Chain33:", ethRelayer.rpcURL2Chain33)
client, err := ethtxs.SetupWebsocketEthClient(ethRelayer.provider)
if err != nil {
panic(err)
}
ethRelayer.clientSpec = client
ctx := context.Background()
clientChainID, err := client.NetworkID(ctx)
if err != nil {
errinfo := fmt.Sprintf("Failed to get NetworkID due to:%s", err.Error())
panic(errinfo)
}
ethRelayer.clientChainID = clientChainID
go ethRelayer.proc()
return ethRelayer
}
func (ethRelayer *Relayer4Ethereum) recoverDeployPara() (err error) {
if nil == ethRelayer.deployInfo {
return nil
}
deployPrivateKey, err := crypto.ToECDSA(common.FromHex(ethRelayer.deployInfo.DeployerPrivateKey))
if nil != err {
return err
}
deployerAddr := crypto.PubkeyToAddress(deployPrivateKey.PublicKey)
ethRelayer.rwLock.Lock()
ethRelayer.operatorInfo = &ethtxs.OperatorInfo{
PrivateKey: deployPrivateKey,
Address: deployerAddr,
}
ethRelayer.rwLock.Unlock()
return nil
}
//部署以太坊合约
func (ethRelayer *Relayer4Ethereum) DeployContrcts() (bridgeRegistry string, err error) {
bridgeRegistry = ""
if nil == ethRelayer.deployInfo {
return bridgeRegistry, errors.New("no deploy info configured yet")
}
deployPrivateKey, err := crypto.ToECDSA(common.FromHex(ethRelayer.deployInfo.DeployerPrivateKey))
if nil != err {
return bridgeRegistry, err
}
if len(ethRelayer.deployInfo.ValidatorsAddr) != len(ethRelayer.deployInfo.InitPowers) {
return bridgeRegistry, errors.New("not same number for validator address and power")
}
if len(ethRelayer.deployInfo.ValidatorsAddr) < 3 {
return bridgeRegistry, errors.New("the number of validator must be not less than 3")
}
nilAddr := common.Address{}
//已经设置了注册合约地址,说明已经部署了相关的合约,不再重复部署
if ethRelayer.bridgeRegistryAddr != nilAddr {
return bridgeRegistry, errors.New("contract deployed already")
}
var validators []common.Address
var initPowers []*big.Int
for i, addr := range ethRelayer.deployInfo.ValidatorsAddr {
validators = append(validators, common.HexToAddress(addr))
initPowers = append(initPowers, big.NewInt(ethRelayer.deployInfo.InitPowers[i]))
}
deployerAddr := crypto.PubkeyToAddress(deployPrivateKey.PublicKey)
para := &ethtxs.DeployPara{
DeployPrivateKey: deployPrivateKey,
Deployer: deployerAddr,
Operator: deployerAddr,
InitValidators: validators,
ValidatorPriKey: []*ecdsa.PrivateKey{deployPrivateKey},
InitPowers: initPowers,
}
for i, power := range para.InitPowers {
relayerLog.Info("deploy", "the validator address ", para.InitValidators[i].String(),
"power", power.String())
}
x2EthContracts, x2EthDeployInfo, err := ethtxs.DeployAndInit(ethRelayer.clientSpec, para)
if err != nil {
return bridgeRegistry, err
}
ethRelayer.rwLock.Lock()
ethRelayer.operatorInfo = &ethtxs.OperatorInfo{
PrivateKey: deployPrivateKey,
Address: deployerAddr,
}
ethRelayer.deployPara = para
ethRelayer.x2EthDeployInfo = x2EthDeployInfo
ethRelayer.x2EthContracts = x2EthContracts
bridgeRegistry = x2EthDeployInfo.BridgeRegistry.Address.String()
_ = ethRelayer.setBridgeRegistryAddr(bridgeRegistry)
//设置注册合约地址,同时设置启动中继服务的信号
ethRelayer.bridgeRegistryAddr = x2EthDeployInfo.BridgeRegistry.Address
ethRelayer.rwLock.Unlock()
ethRelayer.unlockchan <- start
relayerLog.Info("deploy", "the BridgeRegistry address is", bridgeRegistry)
return bridgeRegistry, nil
}
//GetBalance:获取某一个币种的余额
func (ethRelayer *Relayer4Ethereum) GetBalance(tokenAddr, owner string) (string, error) {
return ethtxs.GetBalance(ethRelayer.clientSpec, tokenAddr, owner)
}
func (ethRelayer *Relayer4Ethereum) ShowBridgeBankAddr() (string, error) {
if nil == ethRelayer.x2EthDeployInfo {
return "", errors.New("the relayer is not started yes")
}
return ethRelayer.x2EthDeployInfo.BridgeBank.Address.String(), nil
}
func (ethRelayer *Relayer4Ethereum) ShowBridgeRegistryAddr() (string, error) {
if nil == ethRelayer.x2EthDeployInfo {
return "", errors.New("the relayer is not started yes")
}
return ethRelayer.x2EthDeployInfo.BridgeRegistry.Address.String(), nil
}
func (ethRelayer *Relayer4Ethereum) ShowLockStatics(tokenAddr string) (string, error) {
return ethtxs.GetLockedFunds(ethRelayer.x2EthContracts.BridgeBank, tokenAddr)
}
func (ethRelayer *Relayer4Ethereum) ShowDepositStatics(tokenAddr string) (string, error) {
return ethtxs.GetDepositFunds(ethRelayer.clientSpec, tokenAddr)
}
func (ethRelayer *Relayer4Ethereum) ShowTokenAddrBySymbol(tokenSymbol string) (string, error) {
return ethtxs.GetToken2address(ethRelayer.x2EthContracts.BridgeBank, tokenSymbol)
}
func (ethRelayer *Relayer4Ethereum) IsProphecyPending(claimID [32]byte) (bool, error) {
return ethtxs.IsProphecyPending(claimID, ethRelayer.ethValidator, ethRelayer.x2EthContracts.Chain33Bridge)
}
func (ethRelayer *Relayer4Ethereum) CreateBridgeToken(symbol string) (string, error) {
ethRelayer.rwLock.RLock()
defer ethRelayer.rwLock.RUnlock()
return ethtxs.CreateBridgeToken(symbol, ethRelayer.clientSpec, ethRelayer.operatorInfo, ethRelayer.x2EthDeployInfo, ethRelayer.x2EthContracts)
}
func (ethRelayer *Relayer4Ethereum) CreateERC20Token(symbol string) (string, error) {
ethRelayer.rwLock.RLock()
defer ethRelayer.rwLock.RUnlock()
return ethtxs.CreateERC20Token(symbol, ethRelayer.clientSpec, ethRelayer.operatorInfo)
}
func (ethRelayer *Relayer4Ethereum) MintERC20Token(tokenAddr, ownerAddr, amount string) (string, error) {
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
ethRelayer.rwLock.RLock()
defer ethRelayer.rwLock.RUnlock()
return ethtxs.MintERC20Token(tokenAddr, ownerAddr, bn, ethRelayer.clientSpec, ethRelayer.operatorInfo)
}
func (ethRelayer *Relayer4Ethereum) ApproveAllowance(ownerPrivateKey, tokenAddr, amount string) (string, error) {
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
return ethtxs.ApproveAllowance(ownerPrivateKey, tokenAddr, ethRelayer.x2EthDeployInfo.BridgeBank.Address, bn, ethRelayer.clientSpec)
}
func (ethRelayer *Relayer4Ethereum) Burn(ownerPrivateKey, tokenAddr, chain33Receiver, amount string) (string, error) {
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
return ethtxs.Burn(ownerPrivateKey, tokenAddr, chain33Receiver, ethRelayer.x2EthDeployInfo.BridgeBank.Address, bn, ethRelayer.x2EthContracts.BridgeBank, ethRelayer.clientSpec)
}
func (ethRelayer *Relayer4Ethereum) BurnAsync(ownerPrivateKey, tokenAddr, chain33Receiver, amount string) (string, error) {
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
return ethtxs.BurnAsync(ownerPrivateKey, tokenAddr, chain33Receiver, bn, ethRelayer.x2EthContracts.BridgeBank, ethRelayer.clientSpec)
}
func (ethRelayer *Relayer4Ethereum) TransferToken(tokenAddr, fromKey, toAddr, amount string) (string, error) {
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
return ethtxs.TransferToken(tokenAddr, fromKey, toAddr, bn, ethRelayer.clientSpec)
}
func (ethRelayer *Relayer4Ethereum) GetDecimals(tokenAddr string) (uint8, error) {
opts := &bind.CallOpts{
Pending: true,
From: common.HexToAddress(tokenAddr),
Context: context.Background(),
}
bridgeToken, _ := generated.NewBridgeToken(common.HexToAddress(tokenAddr), ethRelayer.clientSpec)
return bridgeToken.Decimals(opts)
}
func (ethRelayer *Relayer4Ethereum) LockEthErc20Asset(ownerPrivateKey, tokenAddr, amount string, chain33Receiver string) (string, error) {
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
return ethtxs.LockEthErc20Asset(ownerPrivateKey, tokenAddr, chain33Receiver, bn, ethRelayer.clientSpec, ethRelayer.x2EthContracts.BridgeBank, ethRelayer.x2EthDeployInfo.BridgeBank.Address)
}
func (ethRelayer *Relayer4Ethereum) LockEthErc20AssetAsync(ownerPrivateKey, tokenAddr, amount string, chain33Receiver string) (string, error) {
bn := big.NewInt(1)
bn, _ = bn.SetString(x2ethTypes.TrimZeroAndDot(amount), 10)
return ethtxs.LockEthErc20AssetAsync(ownerPrivateKey, tokenAddr, chain33Receiver, bn, ethRelayer.clientSpec, ethRelayer.x2EthContracts.BridgeBank)
}
func (ethRelayer *Relayer4Ethereum) ShowTxReceipt(hash string) (*types.Receipt, error) {
txhash := common.HexToHash(hash)
return ethRelayer.clientSpec.TransactionReceipt(context.Background(), txhash)
}
func (ethRelayer *Relayer4Ethereum) proc() {
//等待用户导入
relayerLog.Info("Please unlock or import private key for Ethereum relayer")
nilAddr := common.Address{}
if nilAddr != ethRelayer.bridgeRegistryAddr {
relayerLog.Info("proc", "Going to recover corresponding solidity contract handler with bridgeRegistryAddr", ethRelayer.bridgeRegistryAddr.String())
var err error
ethRelayer.rwLock.Lock()
ethRelayer.x2EthContracts, ethRelayer.x2EthDeployInfo, err = ethtxs.RecoverContractHandler(ethRelayer.clientSpec, ethRelayer.bridgeRegistryAddr, ethRelayer.bridgeRegistryAddr)
if nil != err {
panic("Failed to recover corresponding solidity contract handler due to:" + err.Error())
}
ethRelayer.rwLock.Unlock()
relayerLog.Info("^-^ ^-^ Succeed to recover corresponding solidity contract handler")
if nil != ethRelayer.recoverDeployPara() {
panic("Failed to recoverDeployPara")
}
ethRelayer.unlockchan <- start
}
var timer *time.Ticker
ctx := context.Background()
continueFailCount := int32(0)
for range ethRelayer.unlockchan {
relayerLog.Info("Received ethRelayer.unlockchan")
ethRelayer.rwLock.RLock()
privateKey4Chain33 := ethRelayer.privateKey4Chain33
ethRelayer.rwLock.RUnlock()
if nil != privateKey4Chain33 && nilAddr != ethRelayer.bridgeRegistryAddr {
relayerLog.Info("Ethereum relayer starts to run...")
ethRelayer.prePareSubscribeEvent()
//向bridgeBank订阅事件
ethRelayer.subscribeEvent()
ethRelayer.filterLogEvents()
relayerLog.Info("Ethereum relayer starts to process online log event...")
timer = time.NewTicker(time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
goto latter
}
}
latter:
for {
select {
case <-timer.C:
ethRelayer.procNewHeight(ctx, &continueFailCount)
case err := <-ethRelayer.bridgeBankSub.Err():
panic("bridgeBankSub" + err.Error())
case vLog := <-ethRelayer.bridgeBankLog:
ethRelayer.storeBridgeBankLogs(vLog, true)
}
}
}
func (ethRelayer *Relayer4Ethereum) procNewHeight(ctx context.Context, continueFailCount *int32) {
head, err := ethRelayer.clientSpec.HeaderByNumber(ctx, nil)
if nil != err {
*continueFailCount++
if *continueFailCount >= (12 * 5) {
panic(err.Error())
}
relayerLog.Error("Failed to get ethereum height", "provider", ethRelayer.provider,
"continueFailCount", continueFailCount)
return
}
*continueFailCount = 0
currentHeight := head.Number.Uint64()
relayerLog.Info("procNewHeight", "currentHeight", currentHeight)
//一次最大只获取10个logEvent进行处理
fetchCnt := int32(10)
for ethRelayer.eventLogIndex.Height+uint64(ethRelayer.maturityDegree)+1 <= currentHeight {
logs, err := ethRelayer.getNextValidEthTxEventLogs(ethRelayer.eventLogIndex.Height, ethRelayer.eventLogIndex.Index, fetchCnt)
if nil != err {
relayerLog.Error("Failed to get ethereum height", "getNextValidEthTxEventLogs err", err.Error())
return
}
for i, vLog := range logs {
if vLog.BlockNumber+uint64(ethRelayer.maturityDegree)+1 > currentHeight {
logs = logs[:i]
break
}
ethRelayer.procBridgeBankLogs(*vLog)
}
cnt := int32(len(logs))
if len(logs) > 0 {
//firstHeight := logs[0].BlockNumber
lastHeight := logs[cnt-1].BlockNumber
index := logs[cnt-1].TxIndex
//获取的数量小于批量获取数量,则认为直接
ethRelayer.setBridgeBankProcessedHeight(lastHeight, uint32(index))
ethRelayer.eventLogIndex.Height = lastHeight
ethRelayer.eventLogIndex.Index = uint32(index)
}
//当前需要处理的event数量已经少于10个,直接返回
if cnt < fetchCnt {
return
}
}
}
func (ethRelayer *Relayer4Ethereum) storeBridgeBankLogs(vLog types.Log, setBlockNumber bool) {
//lock,用于捕捉 (ETH/ERC20----->chain33) 跨链转移
//burn,用于捕捉 (chain33 token----->chain33) 实现chain33资产withdraw操作,之后在chain33上实现unlock操作
if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventLockSig {
//先进行数据的持久化,等到一定的高度成熟度之后再进行处理
relayerLog.Info("Relayer4Ethereum storeBridgeBankLogs", "^_^ ^_^ Received bridgeBankLog for event", "lock",
"Block number:", vLog.BlockNumber, "tx Index", vLog.TxIndex, "log Index", vLog.Index, "Tx hash:", vLog.TxHash.Hex())
if err := ethRelayer.setEthTxEvent(vLog); nil != err {
panic(err.Error())
}
} else if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventBurnSig {
relayerLog.Info("Relayer4Ethereum storeBridgeBankLogs", "^_^ ^_^ Received bridgeBankLog for event", "burn",
"Block number:", vLog.BlockNumber, "tx Index", vLog.TxIndex, "log Index", vLog.Index, "Tx hash:", vLog.TxHash.Hex())
if err := ethRelayer.setEthTxEvent(vLog); nil != err {
panic(err.Error())
}
}
//确定是否需要更新保存同步日志高度
if setBlockNumber {
if err := ethRelayer.setHeight4BridgeBankLogAt(vLog.BlockNumber); nil != err {
panic(err.Error())
}
}
}
func (ethRelayer *Relayer4Ethereum) procBridgeBankLogs(vLog types.Log) {
if ethRelayer.checkTxProcessed(vLog.TxHash.Bytes()) {
relayerLog.Info("procBridgeBankLogs", "Tx has been already Processed with hash:", vLog.TxHash.Hex(),
"height", vLog.BlockNumber, "index", vLog.Index)
return
}
defer func() {
if err := ethRelayer.setTxProcessed(vLog.TxHash.Bytes()); nil != err {
panic(err.Error())
}
}()
//检查当前交易是否因为区块回退而导致交易丢失
receipt, err := ethRelayer.clientSpec.TransactionReceipt(context.Background(), vLog.TxHash)
if nil != err {
relayerLog.Error("procBridgeBankLogs", "Failed to get tx receipt with hash", vLog.TxHash.String())
return
}
//检查当前的交易是否成功执行
if receipt.Status != types.ReceiptStatusSuccessful {
relayerLog.Error("procBridgeBankLogs", "tx not successful with status", receipt.Status)
return
}
//lock,用于捕捉 (ETH/ERC20----->chain33) 跨链转移
if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventLockSig {
eventName := events.LogLock.String()
relayerLog.Info("Relayer4Ethereum proc", "Going to process", eventName,
"Block number:", vLog.BlockNumber, "Tx hash:", vLog.TxHash.Hex())
err := ethRelayer.handleLogLockEvent(ethRelayer.clientChainID, ethRelayer.bridgeBankAbi, eventName, vLog)
if err != nil {
errinfo := fmt.Sprintf("Failed to handleLogLockEvent due to:%s", err.Error())
relayerLog.Info("Relayer4Ethereum procBridgeBankLogs", "errinfo", errinfo)
panic(errinfo)
}
} else if vLog.Topics[0].Hex() == ethRelayer.bridgeBankEventBurnSig {
//burn,用于捕捉 (chain33 token----->chain33) 实现chain33资产withdraw操作,之后在chain33上实现unlock操作
eventName := events.LogChain33TokenBurn.String()
relayerLog.Info("Relayer4Ethereum proc", "Going to process", eventName,
"Block number:", vLog.BlockNumber, "Tx hash:", vLog.TxHash.Hex())
err := ethRelayer.handleLogBurnEvent(ethRelayer.clientChainID, ethRelayer.bridgeBankAbi, eventName, vLog)
if err != nil {
errinfo := fmt.Sprintf("Failed to handleLogBurnEvent due to:%s", err.Error())
relayerLog.Info("Relayer4Ethereum procBridgeBankLogs", "errinfo", errinfo)
panic(errinfo)
}
}
}
func (ethRelayer *Relayer4Ethereum) filterLogEvents() {
deployHeight, _ := ethtxs.GetDeployHeight(ethRelayer.clientSpec, ethRelayer.x2EthDeployInfo.BridgeRegistry.Address, ethRelayer.x2EthDeployInfo.BridgeRegistry.Address)
height4BridgeBankLogAt := int64(ethRelayer.getHeight4BridgeBankLogAt())
if height4BridgeBankLogAt < deployHeight {
height4BridgeBankLogAt = deployHeight
}
header, err := ethRelayer.clientSpec.HeaderByNumber(context.Background(), nil)
if err != nil {
errinfo := fmt.Sprintf("Failed to get HeaderByNumbers due to:%s", err.Error())
panic(errinfo)
}
curHeight := int64(header.Number.Uint64())
relayerLog.Info("filterLogEvents", "curHeight:", curHeight)
bridgeBankSig := make(map[string]bool)
bridgeBankSig[ethRelayer.bridgeBankEventLockSig] = true
bridgeBankSig[ethRelayer.bridgeBankEventBurnSig] = true
bridgeBankLog := make(chan types.Log)
done := make(chan int)
go ethRelayer.filterLogEventsProc(bridgeBankLog, done, "bridgeBank", curHeight, height4BridgeBankLogAt, ethRelayer.bridgeBankAddr, bridgeBankSig)
for {
select {
case vLog := <-bridgeBankLog:
ethRelayer.storeBridgeBankLogs(vLog, true)
case vLog := <-ethRelayer.bridgeBankLog:
//因为此处是同步保存信息,防止未同步完成出现panic时,直接将其设置为最新高度,中间出现部分信息不同步的情况
ethRelayer.storeBridgeBankLogs(vLog, false)
case <-done:
relayerLog.Info("Finshed offline logs processed")
return
}
}
}
func (ethRelayer *Relayer4Ethereum) filterLogEventsProc(logchan chan<- types.Log, done chan<- int, title string, curHeight, heightLogProcAt int64, contractAddr common.Address, eventSig map[string]bool) {
relayerLog.Info(title, "eventSig", eventSig)
startHeight := heightLogProcAt
batchCount := int64(10)
query := ethereum.FilterQuery{
Addresses: []common.Address{contractAddr},
}
for {
if batchCount < (curHeight - startHeight + 1) {
stopHeight := startHeight + batchCount - 1
query.FromBlock = big.NewInt(startHeight)
query.ToBlock = big.NewInt(stopHeight)
} else {
query.FromBlock = big.NewInt(startHeight)
query.ToBlock = big.NewInt(curHeight)
}
// Filter by contract and event, write results to logs
logs, err := ethRelayer.clientSpec.FilterLogs(context.Background(), query)
if err != nil {
errinfo := fmt.Sprintf("Failed to filterLogEvents due to:%s", err.Error())
panic(errinfo)
}
relayerLog.Info(title, "received logs with number", len(logs),
"start height", query.FromBlock.String(), "stop height", query.ToBlock.String())
for _, logv := range logs {
relayerLog.Info(title, "received log with topics", logv.Topics[0].Hex(), "BlockNumber", logv.BlockNumber)
if _, exist := eventSig[logv.Topics[0].Hex()]; !exist {
continue
}
logchan <- logv
relayerLog.Info(title, "get unprocessed log with topic:", logv.Topics[0].String(),
"BlockNumber", logv.BlockNumber)
}
if query.ToBlock.Int64() == curHeight {
relayerLog.Info(title, "Finished FilterLogs to height", curHeight)
done <- 1
break
}
startHeight = query.ToBlock.Int64() + 1
}
}
func (ethRelayer *Relayer4Ethereum) prePareSubscribeEvent() {
var eventName string
//bridgeBank处理
contactAbi := ethtxs.LoadABI(ethtxs.BridgeBankABI)
ethRelayer.bridgeBankAbi = contactAbi
eventName = events.LogLock.String()
ethRelayer.bridgeBankEventLockSig = contactAbi.Events[eventName].ID().Hex()
eventName = events.LogChain33TokenBurn.String()
ethRelayer.bridgeBankEventBurnSig = contactAbi.Events[eventName].ID().Hex()
ethRelayer.bridgeBankAddr = ethRelayer.x2EthDeployInfo.BridgeBank.Address
}
func (ethRelayer *Relayer4Ethereum) subscribeEvent() {
targetAddress := ethRelayer.bridgeBankAddr
// We need the target address in bytes[] for the query
query := ethereum.FilterQuery{
Addresses: []common.Address{targetAddress},
FromBlock: big.NewInt(int64(1)),
}
// We will check logs for new events
logs := make(chan types.Log, 10)
// Filter by contract and event, write results to logs
sub, err := ethRelayer.clientSpec.SubscribeFilterLogs(context.Background(), query, logs)
if err != nil {
errinfo := fmt.Sprintf("Failed to SubscribeFilterLogs due to:%s", err.Error())
panic(errinfo)
}
relayerLog.Info("subscribeEvent", "Subscribed to contract at address:", targetAddress.Hex())
ethRelayer.bridgeBankLog = logs
ethRelayer.bridgeBankSub = sub
}
func (ethRelayer *Relayer4Ethereum) IsValidatorActive(addr string) (bool, error) {
re := regexp.MustCompile("^0x[0-9a-fA-F]{40}$")
if !re.MatchString(addr) {
return false, errors.New("this address is not an ethereum address")
}
ethRelayer.rwLock.RLock()
active, err := ethtxs.IsActiveValidator(common.HexToAddress(addr), ethRelayer.x2EthContracts.Valset)
ethRelayer.rwLock.RUnlock()
return active, err
}
func (ethRelayer *Relayer4Ethereum) ShowOperator() (string, error) {
operator, err := ethtxs.GetOperator(ethRelayer.clientSpec, ethRelayer.ethValidator, ethRelayer.bridgeBankAddr)
if nil != err {
return "", err
}
return operator.String(), nil
}
func (ethRelayer *Relayer4Ethereum) QueryTxhashRelay2Eth() ebTypes.Txhashes {
txhashs := ethRelayer.queryTxhashes([]byte(chain33ToEthTxHashPrefix))
return ebTypes.Txhashes{Txhash: txhashs}
}
func (ethRelayer *Relayer4Ethereum) QueryTxhashRelay2Chain33() ebTypes.Txhashes {
txhashs := ethRelayer.queryTxhashes([]byte(eth2chain33TxHashPrefix))
return ebTypes.Txhashes{Txhash: txhashs}
}
// handleLogLockEvent : unpacks a LogLock event, converts it to a ProphecyClaim, and relays a tx to chain33
func (ethRelayer *Relayer4Ethereum) handleLogLockEvent(clientChainID *big.Int, contractABI abi.ABI, eventName string, log types.Log) error {
rpcURL := ethRelayer.rpcURL2Chain33
// Unpack the LogLock event using its unique event signature from the contract's ABI
event, err := events.UnpackLogLock(contractABI, eventName, log.Data)
if nil != err {
return err
}
// Add the event to the record
events.NewEventWrite(log.TxHash.Hex(), *event)
var decimal uint8
if event.Token.String() == "" || event.Token.String() == "0x0000000000000000000000000000000000000000" {
decimal = 18
} else {
opts := &bind.CallOpts{
Pending: true,
From: common.HexToAddress(event.Token.String()),
Context: context.Background(),
}
bridgeToken, _ := generated.NewBridgeToken(common.HexToAddress(event.Token.String()), ethRelayer.clientSpec)
decimal, err = bridgeToken.Decimals(opts)
if err != nil {
return err
}
}
// Parse the LogLock event's payload into a struct
prophecyClaim, err := ethtxs.LogLockToEthBridgeClaim(event, clientChainID.Int64(), ethRelayer.bridgeBankAddr.String(), int64(decimal))
if err != nil {
return err
}
// Initiate the relay
ethRelayer.rwLock.RLock()
privateKey4Chain33 := ethRelayer.privateKey4Chain33
ethRelayer.rwLock.RUnlock()
txhash, err := ethtxs.RelayLockToChain33(privateKey4Chain33, prophecyClaim, rpcURL)
if err != nil {
relayerLog.Error("handleLogLockEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
relayerLog.Info("handleLogLockEvent", "RelayLockToChain33 with hash", txhash)
//保存交易hash,方便查询
atomic.AddInt64(&ethRelayer.totalTx4Eth2Chain33, 1)
txIndex := atomic.LoadInt64(&ethRelayer.totalTx4Eth2Chain33)
if err = ethRelayer.updateTotalTxAmount2chain33(txIndex); nil != err {
relayerLog.Error("handleLogLockEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
if err = ethRelayer.setLastestRelay2Chain33Txhash(txhash, txIndex); nil != err {
relayerLog.Error("handleLogLockEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
return nil
}
// handleLogBurnEvent : unpacks a burn event, converts it to a ProphecyClaim, and relays a tx to chain33
func (ethRelayer *Relayer4Ethereum) handleLogBurnEvent(clientChainID *big.Int, contractABI abi.ABI, eventName string, log types.Log) error {
rpcURL := ethRelayer.rpcURL2Chain33
event, err := events.UnpackLogBurn(contractABI, eventName, log.Data)
if nil != err {
return err
}
var decimal uint8
if event.Token.String() == "" || event.Token.String() == "0x0000000000000000000000000000000000000000" {
decimal = 18
} else {
opts := &bind.CallOpts{
Pending: true,
From: common.HexToAddress(event.Token.String()),
Context: context.Background(),
}
bridgeToken, _ := generated.NewBridgeToken(common.HexToAddress(event.Token.String()), ethRelayer.clientSpec)
decimal, err = bridgeToken.Decimals(opts)
if err != nil {
return err
}
}
// Parse the LogLock event's payload into a struct
prophecyClaim, err := ethtxs.LogBurnToEthBridgeClaim(event, clientChainID.Int64(), ethRelayer.bridgeBankAddr.String(), int64(decimal))
if err != nil {
return err
}
// Initiate the relay
ethRelayer.rwLock.RLock()
privateKey4Chain33 := ethRelayer.privateKey4Chain33
ethRelayer.rwLock.RUnlock()
txhash, err := ethtxs.RelayBurnToChain33(privateKey4Chain33, prophecyClaim, rpcURL)
if err != nil {
relayerLog.Error("handleLogLockEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
relayerLog.Info("handleLogLockEvent", "RelayBurnToChain33 with hash", txhash)
//保存交易hash,方便查询
atomic.AddInt64(&ethRelayer.totalTx4Eth2Chain33, 1)
txIndex := atomic.LoadInt64(&ethRelayer.totalTx4Eth2Chain33)
if err = ethRelayer.updateTotalTxAmount2chain33(txIndex); nil != err {
relayerLog.Error("handleLogBurnEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
if err = ethRelayer.setLastestRelay2Chain33Txhash(txhash, txIndex); nil != err {
relayerLog.Error("handleLogBurnEvent", "Failed to RelayLockToChain33 due to:", err.Error())
return err
}
return nil
}
package ethereum
import (
"context"
"encoding/hex"
"flag"
"fmt"
"math/big"
"os"
"testing"
"time"
"github.com/33cn/chain33/client/mocks"
dbm "github.com/33cn/chain33/common/db"
_ "github.com/33cn/chain33/system"
chain33Types "github.com/33cn/chain33/types"
"github.com/33cn/chain33/util/testnode"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/generated"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethcontract/test/setup"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethinterface"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/ethtxs"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/events"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
relayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
tml "github.com/BurntSushi/toml"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/influxdata/influxdb/pkg/testing/assert"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
var (
configPath = flag.String("f", "./../../relayer.toml", "configfile")
chain33PrivateKeyStr = "0xd627968e445f2a41c92173225791bae1ba42126ae96c32f28f97ff8f226e5c68"
chain33AccountAddr = "1GTxrmuWiXavhcvsaH5w9whgVxUrWsUMdV"
passphrase = "123456hzj"
chainTestCfg = chain33Types.NewChain33Config(chain33Types.GetDefaultCfgstring())
// 0x8AFDADFC88a1087c9A1D6c0F5Dd04634b87F303a
deployerPrivateKey = "8656d2bc732a8a816a461ba5e2d8aac7c7f85c26a813df30d5327210465eb230"
// 0x92C8b16aFD6d423652559C6E266cBE1c29Bfd84f
ethValidatorAddrKeyA = "3fa21584ae2e4fd74db9b58e2386f5481607dfa4d7ba0617aaa7858e5025dc1e"
ethValidatorAddrKeyB = "a5f3063552f4483cfc20ac4f40f45b798791379862219de9e915c64722c1d400"
ethValidatorAddrKeyC = "bbf5e65539e9af0eb0cfac30bad475111054b09c11d668fc0731d54ea777471e"
ethValidatorAddrKeyD = "c9fa31d7984edf81b8ef3b40c761f1847f6fcd5711ab2462da97dc458f1f896b"
)
func Test_LockAndBurn(t *testing.T) {
var tx chain33Types.Transaction
var ret chain33Types.Reply
ret.IsOk = true
mockapi := &mocks.QueueProtocolAPI{}
// 这里对需要mock的方法打桩,Close是必须的,其它方法根据需要
mockapi.On("Close").Return()
mockapi.On("AddPushSubscribe", mock.Anything).Return(&ret, nil)
mockapi.On("CreateTransaction", mock.Anything).Return(&tx, nil)
mockapi.On("SendTx", mock.Anything).Return(&ret, nil)
mockapi.On("SendTransaction", mock.Anything).Return(&ret, nil)
mockapi.On("GetConfig", mock.Anything).Return(chainTestCfg, nil)
mock33 := testnode.New("", mockapi)
defer mock33.Close()
rpcCfg := mock33.GetCfg().RPC
// 这里必须设置监听端口,默认的是无效值
rpcCfg.JrpcBindAddr = "127.0.0.1:8801"
mock33.GetRPC().Listen()
fmt.Println("======================= testLockEth =======================")
testLockEth(t)
fmt.Println("======================= testCreateERC20Token =======================")
testCreateERC20Token(t)
fmt.Println("======================= testBurnBty =======================")
testBurnBty(t)
}
func Test_GetValidatorAddr(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
_, _, err = ethRelayer.NewAccount("123")
require.Nil(t, err)
privateKey, addr, err := ethRelayer.GetAccount("123")
require.Nil(t, err)
assert.NotEqual(t, privateKey, chain33PrivateKeyStr)
privateKey, addr, err = ethRelayer.GetAccount(passphrase)
require.Nil(t, err)
assert.Equal(t, privateKey, chain33PrivateKeyStr)
assert.Equal(t, addr, chain33AccountAddr)
validators, err := ethRelayer.GetValidatorAddr()
require.Nil(t, err)
assert.Equal(t, validators.Chain33Validator, chain33AccountAddr)
}
func Test_IsValidatorActive(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
is, err := ethRelayer.IsValidatorActive(para.InitValidators[0].String())
assert.Equal(t, is, true)
require.Nil(t, err)
is, err = ethRelayer.IsValidatorActive("0x0C05bA5c230fDaA503b53702aF1962e08D0C60BF")
assert.Equal(t, is, false)
require.Nil(t, err)
is, err = ethRelayer.IsValidatorActive("123")
require.Error(t, err)
}
func Test_ShowAddr(t *testing.T) {
{
cfg := initCfg(*configPath)
relayer := &Relayer4Ethereum{
provider: cfg.EthProvider,
unlockchan: make(chan int, 2),
rpcURL2Chain33: cfg.SyncTxConfig.Chain33Host,
maturityDegree: cfg.EthMaturityDegree,
fetchHeightPeriodMs: cfg.EthBlockFetchPeriod,
}
_, err := relayer.ShowBridgeBankAddr()
require.Error(t, err)
_, err = relayer.ShowBridgeRegistryAddr()
require.Error(t, err)
}
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
ethRelayer.prePareSubscribeEvent()
addr, err := ethRelayer.ShowBridgeBankAddr()
require.Nil(t, err)
assert.Equal(t, addr, x2EthDeployInfo.BridgeBank.Address.String())
addr, err = ethRelayer.ShowBridgeRegistryAddr()
require.Nil(t, err)
assert.Equal(t, addr, x2EthDeployInfo.BridgeRegistry.Address.String())
addr, err = ethRelayer.ShowOperator()
require.Nil(t, err)
assert.Equal(t, addr, para.Operator.String())
}
func Test_DeployContrcts(t *testing.T) {
_, sim, _, _ := deployContracts()
cfg := initCfg(*configPath)
cfg.SyncTxConfig.Dbdriver = "memdb"
db := dbm.NewDB("relayer_db_service", cfg.SyncTxConfig.Dbdriver, cfg.SyncTxConfig.DbPath, cfg.SyncTxConfig.DbCache)
relayer := &Relayer4Ethereum{
provider: cfg.EthProvider,
db: db,
unlockchan: make(chan int, 2),
rpcURL2Chain33: cfg.SyncTxConfig.Chain33Host,
maturityDegree: cfg.EthMaturityDegree,
fetchHeightPeriodMs: cfg.EthBlockFetchPeriod,
deployInfo: cfg.Deploy,
}
relayer.clientSpec = sim
relayer.clientChainID = big.NewInt(1)
deployPrivateKey, _ := crypto.ToECDSA(common.FromHex(relayer.deployInfo.DeployerPrivateKey))
deployerAddr := crypto.PubkeyToAddress(deployPrivateKey.PublicKey)
relayer.operatorInfo = &ethtxs.OperatorInfo{
PrivateKey: deployPrivateKey,
Address: deployerAddr,
}
_, err := relayer.DeployContrcts()
require.NoError(t, err)
}
func Test_SetBridgeRegistryAddr(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
_ = ethRelayer.setBridgeRegistryAddr(x2EthDeployInfo.BridgeRegistry.Address.String())
registrAddrInDB, err := ethRelayer.getBridgeRegistryAddr()
require.Nil(t, err)
assert.Equal(t, registrAddrInDB, x2EthDeployInfo.BridgeRegistry.Address.String())
}
func Test_CreateBridgeToken(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
balance, err := ethRelayer.GetBalance("", para.InitValidators[0].String())
require.Nil(t, err)
assert.Equal(t, balance, "10000000000")
tokenAddrbty, err := ethRelayer.CreateBridgeToken("BTY")
require.Nil(t, err)
require.NotEmpty(t, tokenAddrbty)
sim.Commit()
addr, err := ethRelayer.ShowTokenAddrBySymbol("BTY")
require.Nil(t, err)
assert.Equal(t, addr, tokenAddrbty)
decimals, err := ethRelayer.GetDecimals(tokenAddrbty)
require.Nil(t, err)
assert.Equal(t, decimals, uint8(8))
_, err = ethRelayer.Burn(para.InitValidators[0].String(), tokenAddrbty, chain33AccountAddr, "10")
require.Error(t, err)
_, err = ethRelayer.BurnAsync(para.InitValidators[0].String(), tokenAddrbty, chain33AccountAddr, "10")
require.Error(t, err)
}
func testLockEth(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
ctx := context.Background()
bridgeBankBalance, err := sim.BalanceAt(ctx, x2EthDeployInfo.BridgeBank.Address, nil)
require.Nil(t, err)
assert.Equal(t, bridgeBankBalance.Int64(), int64(0))
userOneAuth, err := ethtxs.PrepareAuth(sim, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
//lock 50 eth
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
ethAmount := big.NewInt(50)
userOneAuth.Value = ethAmount
_, err = x2EthContracts.BridgeBank.Lock(userOneAuth, chain33Sender, common.Address{}, ethAmount)
require.Nil(t, err)
sim.Commit()
bridgeBankBalance, err = sim.BalanceAt(ctx, x2EthDeployInfo.BridgeBank.Address, nil)
require.Nil(t, err)
assert.Equal(t, bridgeBankBalance.Int64(), ethAmount.Int64())
for i := 0; i < 11; i++ {
sim.Commit()
}
time.Sleep(time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
balance, err := ethRelayer.ShowLockStatics("")
require.Nil(t, err)
assert.Equal(t, balance, "50")
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
}
func testCreateERC20Token(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
tokenErc20Addr, err := ethRelayer.CreateERC20Token("testcc")
require.Nil(t, err)
require.NotEmpty(t, tokenErc20Addr)
sim.Commit()
_, err = ethRelayer.MintERC20Token(tokenErc20Addr, para.Deployer.String(), "20000000000000")
require.Nil(t, err)
sim.Commit()
balance, err := ethRelayer.ShowDepositStatics(tokenErc20Addr)
require.Nil(t, err)
assert.Equal(t, balance, "20000000000000")
claimID := crypto.Keccak256Hash(big.NewInt(50).Bytes())
bret, err := ethRelayer.IsProphecyPending(claimID)
require.Nil(t, err)
assert.Equal(t, bret, false)
txhash, err := ethRelayer.TransferToken(tokenErc20Addr, hexutil.Encode(crypto.FromECDSA(para.DeployPrivateKey)), ethRelayer.deployInfo.ValidatorsAddr[0], "100")
require.Nil(t, err)
sim.Commit()
_, err = ethRelayer.ShowTxReceipt(txhash)
require.Nil(t, err)
balance, err = ethRelayer.GetBalance(tokenErc20Addr, ethRelayer.deployInfo.ValidatorsAddr[0])
require.Nil(t, err)
assert.Equal(t, balance, "100")
balance, err = ethRelayer.GetBalance(tokenErc20Addr, para.Deployer.String())
require.Nil(t, err)
assert.Equal(t, balance, "19999999999900")
tx1 := ethRelayer.QueryTxhashRelay2Eth()
require.Empty(t, tx1)
tx2 := ethRelayer.QueryTxhashRelay2Chain33()
require.Empty(t, tx2)
tokenErc20Addrtestc, err := ethRelayer.CreateERC20Token("testc")
require.Nil(t, err)
require.NotEmpty(t, tokenErc20Addrtestc)
sim.Commit()
_, err = ethRelayer.MintERC20Token(tokenErc20Addrtestc, para.Deployer.String(), "10000000000000")
require.Nil(t, err)
sim.Commit()
balance, err = ethRelayer.ShowDepositStatics(tokenErc20Addrtestc)
require.Nil(t, err)
assert.Equal(t, balance, "10000000000000")
chain33Receiver := "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
_, err = ethRelayer.LockEthErc20Asset(hexutil.Encode(crypto.FromECDSA(para.DeployPrivateKey)), tokenErc20Addrtestc, "100", chain33Receiver)
require.Nil(t, err)
sim.Commit()
balance, err = ethRelayer.GetBalance(tokenErc20Addrtestc, para.Deployer.String())
require.Nil(t, err)
assert.Equal(t, balance, "9999999999900")
_, err = ethRelayer.ApproveAllowance(hexutil.Encode(crypto.FromECDSA(para.DeployPrivateKey)), tokenErc20Addrtestc, "500")
require.Nil(t, err)
sim.Commit()
_, err = ethRelayer.LockEthErc20AssetAsync(hexutil.Encode(crypto.FromECDSA(para.DeployPrivateKey)), tokenErc20Addrtestc, "100", chain33Receiver)
require.Nil(t, err)
sim.Commit()
balance, err = ethRelayer.GetBalance(tokenErc20Addrtestc, para.Deployer.String())
require.Nil(t, err)
assert.Equal(t, balance, "9999999999800")
for i := 0; i < 11; i++ {
sim.Commit()
}
time.Sleep(time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
}
func testBurnBty(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
tokenAddrbty, err := ethRelayer.CreateBridgeToken("bty")
require.Nil(t, err)
require.NotEmpty(t, tokenAddrbty)
sim.Commit()
chain33Sender := []byte("14KEKbYtKKQm4wMthSK9J4La4nAiidGozt")
amount := int64(100)
ethReceiver := para.InitValidators[2]
claimID := crypto.Keccak256Hash(chain33Sender, ethReceiver.Bytes(), big.NewInt(amount).Bytes())
authOracle, err := ethtxs.PrepareAuth(ethRelayer.clientSpec, para.ValidatorPriKey[0], para.InitValidators[0])
require.Nil(t, err)
signature, err := ethtxs.SignClaim4Eth(claimID, para.ValidatorPriKey[0])
require.Nil(t, err)
_, err = x2EthContracts.Oracle.NewOracleClaim(
authOracle,
events.ClaimTypeLock,
chain33Sender,
ethReceiver,
common.HexToAddress(tokenAddrbty),
"bty",
big.NewInt(amount),
claimID,
signature)
require.Nil(t, err)
sim.Commit()
balanceNew, err := ethRelayer.GetBalance(tokenAddrbty, ethReceiver.String())
require.Nil(t, err)
require.Equal(t, balanceNew, "100")
_, err = ethRelayer.Burn(hexutil.Encode(crypto.FromECDSA(para.ValidatorPriKey[2])), tokenAddrbty, chain33AccountAddr, "10")
require.NoError(t, err)
sim.Commit()
balanceNew, err = ethRelayer.GetBalance(tokenAddrbty, ethReceiver.String())
require.Nil(t, err)
require.Equal(t, balanceNew, "90")
_, err = ethRelayer.ApproveAllowance(hexutil.Encode(crypto.FromECDSA(para.ValidatorPriKey[2])), tokenAddrbty, "10")
require.Nil(t, err)
sim.Commit()
_, err = ethRelayer.BurnAsync(hexutil.Encode(crypto.FromECDSA(para.ValidatorPriKey[2])), tokenAddrbty, chain33AccountAddr, "10")
require.NoError(t, err)
sim.Commit()
balanceNew, err = ethRelayer.GetBalance(tokenAddrbty, ethReceiver.String())
require.Nil(t, err)
require.Equal(t, balanceNew, "80")
fetchCnt := int32(10)
logs, err := ethRelayer.getNextValidEthTxEventLogs(ethRelayer.eventLogIndex.Height, ethRelayer.eventLogIndex.Index, fetchCnt)
require.NoError(t, err)
for _, vLog := range logs {
ethRelayer.procBridgeBankLogs(*vLog)
}
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
}
func Test_RestorePrivateKeys(t *testing.T) {
para, sim, x2EthContracts, x2EthDeployInfo, err := setup.DeployContracts()
require.NoError(t, err)
ethRelayer := newEthRelayer(para, sim, x2EthContracts, x2EthDeployInfo)
_ = ethRelayer.ImportChain33PrivateKey(passphrase, chain33PrivateKeyStr)
time.Sleep(4 * time.Duration(ethRelayer.fetchHeightPeriodMs) * time.Millisecond)
go func() {
for range ethRelayer.unlockchan {
}
}()
ethRelayer.rwLock.RLock()
temp := ethRelayer.privateKey4Chain33
ethRelayer.rwLock.RUnlock()
err = ethRelayer.RestorePrivateKeys("123")
ethRelayer.rwLock.RLock()
assert.NotEqual(t, hex.EncodeToString(temp.Bytes()), hex.EncodeToString(ethRelayer.privateKey4Chain33.Bytes()))
ethRelayer.rwLock.RUnlock()
require.Nil(t, err)
err = ethRelayer.RestorePrivateKeys(passphrase)
ethRelayer.rwLock.RLock()
assert.Equal(t, hex.EncodeToString(temp.Bytes()), hex.EncodeToString(ethRelayer.privateKey4Chain33.Bytes()))
ethRelayer.rwLock.RUnlock()
require.Nil(t, err)
err = ethRelayer.StoreAccountWithNewPassphase("new123", passphrase)
require.Nil(t, err)
err = ethRelayer.RestorePrivateKeys("new123")
ethRelayer.rwLock.RLock()
assert.Equal(t, hex.EncodeToString(temp.Bytes()), hex.EncodeToString(ethRelayer.privateKey4Chain33.Bytes()))
ethRelayer.rwLock.RUnlock()
require.Nil(t, err)
}
func newEthRelayer(para *ethtxs.DeployPara, sim *ethinterface.SimExtend, x2EthContracts *ethtxs.X2EthContracts, x2EthDeployInfo *ethtxs.X2EthDeployInfo) *Relayer4Ethereum {
cfg := initCfg(*configPath)
cfg.SyncTxConfig.Chain33Host = "http://127.0.0.1:8801"
cfg.BridgeRegistry = x2EthDeployInfo.BridgeRegistry.Address.String()
cfg.SyncTxConfig.PushBind = "127.0.0.1:60000"
cfg.SyncTxConfig.FetchHeightPeriodMs = 50
cfg.SyncTxConfig.Dbdriver = "memdb"
cfg.SyncTxConfig.DbPath = "datadirEth"
db := dbm.NewDB("relayer_db_service", cfg.SyncTxConfig.Dbdriver, cfg.SyncTxConfig.DbPath, cfg.SyncTxConfig.DbCache)
relayer := &Relayer4Ethereum{
provider: cfg.EthProvider,
db: db,
unlockchan: make(chan int, 2),
rpcURL2Chain33: cfg.SyncTxConfig.Chain33Host,
bridgeRegistryAddr: x2EthDeployInfo.BridgeRegistry.Address,
maturityDegree: cfg.EthMaturityDegree,
fetchHeightPeriodMs: cfg.EthBlockFetchPeriod,
//deployInfo: cfg.Deploy,
}
relayer.deployInfo = &ebTypes.Deploy{}
relayer.deployInfo.DeployerPrivateKey = hexutil.Encode(crypto.FromECDSA(para.DeployPrivateKey))
relayer.deployInfo.OperatorAddr = para.Operator.String()
for _, v := range para.InitValidators {
relayer.deployInfo.ValidatorsAddr = append(relayer.deployInfo.ValidatorsAddr, v.String())
}
for _, v := range para.InitPowers {
relayer.deployInfo.InitPowers = append(relayer.deployInfo.InitPowers, v.Int64())
}
relayer.eventLogIndex = relayer.getLastBridgeBankProcessedHeight()
relayer.initBridgeBankTx()
relayer.clientSpec = sim
relayer.clientChainID = big.NewInt(1)
deployPrivateKey, _ := crypto.ToECDSA(common.FromHex(relayer.deployInfo.DeployerPrivateKey))
deployerAddr := crypto.PubkeyToAddress(deployPrivateKey.PublicKey)
relayer.rwLock.Lock()
relayer.operatorInfo = &ethtxs.OperatorInfo{
PrivateKey: deployPrivateKey,
Address: deployerAddr,
}
relayer.deployPara = para
relayer.x2EthContracts = x2EthContracts
relayer.x2EthDeployInfo = x2EthDeployInfo
relayer.rwLock.Unlock()
go relayer.proc()
return relayer
}
func deployContracts() (*ethtxs.DeployPara, *ethinterface.SimExtend, *ethtxs.X2EthContracts, *ethtxs.X2EthDeployInfo) {
ethValidatorAddrKeys := make([]string, 0)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyA)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyB)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyC)
ethValidatorAddrKeys = append(ethValidatorAddrKeys, ethValidatorAddrKeyD)
ctx := context.Background()
//var backend bind.ContractBackend
backend, para := setup.PrepareTestEnvironment(deployerPrivateKey, ethValidatorAddrKeys)
sim := new(ethinterface.SimExtend)
sim.SimulatedBackend = backend.(*backends.SimulatedBackend)
callMsg := ethereum.CallMsg{
From: para.Deployer,
Data: common.FromHex(generated.BridgeBankBin),
}
_, _ = sim.EstimateGas(ctx, callMsg)
x2EthContracts, x2EthDeployInfo, _ := ethtxs.DeployAndInit(sim, para)
sim.Commit()
return para, sim, x2EthContracts, x2EthDeployInfo
}
func initCfg(path string) *relayerTypes.RelayerConfig {
var cfg relayerTypes.RelayerConfig
if _, err := tml.DecodeFile(path, &cfg); err != nil {
//fmt.Println(err)
os.Exit(-1)
}
return &cfg
}
package ethereum
import (
"encoding/json"
"fmt"
"sync/atomic"
dbm "github.com/33cn/chain33/common/db"
chain33Types "github.com/33cn/chain33/types"
ebTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
"github.com/ethereum/go-ethereum/core/types"
)
var (
eth2chain33TxHashPrefix = "Eth2chain33TxHash"
eth2chain33TxTotalAmount = []byte("Eth2chain33TxTotalAmount")
chain33ToEthTxHashPrefix = "chain33ToEthTxHash"
bridgeRegistryAddrPrefix = []byte("x2EthBridgeRegistryAddr")
bridgeBankLogProcessedAt = []byte("bridgeBankLogProcessedAt")
ethTxEventPrefix = []byte("ethTxEventPrefix")
lastBridgeBankHeightProcPrefix = []byte("lastBridgeBankHeight")
)
func ethTxEventKey4Height(height uint64, index uint32) []byte {
return append(ethTxEventPrefix, []byte(fmt.Sprintf("%020d-%d", height, index))...)
}
func calcRelay2Chain33Txhash(txindex int64) []byte {
return []byte(fmt.Sprintf("%s-%012d", eth2chain33TxHashPrefix, txindex))
}
func (ethRelayer *Relayer4Ethereum) setBridgeRegistryAddr(bridgeRegistryAddr string) error {
return ethRelayer.db.Set(bridgeRegistryAddrPrefix, []byte(bridgeRegistryAddr))
}
func (ethRelayer *Relayer4Ethereum) getBridgeRegistryAddr() (string, error) {
addr, err := ethRelayer.db.Get(bridgeRegistryAddrPrefix)
if nil != err {
return "", err
}
return string(addr), nil
}
func (ethRelayer *Relayer4Ethereum) updateTotalTxAmount2chain33(total int64) error {
totalTx := &chain33Types.Int64{
Data: atomic.LoadInt64(&ethRelayer.totalTx4Eth2Chain33),
}
//更新成功见证的交易数
return ethRelayer.db.Set(eth2chain33TxTotalAmount, chain33Types.Encode(totalTx))
}
func (ethRelayer *Relayer4Ethereum) setLastestRelay2Chain33Txhash(txhash string, txIndex int64) error {
key := calcRelay2Chain33Txhash(txIndex)
return ethRelayer.db.Set(key, []byte(txhash))
}
func (ethRelayer *Relayer4Ethereum) queryTxhashes(prefix []byte) []string {
return utils.QueryTxhashes(prefix, ethRelayer.db)
}
func (ethRelayer *Relayer4Ethereum) setHeight4BridgeBankLogAt(height uint64) error {
return ethRelayer.setLogProcHeight(bridgeBankLogProcessedAt, height)
}
func (ethRelayer *Relayer4Ethereum) getHeight4BridgeBankLogAt() uint64 {
return ethRelayer.getLogProcHeight(bridgeBankLogProcessedAt)
}
func (ethRelayer *Relayer4Ethereum) setLogProcHeight(key []byte, height uint64) error {
data := &ebTypes.Uint64{
Data: height,
}
return ethRelayer.db.Set(key, chain33Types.Encode(data))
}
func (ethRelayer *Relayer4Ethereum) getLogProcHeight(key []byte) uint64 {
value, err := ethRelayer.db.Get(key)
if nil != err {
return 0
}
var height ebTypes.Uint64
err = chain33Types.Decode(value, &height)
if nil != err {
return 0
}
return height.Data
}
//保存处理过的交易
func (ethRelayer *Relayer4Ethereum) setTxProcessed(txhash []byte) error {
return ethRelayer.db.Set(txhash, []byte("1"))
}
//判断是否已经被处理,如果能够在数据库中找到该笔交易,则认为已经被处理
func (ethRelayer *Relayer4Ethereum) checkTxProcessed(txhash []byte) bool {
_, err := ethRelayer.db.Get(txhash)
return nil == err
}
func (ethRelayer *Relayer4Ethereum) setEthTxEvent(vLog types.Log) error {
key := ethTxEventKey4Height(vLog.BlockNumber, uint32(vLog.TxIndex))
value, err := json.Marshal(vLog)
if nil != err {
return err
}
return ethRelayer.db.Set(key, value)
}
func (ethRelayer *Relayer4Ethereum) getEthTxEvent(blockNumber uint64, txIndex uint32) (*types.Log, error) {
key := ethTxEventKey4Height(blockNumber, txIndex)
data, err := ethRelayer.db.Get(key)
if nil != err {
return nil, err
}
log := types.Log{}
err = json.Unmarshal(data, &log)
if err != nil {
return nil, err
}
return &log, nil
}
func (ethRelayer *Relayer4Ethereum) getNextValidEthTxEventLogs(height uint64, index uint32, fetchCnt int32) ([]*types.Log, error) {
key := ethTxEventKey4Height(height, index)
helper := dbm.NewListHelper(ethRelayer.db)
datas := helper.List(ethTxEventPrefix, key, fetchCnt, dbm.ListASC)
if nil == datas {
return nil, nil
}
var logs []*types.Log
for _, data := range datas {
log := &types.Log{}
err := json.Unmarshal(data, log)
if err != nil {
return nil, err
}
logs = append(logs, log)
}
return logs, nil
}
func (ethRelayer *Relayer4Ethereum) setBridgeBankProcessedHeight(height uint64, index uint32) {
bytes := chain33Types.Encode(&ebTypes.EventLogIndex{
Height: height,
Index: index})
_ = ethRelayer.db.Set(lastBridgeBankHeightProcPrefix, bytes)
}
func (ethRelayer *Relayer4Ethereum) getLastBridgeBankProcessedHeight() ebTypes.EventLogIndex {
data, err := ethRelayer.db.Get(lastBridgeBankHeightProcPrefix)
if nil != err {
return ebTypes.EventLogIndex{}
}
logIndex := ebTypes.EventLogIndex{}
_ = chain33Types.Decode(data, &logIndex)
return logIndex
}
//构建一个引导查询使用的bridgeBankTx
func (ethRelayer *Relayer4Ethereum) initBridgeBankTx() {
log, _ := ethRelayer.getEthTxEvent(0, 0)
if nil != log {
return
}
_ = ethRelayer.setEthTxEvent(types.Log{})
}
package relayer
import (
"errors"
"fmt"
"strconv"
"sync"
"sync/atomic"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/log/log15"
rpctypes "github.com/33cn/chain33/rpc/types"
chain33Types "github.com/33cn/chain33/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/relayer/chain33"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/relayer/ethereum"
relayerTypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/types"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/ebrelayer/utils"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
lru "github.com/hashicorp/golang-lru"
)
var (
mlog = log15.New("relayer manager", "manager")
)
const (
Locked = int32(1)
Unlocked = int32(99)
EncryptEnable = int64(1)
)
type Manager struct {
chain33Relayer *chain33.Relayer4Chain33
ethRelayer *ethereum.Relayer4Ethereum
store *Store
isLocked int32
mtx sync.Mutex
encryptFlag int64
passphase string
decimalLru *lru.Cache
}
//实现记录
//1.验证人的私钥需要通过cli命令行进行导入,且chain33和ethereum两种不同的验证人需要分别导入
//2.显示或者重新替换原有的私钥首先需要通过passpin进行unlock的操作
func NewRelayerManager(chain33Relayer *chain33.Relayer4Chain33, ethRelayer *ethereum.Relayer4Ethereum, db dbm.DB) *Manager {
l, _ := lru.New(4096)
manager := &Manager{
chain33Relayer: chain33Relayer,
ethRelayer: ethRelayer,
store: NewStore(db),
isLocked: Locked,
mtx: sync.Mutex{},
encryptFlag: 0,
passphase: "",
decimalLru: l,
}
manager.encryptFlag = manager.store.GetEncryptionFlag()
return manager
}
func (manager *Manager) SetPassphase(setPasswdReq relayerTypes.ReqSetPasswd, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
// 第一次设置密码的时候才使用 后面用 ChangePasswd
if EncryptEnable == manager.encryptFlag {
return errors.New("passphase alreade exists")
}
// 密码合法性校验
if !utils.IsValidPassWord(setPasswdReq.Passphase) {
return chain33Types.ErrInvalidPassWord
}
//使用密码生成passwdhash用于下次密码的验证
newBatch := manager.store.NewBatch(true)
err := manager.store.SetPasswordHash(setPasswdReq.Passphase, newBatch)
if err != nil {
mlog.Error("SetPassphase", "SetPasswordHash err", err)
return err
}
//设置钱包加密标志位
err = manager.store.SetEncryptionFlag(newBatch)
if err != nil {
mlog.Error("SetPassphase", "SetEncryptionFlag err", err)
return err
}
err = newBatch.Write()
if err != nil {
mlog.Error("ProcWalletSetPasswd newBatch.Write", "err", err)
return err
}
manager.passphase = setPasswdReq.Passphase
atomic.StoreInt64(&manager.encryptFlag, EncryptEnable)
*result = rpctypes.Reply{
IsOk: true,
Msg: "Succeed to set passphase",
}
return nil
}
func (manager *Manager) ChangePassphase(setPasswdReq relayerTypes.ReqChangePasswd, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if setPasswdReq.OldPassphase == setPasswdReq.NewPassphase {
return errors.New("the old password is the same as the new one")
}
// 新密码合法性校验
if !utils.IsValidPassWord(setPasswdReq.NewPassphase) {
return chain33Types.ErrInvalidPassWord
}
//保存钱包的锁状态,需要暂时的解锁,函数退出时再恢复回去
tempislock := atomic.LoadInt32(&manager.isLocked)
atomic.CompareAndSwapInt32(&manager.isLocked, Locked, Unlocked)
defer func() {
//wallet.isWalletLocked = tempislock
atomic.CompareAndSwapInt32(&manager.isLocked, Unlocked, tempislock)
}()
// 钱包已经加密需要验证oldpass的正确性
if len(manager.passphase) == 0 && manager.encryptFlag == EncryptEnable {
isok := manager.store.VerifyPasswordHash(setPasswdReq.OldPassphase)
if !isok {
mlog.Error("ChangePassphase Verify Oldpasswd fail!")
return chain33Types.ErrVerifyOldpasswdFail
}
}
if len(manager.passphase) != 0 && setPasswdReq.OldPassphase != manager.passphase {
mlog.Error("ChangePassphase Oldpass err!")
return chain33Types.ErrVerifyOldpasswdFail
}
//使用新的密码生成passwdhash用于下次密码的验证
newBatch := manager.store.NewBatch(true)
err := manager.store.SetPasswordHash(setPasswdReq.NewPassphase, newBatch)
if err != nil {
mlog.Error("ChangePassphase", "SetPasswordHash err", err)
return err
}
//设置钱包加密标志位
err = manager.store.SetEncryptionFlag(newBatch)
if err != nil {
mlog.Error("ChangePassphase", "SetEncryptionFlag err", err)
return err
}
err = manager.ethRelayer.StoreAccountWithNewPassphase(setPasswdReq.NewPassphase, setPasswdReq.OldPassphase)
if err != nil {
mlog.Error("ChangePassphase", "StoreAccountWithNewPassphase err", err)
return err
}
err = manager.chain33Relayer.StoreAccountWithNewPassphase(setPasswdReq.NewPassphase, setPasswdReq.OldPassphase)
if err != nil {
mlog.Error("ChangePassphase", "StoreAccountWithNewPassphase err", err)
return err
}
err = newBatch.Write()
if err != nil {
mlog.Error("ProcWalletSetPasswd newBatch.Write", "err", err)
return err
}
manager.passphase = setPasswdReq.NewPassphase
atomic.StoreInt64(&manager.encryptFlag, EncryptEnable)
*result = rpctypes.Reply{
IsOk: true,
Msg: "Succeed to change passphase",
}
return nil
}
//进行unlok操作
func (manager *Manager) Unlock(passphase string, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if EncryptEnable != manager.encryptFlag {
return errors.New("pls set passphase first")
}
if Unlocked == manager.isLocked {
return errors.New("unlock already")
}
if !manager.store.VerifyPasswordHash(passphase) {
return errors.New("wrong passphase")
}
if err := manager.chain33Relayer.RestorePrivateKeys(passphase); nil != err {
info := fmt.Sprintf("Failed to RestorePrivateKeys for chain33Relayer due to:%s", err.Error())
return errors.New(info)
}
if err := manager.ethRelayer.RestorePrivateKeys(passphase); nil != err {
info := fmt.Sprintf("Failed to RestorePrivateKeys for ethRelayer due to:%s", err.Error())
return errors.New(info)
}
manager.isLocked = Unlocked
manager.passphase = passphase
*result = rpctypes.Reply{
IsOk: true,
Msg: "Succeed to unlock",
}
return nil
}
//锁定操作,该操作一旦执行,就不能替换验证人的私钥,需要重新unlock之后才能修改
func (manager *Manager) Lock(param interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
manager.isLocked = Locked
*result = rpctypes.Reply{
IsOk: true,
Msg: "Succeed to lock",
}
return nil
}
//导入chain33relayer验证人的私钥,该私钥实际用于向ethereum提交验证交易时签名使用
func (manager *Manager) ImportChain33RelayerPrivateKey(importKeyReq relayerTypes.ImportKeyReq, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
privateKey := importKeyReq.PrivateKey
if err := manager.checkPermission(); nil != err {
return err
}
_, err := manager.chain33Relayer.ImportPrivateKey(manager.passphase, privateKey)
if err != nil {
mlog.Error("ImportChain33ValidatorPrivateKey", "Failed due to cause:", err.Error())
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: "Succeed to import private key for chain33 relayer",
}
return nil
}
//生成以太坊私钥
func (manager *Manager) GenerateEthereumPrivateKey(param interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
account4Show := relayerTypes.Account4Show{}
var err error
account4Show.Privkey, account4Show.Addr, err = manager.ethRelayer.NewAccount(manager.passphase)
if nil != err {
return err
}
*result = account4Show
return nil
}
//为ethrelayer导入chain33私钥,为向chain33发送交易时进行签名使用
func (manager *Manager) ImportChain33PrivateKey4EthRelayer(privateKey string, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
if err := manager.ethRelayer.ImportChain33PrivateKey(manager.passphase, privateKey); nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: "Succeed to import chain33 private key for ethereum relayer",
}
return nil
}
//显示在chain33中以验证人validator身份进行登录的地址
func (manager *Manager) ShowChain33RelayerValidator(param interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
var err error
*result, err = manager.chain33Relayer.GetAccountAddr()
if nil != err {
return err
}
return nil
}
//显示在Ethereum中以验证人validator身份进行登录的地址
func (manager *Manager) ShowEthRelayerValidator(param interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
var err error
*result, err = manager.ethRelayer.GetValidatorAddr()
if nil != err {
return err
}
return nil
}
func (manager *Manager) IsValidatorActive(vallidatorAddr string, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
active, err := manager.ethRelayer.IsValidatorActive(vallidatorAddr)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: active,
Msg: "",
}
return nil
}
func (manager *Manager) ShowOperator(param interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
operator, err := manager.ethRelayer.ShowOperator()
if nil != err {
return err
}
*result = operator
return nil
}
func (manager *Manager) DeployContrcts(param interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
bridgeRegistry, err := manager.ethRelayer.DeployContrcts()
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: fmt.Sprintf("Contract BridgeRegistry's address is:%s", bridgeRegistry),
}
return nil
}
func (manager *Manager) CreateBridgeToken(symbol string, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
tokenAddr, err := manager.ethRelayer.CreateBridgeToken(symbol)
if nil != err {
return err
}
*result = relayerTypes.ReplyAddr{
IsOK: true,
Addr: tokenAddr,
}
return nil
}
func (manager *Manager) CreateERC20Token(symbol string, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
tokenAddr, err := manager.ethRelayer.CreateERC20Token(symbol)
if nil != err {
return err
}
*result = relayerTypes.ReplyAddr{
IsOK: true,
Addr: tokenAddr,
}
return nil
}
func (manager *Manager) MintErc20(mintToken relayerTypes.MintToken, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
txhash, err := manager.ethRelayer.MintERC20Token(mintToken.TokenAddr, mintToken.Owner, mintToken.Amount)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: txhash,
}
return nil
}
func (manager *Manager) ApproveAllowance(approveAllowance relayerTypes.ApproveAllowance, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
txhash, err := manager.ethRelayer.ApproveAllowance(approveAllowance.OwnerKey, approveAllowance.TokenAddr, approveAllowance.Amount)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: txhash,
}
return nil
}
func (manager *Manager) Burn(burn relayerTypes.Burn, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
txhash, err := manager.ethRelayer.Burn(burn.OwnerKey, burn.TokenAddr, burn.Chain33Receiver, burn.Amount)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: txhash,
}
return nil
}
func (manager *Manager) BurnAsync(burn relayerTypes.Burn, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
txhash, err := manager.ethRelayer.BurnAsync(burn.OwnerKey, burn.TokenAddr, burn.Chain33Receiver, burn.Amount)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: txhash,
}
return nil
}
func (manager *Manager) LockEthErc20AssetAsync(lockEthErc20Asset relayerTypes.LockEthErc20, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
txhash, err := manager.ethRelayer.LockEthErc20AssetAsync(lockEthErc20Asset.OwnerKey, lockEthErc20Asset.TokenAddr, lockEthErc20Asset.Amount, lockEthErc20Asset.Chain33Receiver)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: txhash,
}
return nil
}
func (manager *Manager) LockEthErc20Asset(lockEthErc20Asset relayerTypes.LockEthErc20, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
if err := manager.checkPermission(); nil != err {
return err
}
txhash, err := manager.ethRelayer.LockEthErc20Asset(lockEthErc20Asset.OwnerKey, lockEthErc20Asset.TokenAddr, lockEthErc20Asset.Amount, lockEthErc20Asset.Chain33Receiver)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: txhash,
}
return nil
}
func (manager *Manager) IsProphecyPending(claimID [32]byte, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
active, err := manager.ethRelayer.IsProphecyPending(claimID)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: active,
}
return nil
}
func (manager *Manager) GetBalance(balanceAddr relayerTypes.BalanceAddr, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
balance, err := manager.ethRelayer.GetBalance(balanceAddr.TokenAddr, balanceAddr.Owner)
if nil != err {
return err
}
var d int64
if balanceAddr.TokenAddr == "" || balanceAddr.TokenAddr == "0x0000000000000000000000000000000000000000" {
d = 18
} else {
d, err = manager.GetDecimals(balanceAddr.TokenAddr)
if err != nil {
return errors.New("get decimals error")
}
}
*result = relayerTypes.ReplyBalance{
IsOK: true,
Balance: types.TrimZeroAndDot(strconv.FormatFloat(types.Toeth(balance, d), 'f', 4, 64)),
}
return nil
}
func (manager *Manager) ShowBridgeBankAddr(para interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
addr, err := manager.ethRelayer.ShowBridgeBankAddr()
if nil != err {
return err
}
*result = relayerTypes.ReplyAddr{
IsOK: true,
Addr: addr,
}
return nil
}
func (manager *Manager) ShowBridgeRegistryAddr(para interface{}, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
addr, err := manager.ethRelayer.ShowBridgeRegistryAddr()
if nil != err {
return err
}
*result = relayerTypes.ReplyAddr{
IsOK: true,
Addr: addr,
}
return nil
}
func (manager *Manager) ShowLockStatics(token relayerTypes.TokenStatics, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
balance, err := manager.ethRelayer.ShowLockStatics(token.TokenAddr)
if nil != err {
return err
}
var d int64
if token.TokenAddr == "" || token.TokenAddr == "0x0000000000000000000000000000000000000000" {
d = 18
} else {
d, err = manager.GetDecimals(token.TokenAddr)
if err != nil {
return errors.New("get decimals error")
}
}
*result = relayerTypes.StaticsLock{
Balance: strconv.FormatFloat(types.Toeth(balance, d), 'f', 4, 64),
}
return nil
}
func (manager *Manager) ShowDepositStatics(token relayerTypes.TokenStatics, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
supply, err := manager.ethRelayer.ShowDepositStatics(token.TokenAddr)
if nil != err {
return err
}
var d int64
if token.TokenAddr == "" || token.TokenAddr == "0x0000000000000000000000000000000000000000" {
d = 18
} else {
d, err = manager.GetDecimals(token.TokenAddr)
if err != nil {
return errors.New("get decimals error")
}
}
*result = relayerTypes.StaticsDeposit{
Supply: strconv.FormatFloat(types.Toeth(supply, d), 'f', 4, 64),
}
return nil
}
func (manager *Manager) ShowTokenAddrBySymbol(token relayerTypes.TokenStatics, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
addr, err := manager.ethRelayer.ShowTokenAddrBySymbol(token.TokenAddr)
if nil != err {
return err
}
*result = relayerTypes.ReplyAddr{
IsOK: true,
Addr: addr,
}
return nil
}
func (manager *Manager) ShowTxReceipt(txhash string, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
receipt, err := manager.ethRelayer.ShowTxReceipt(txhash)
if nil != err {
return err
}
*result = *receipt
return nil
}
func (manager *Manager) checkPermission() error {
if EncryptEnable != manager.encryptFlag {
return errors.New("pls set passphase first")
}
if Locked == manager.isLocked {
return errors.New("pls unlock this relay-manager first")
}
return nil
}
func (manager *Manager) ShowEthRelayer2EthTxs(param interface{}, result *interface{}) error {
*result = manager.ethRelayer.QueryTxhashRelay2Eth()
return nil
}
func (manager *Manager) ShowEthRelayer2Chain33Txs(param interface{}, result *interface{}) error {
*result = manager.ethRelayer.QueryTxhashRelay2Chain33()
return nil
}
func (manager *Manager) ShowChain33Relayer2EthTxs(param interface{}, result *interface{}) error {
*result = manager.chain33Relayer.QueryTxhashRelay2Eth()
return nil
}
func (manager *Manager) ShowTxsEth2chain33TxLock(param interface{}, result *interface{}) error {
return nil
}
func (manager *Manager) ShowTxsEth2chain33TxBurn(param interface{}, result *interface{}) error {
return nil
}
func (manager *Manager) ShowTxsChain33ToEthTxLock(param interface{}, result *interface{}) error {
return nil
}
func (manager *Manager) ShowTxsChain33ToEthTxBurn(param interface{}, result *interface{}) error {
return nil
}
func (manager *Manager) TransferToken(transfer relayerTypes.TransferToken, result *interface{}) error {
manager.mtx.Lock()
defer manager.mtx.Unlock()
txhash, err := manager.ethRelayer.TransferToken(transfer.TokenAddr, transfer.FromKey, transfer.ToAddr, transfer.Amount)
if nil != err {
return err
}
*result = rpctypes.Reply{
IsOk: true,
Msg: txhash,
}
return nil
}
func (manager *Manager) GetDecimals(tokenAddr string) (int64, error) {
if d, ok := manager.decimalLru.Get(tokenAddr); ok {
mlog.Info("GetDecimals", "from cache", d)
return d.(int64), nil
}
if d, err := manager.store.Get(utils.CalAddr2DecimalsPrefix(tokenAddr)); err == nil {
decimal, err := strconv.ParseInt(string(d), 10, 64)
if err != nil {
return 0, err
}
manager.decimalLru.Add(tokenAddr, decimal)
mlog.Info("GetDecimals", "from DB", d)
return decimal, nil
}
d, err := manager.ethRelayer.GetDecimals(tokenAddr)
if err != nil {
return 0, err
}
_ = manager.store.Set(utils.CalAddr2DecimalsPrefix(tokenAddr), []byte(strconv.FormatInt(int64(d), 10)))
manager.decimalLru.Add(tokenAddr, int64(d))
mlog.Info("GetDecimals", "from Node", d)
return int64(d), nil
}
package relayer
import (
"bytes"
"crypto/sha256"
"encoding/json"
"fmt"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
var (
storelog = log15.New("relayer manager", "store")
)
const (
keyEncryptionFlag = "Encryption"
keyEncryptionCompFlag = "EncryptionFlag" // 中间有一段时间运行了一个错误的密码版本,导致有部分用户信息发生错误,需要兼容下
keyPasswordHash = "PasswordHash"
)
// CalcEncryptionFlag 加密标志Key
func calcEncryptionFlag() []byte {
return []byte(keyEncryptionFlag)
}
// calckeyEncryptionCompFlag 加密比较标志Key
func calckeyEncryptionCompFlag() []byte {
return []byte(keyEncryptionCompFlag)
}
// CalcPasswordHash 密码hash的Key
func calcPasswordHash() []byte {
return []byte(keyPasswordHash)
}
// NewStore 新建存储对象
func NewStore(db db.DB) *Store {
return &Store{db: db}
}
// Store 钱包通用数据库存储类,实现对钱包账户数据库操作的基本实现
type Store struct {
db db.DB
}
// Close 关闭数据库
func (store *Store) Close() {
store.db.Close()
}
// GetDB 获取数据库操作接口
func (store *Store) GetDB() db.DB {
return store.db
}
// NewBatch 新建批处理操作对象接口
func (store *Store) NewBatch(sync bool) db.Batch {
return store.db.NewBatch(sync)
}
// Get 取值
func (store *Store) Get(key []byte) ([]byte, error) {
return store.db.Get(key)
}
// Set 设置值
func (store *Store) Set(key []byte, value []byte) (err error) {
return store.db.Set(key, value)
}
// NewListHelper 新建列表复制操作对象
func (store *Store) NewListHelper() *db.ListHelper {
return db.NewListHelper(store.db)
}
// SetEncryptionFlag 设置加密方式标志
func (store *Store) SetEncryptionFlag(batch db.Batch) error {
var flag int64 = 1
data, err := json.Marshal(flag)
if err != nil {
storelog.Error("SetEncryptionFlag marshal flag", "err", err)
return types.ErrMarshal
}
batch.Set(calcEncryptionFlag(), data)
return nil
}
// GetEncryptionFlag 获取加密方式
func (store *Store) GetEncryptionFlag() int64 {
var flag int64
data, err := store.Get(calcEncryptionFlag())
if data == nil || err != nil {
data, err = store.Get(calckeyEncryptionCompFlag())
if data == nil || err != nil {
return 0
}
}
err = json.Unmarshal(data, &flag)
if err != nil {
storelog.Error("GetEncryptionFlag unmarshal", "err", err)
return 0
}
return flag
}
// SetPasswordHash 保存密码哈希
func (store *Store) SetPasswordHash(password string, batch db.Batch) error {
var WalletPwHash types.WalletPwHash
//获取一个随机字符串
randstr := fmt.Sprintf("fuzamei:$@%s", crypto.CRandHex(16))
WalletPwHash.Randstr = randstr
//通过password和随机字符串生成一个hash值
pwhashstr := fmt.Sprintf("%s:%s", password, WalletPwHash.Randstr)
pwhash := sha256.Sum256([]byte(pwhashstr))
WalletPwHash.PwHash = pwhash[:]
pwhashbytes, err := json.Marshal(WalletPwHash)
if err != nil {
storelog.Error("SetEncryptionFlag marshal flag", "err", err)
return types.ErrMarshal
}
batch.Set(calcPasswordHash(), pwhashbytes)
return nil
}
// VerifyPasswordHash 检查密码有效性
func (store *Store) VerifyPasswordHash(password string) bool {
var WalletPwHash types.WalletPwHash
pwhashbytes, err := store.Get(calcPasswordHash())
if pwhashbytes == nil || err != nil {
return false
}
err = json.Unmarshal(pwhashbytes, &WalletPwHash)
if err != nil {
storelog.Error("VerifyPasswordHash unmarshal", "err", err)
return false
}
pwhashstr := fmt.Sprintf("%s:%s", password, WalletPwHash.Randstr)
pwhash := sha256.Sum256([]byte(pwhashstr))
Pwhash := pwhash[:]
//通过新的密码计算pwhash最对比
return bytes.Equal(WalletPwHash.GetPwHash(), Pwhash)
}
// Code generated by protoc-gen-go.
// source: config.proto
// DO NOT EDIT!
/*
Package types is a generated protocol buffer package.
It is generated from these files:
config.proto
relayer.proto
It has these top-level messages:
SyncTxConfig
Log
RelayerConfig
SyncTxReceiptConfig
Deploy
*/
package types
import proto "github.com/golang/protobuf/proto"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
type SyncTxConfig struct {
Chain33Host string `protobuf:"bytes,1,opt,name=chain33host" json:"chain33host,omitempty"`
PushHost string `protobuf:"bytes,2,opt,name=pushHost" json:"pushHost,omitempty"`
PushName string `protobuf:"bytes,3,opt,name=pushName" json:"pushName,omitempty"`
PushBind string `protobuf:"bytes,4,opt,name=pushBind" json:"pushBind,omitempty"`
MaturityDegree int32 `protobuf:"varint,5,opt,name=maturityDegree" json:"maturityDegree,omitempty"`
Dbdriver string `protobuf:"bytes,6,opt,name=dbdriver" json:"dbdriver,omitempty"`
DbPath string `protobuf:"bytes,7,opt,name=dbPath" json:"dbPath,omitempty"`
DbCache int32 `protobuf:"varint,8,opt,name=dbCache" json:"dbCache,omitempty"`
FetchHeightPeriodMs int64 `protobuf:"varint,9,opt,name=fetchHeightPeriodMs" json:"fetchHeightPeriodMs,omitempty"`
StartSyncHeight int64 `protobuf:"varint,10,opt,name=startSyncHeight" json:"startSyncHeight,omitempty"`
StartSyncSequence int64 `protobuf:"varint,11,opt,name=startSyncSequence" json:"startSyncSequence,omitempty"`
StartSyncHash string `protobuf:"bytes,12,opt,name=startSyncHash" json:"startSyncHash,omitempty"`
}
func (m *SyncTxConfig) Reset() { *m = SyncTxConfig{} }
func (m *SyncTxConfig) String() string { return proto.CompactTextString(m) }
func (*SyncTxConfig) ProtoMessage() {}
type Log struct {
Loglevel string `protobuf:"bytes,1,opt,name=loglevel" json:"loglevel,omitempty"`
LogConsoleLevel string `protobuf:"bytes,2,opt,name=logConsoleLevel" json:"logConsoleLevel,omitempty"`
LogFile string `protobuf:"bytes,3,opt,name=logFile" json:"logFile,omitempty"`
MaxFileSize uint32 `protobuf:"varint,4,opt,name=maxFileSize" json:"maxFileSize,omitempty"`
MaxBackups uint32 `protobuf:"varint,5,opt,name=maxBackups" json:"maxBackups,omitempty"`
MaxAge uint32 `protobuf:"varint,6,opt,name=maxAge" json:"maxAge,omitempty"`
LocalTime bool `protobuf:"varint,7,opt,name=localTime" json:"localTime,omitempty"`
Compress bool `protobuf:"varint,8,opt,name=compress" json:"compress,omitempty"`
CallerFile bool `protobuf:"varint,9,opt,name=callerFile" json:"callerFile,omitempty"`
CallerFunction bool `protobuf:"varint,10,opt,name=callerFunction" json:"callerFunction,omitempty"`
}
func (m *Log) Reset() { *m = Log{} }
func (m *Log) String() string { return proto.CompactTextString(m) }
func (*Log) ProtoMessage() {}
type RelayerConfig struct {
Title string `protobuf:"bytes,1,opt,name=title" json:"title,omitempty"`
SyncTxConfig *SyncTxConfig `protobuf:"bytes,2,opt,name=syncTxConfig" json:"syncTxConfig,omitempty"`
Log *Log `protobuf:"bytes,3,opt,name=log" json:"log,omitempty"`
JrpcBindAddr string `protobuf:"bytes,4,opt,name=jrpcBindAddr" json:"jrpcBindAddr,omitempty"`
EthProvider string `protobuf:"bytes,5,opt,name=ethProvider" json:"ethProvider,omitempty"`
BridgeRegistry string `protobuf:"bytes,6,opt,name=bridgeRegistry" json:"bridgeRegistry,omitempty"`
Deploy *Deploy `protobuf:"bytes,7,opt,name=deploy" json:"deploy,omitempty"`
EthMaturityDegree int32 `protobuf:"varint,8,opt,name=ethMaturityDegree" json:"ethMaturityDegree,omitempty"`
EthBlockFetchPeriod int32 `protobuf:"varint,9,opt,name=ethBlockFetchPeriod" json:"ethBlockFetchPeriod,omitempty"`
}
func (m *RelayerConfig) Reset() { *m = RelayerConfig{} }
func (m *RelayerConfig) String() string { return proto.CompactTextString(m) }
func (*RelayerConfig) ProtoMessage() {}
func (m *RelayerConfig) GetSyncTxConfig() *SyncTxConfig {
if m != nil {
return m.SyncTxConfig
}
return nil
}
func (m *RelayerConfig) GetLog() *Log {
if m != nil {
return m.Log
}
return nil
}
func (m *RelayerConfig) GetDeploy() *Deploy {
if m != nil {
return m.Deploy
}
return nil
}
type SyncTxReceiptConfig struct {
Chain33Host string `protobuf:"bytes,1,opt,name=chain33host" json:"chain33host,omitempty"`
PushHost string `protobuf:"bytes,2,opt,name=pushHost" json:"pushHost,omitempty"`
PushName string `protobuf:"bytes,3,opt,name=pushName" json:"pushName,omitempty"`
PushBind string `protobuf:"bytes,4,opt,name=pushBind" json:"pushBind,omitempty"`
StartSyncHeight int64 `protobuf:"varint,5,opt,name=startSyncHeight" json:"startSyncHeight,omitempty"`
StartSyncSequence int64 `protobuf:"varint,6,opt,name=startSyncSequence" json:"startSyncSequence,omitempty"`
StartSyncHash string `protobuf:"bytes,7,opt,name=startSyncHash" json:"startSyncHash,omitempty"`
}
func (m *SyncTxReceiptConfig) Reset() { *m = SyncTxReceiptConfig{} }
func (m *SyncTxReceiptConfig) String() string { return proto.CompactTextString(m) }
func (*SyncTxReceiptConfig) ProtoMessage() {}
type Deploy struct {
// 操作管理员地址
OperatorAddr string `protobuf:"bytes,1,opt,name=operatorAddr" json:"operatorAddr,omitempty"`
// 合约部署人员私钥,用于部署合约时签名使用
DeployerPrivateKey string `protobuf:"bytes,2,opt,name=deployerPrivateKey" json:"deployerPrivateKey,omitempty"`
// 验证人地址
ValidatorsAddr []string `protobuf:"bytes,3,rep,name=validatorsAddr" json:"validatorsAddr,omitempty"`
// 验证人权重
InitPowers []int64 `protobuf:"varint,4,rep,name=initPowers" json:"initPowers,omitempty"`
}
func (m *Deploy) Reset() { *m = Deploy{} }
func (m *Deploy) String() string { return proto.CompactTextString(m) }
func (*Deploy) ProtoMessage() {}
func init() {
}
package types
import (
"errors"
)
// relayer定义的错误类型
var (
ErrInvalidEthContractAddress = errors.New("ErrInvalidEthContractAddress")
ErrUnpack = errors.New("ErrUnpack")
ErrEmptyAddress = errors.New("ErrEmptyAddress")
ErrAddress4Eth = errors.New("symbol \"eth\" must have null address set as token address")
ErrPublicKeyType = errors.New("ErrPublicKeyType")
ErrInvalidContractAddress = errors.New("ErrInvalidTargetContractAddress")
ErrNoValidatorConfigured = errors.New("ErrNoValidatorConfigured")
)
package types
import (
"fmt"
"reflect"
gethCommon "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
// EthereumAddress defines a standard ethereum address
type EthereumAddress gethCommon.Address
// NewEthereumAddress is a constructor function for EthereumAddress
func NewEthereumAddress(address string) EthereumAddress {
return EthereumAddress(gethCommon.HexToAddress(address))
}
// Route should return the name of the module
func (ethAddr EthereumAddress) String() string {
return gethCommon.Address(ethAddr).String()
}
// MarshalJSON marshals the etherum address to JSON
func (ethAddr EthereumAddress) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("\"%v\"", ethAddr.String())), nil
}
// UnmarshalJSON unmarshals an ethereum address
func (ethAddr *EthereumAddress) UnmarshalJSON(input []byte) error {
return hexutil.UnmarshalFixedJSON(reflect.TypeOf(gethCommon.Address{}), input, ethAddr[:])
}
package types
const Version4Relayer = "0.1.0"
const (
StatusPending = iota
// Oracle : oracle contract
StatusRunning
)
syntax = "proto3";
package types;
message SyncTxConfig {
string chain33host = 1;
string pushHost = 2;
string pushName = 3;
string pushBind = 4;
int32 maturityDegree = 5;
string dbdriver = 6; //数据库类型
string dbPath = 7; //数据库存储目录
int32 dbCache = 8; //数据库缓存大小
int64 fetchHeightPeriodMs = 9;
int64 startSyncHeight = 10;
int64 startSyncSequence = 11;
string startSyncHash = 12;
}
message Log {
string loglevel = 1;
string logConsoleLevel = 2;
string logFile = 3;
uint32 maxFileSize = 4;
uint32 maxBackups = 5;
uint32 maxAge = 6;
bool localTime = 7;
bool compress = 8;
bool callerFile = 9;
bool callerFunction = 10;
}
message RelayerConfig {
string title = 1;
SyncTxConfig syncTxConfig = 2;
Log log = 3;
string jrpcBindAddr = 4; // Jrpc服务地址
string ethProvider = 5;
string bridgeRegistry = 6;
Deploy deploy = 7;
int32 ethMaturityDegree = 8;
int32 ethBlockFetchPeriod = 9;
}
message SyncTxReceiptConfig {
string chain33host = 1;
string pushHost = 2;
string pushName = 3;
string pushBind = 4;
int64 startSyncHeight = 5;
int64 startSyncSequence = 6;
string startSyncHash = 7;
}
message Deploy {
//操作管理员地址
string operatorAddr = 1;
//合约部署人员私钥,用于部署合约时签名使用
string deployerPrivateKey = 2;
//验证人地址
repeated string validatorsAddr = 3;
//验证人权重
repeated int64 initPowers = 4;
}
\ No newline at end of file
#!/bin/sh
protoc --go_out=../../types ./*.proto --proto_path=.
syntax = "proto3";
package types;
//以太坊账户信息
// privkey : 账户地址对应的私钥
// addr :账户地址
message Account4Relayer {
bytes privkey = 1;
string addr = 2;
}
message ValidatorAddr4EthRelayer {
string chain33Validator = 1;
}
message Txhashes {
repeated string txhash = 1;
}
message ReqChangePasswd {
string oldPassphase = 1;
string newPassphase = 2;
}
message ReqSetPasswd {
string Passphase = 1;
}
message Account4Show {
string privkey = 1;
string addr = 2;
}
message assetType {
string chain = 1;
string issueContract = 2;
string symbol = 3;
}
message EthBridgeClaim {
int64 ethereumChainID = 1;
string bridgeBrankAddr = 2;
int64 nonce = 3;
string tokenAddr = 4;
string symbol = 5;
string ethereumSender = 6;
string chain33Receiver = 7;
string amount = 9;
int32 claimType = 10;
string chainName = 11;
int64 decimal = 12;
}
message ImportKeyReq {
string privateKey = 1;
}
message RelayerRunStatus {
int32 status = 1;
string details = 2;
}
message NewProphecyClaim {
uint32 claimType = 1;
string chain33Sender = 2;
string tokenAddr = 3;
string symbol = 4;
string ethReceiver = 5;
string amount = 6;
string txHash = 7;
}
message BalanceAddr {
string owner = 1;
string tokenAddr = 2;
}
message MintToken {
string owner = 1;
string tokenAddr = 2;
string amount = 3;
}
message ApproveAllowance {
string ownerKey = 1;
string tokenAddr = 2;
string amount = 3;
}
message LockEthErc20 {
string ownerKey = 1;
string tokenAddr = 2;
string amount = 3;
//将lock住的资产跨链转移到chain33的该账户名下
string chain33Receiver = 4;
}
message ReplyAddr {
bool isOK =1;
string addr =2;
}
message ReplyBalance {
bool isOK =1;
string balance =2;
}
message Burn {
string ownerKey = 1;
string tokenAddr = 2;
string amount = 3;
string chain33Receiver = 4;
}
message StaticsRequest {
string owner = 1;
string tokenAddr = 2;
}
message StaticsAll {
}
message StaticsSingle {
}
message StaticsLockResponse {
StaticsLock all = 1;
StaticsLockSingle single = 2;
}
message StaticsResponse {
}
message StaticsLock {
string balance = 1;
}
message StaticsDeposit {
string supply = 1;
}
message StaticsLockSingle {
int64 totalLockedAccumated = 1;
repeated int64 locked = 2;
}
message TransferToken {
string tokenAddr = 1;
string fromKey = 2;
string toAddr = 3;
string amount = 4;
}
message Uint64 {
uint64 data = 1;
}
message TokenStatics {
string tokenAddr = 1;
}
message EventLogIndex {
uint64 height = 1;
uint32 index = 2;
}
message EthTxStatus {
string status = 1;
string txhash = 2;
}
\ No newline at end of file
// Code generated by protoc-gen-go.
// source: relayer.proto
// DO NOT EDIT!
package types
import proto "github.com/golang/protobuf/proto"
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
// 以太坊账户信息
// privkey : 账户地址对应的私钥
// addr :账户地址
type Account4Relayer struct {
Privkey []byte `protobuf:"bytes,1,opt,name=privkey,proto3" json:"privkey,omitempty"`
Addr string `protobuf:"bytes,2,opt,name=addr" json:"addr,omitempty"`
}
func (m *Account4Relayer) Reset() { *m = Account4Relayer{} }
func (m *Account4Relayer) String() string { return proto.CompactTextString(m) }
func (*Account4Relayer) ProtoMessage() {}
type ValidatorAddr4EthRelayer struct {
Chain33Validator string `protobuf:"bytes,1,opt,name=chain33Validator" json:"chain33Validator,omitempty"`
}
func (m *ValidatorAddr4EthRelayer) Reset() { *m = ValidatorAddr4EthRelayer{} }
func (m *ValidatorAddr4EthRelayer) String() string { return proto.CompactTextString(m) }
func (*ValidatorAddr4EthRelayer) ProtoMessage() {}
type Txhashes struct {
Txhash []string `protobuf:"bytes,1,rep,name=txhash" json:"txhash,omitempty"`
}
func (m *Txhashes) Reset() { *m = Txhashes{} }
func (m *Txhashes) String() string { return proto.CompactTextString(m) }
func (*Txhashes) ProtoMessage() {}
type ReqChangePasswd struct {
OldPassphase string `protobuf:"bytes,1,opt,name=oldPassphase" json:"oldPassphase,omitempty"`
NewPassphase string `protobuf:"bytes,2,opt,name=newPassphase" json:"newPassphase,omitempty"`
}
func (m *ReqChangePasswd) Reset() { *m = ReqChangePasswd{} }
func (m *ReqChangePasswd) String() string { return proto.CompactTextString(m) }
func (*ReqChangePasswd) ProtoMessage() {}
type ReqSetPasswd struct {
Passphase string `protobuf:"bytes,1,opt" json:"Passphase,omitempty"`
}
func (m *ReqSetPasswd) Reset() { *m = ReqSetPasswd{} }
func (m *ReqSetPasswd) String() string { return proto.CompactTextString(m) }
func (*ReqSetPasswd) ProtoMessage() {}
type Account4Show struct {
Privkey string `protobuf:"bytes,1,opt,name=privkey" json:"privkey,omitempty"`
Addr string `protobuf:"bytes,2,opt,name=addr" json:"addr,omitempty"`
}
func (m *Account4Show) Reset() { *m = Account4Show{} }
func (m *Account4Show) String() string { return proto.CompactTextString(m) }
func (*Account4Show) ProtoMessage() {}
type AssetType struct {
Chain string `protobuf:"bytes,1,opt,name=chain" json:"chain,omitempty"`
IssueContract string `protobuf:"bytes,2,opt,name=issueContract" json:"issueContract,omitempty"`
Symbol string `protobuf:"bytes,3,opt,name=symbol" json:"symbol,omitempty"`
}
func (m *AssetType) Reset() { *m = AssetType{} }
func (m *AssetType) String() string { return proto.CompactTextString(m) }
func (*AssetType) ProtoMessage() {}
type EthBridgeClaim struct {
EthereumChainID int64 `protobuf:"varint,1,opt,name=ethereumChainID" json:"ethereumChainID,omitempty"`
BridgeBrankAddr string `protobuf:"bytes,2,opt,name=bridgeBrankAddr" json:"bridgeBrankAddr,omitempty"`
Nonce int64 `protobuf:"varint,3,opt,name=nonce" json:"nonce,omitempty"`
TokenAddr string `protobuf:"bytes,4,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
Symbol string `protobuf:"bytes,5,opt,name=symbol" json:"symbol,omitempty"`
EthereumSender string `protobuf:"bytes,6,opt,name=ethereumSender" json:"ethereumSender,omitempty"`
Chain33Receiver string `protobuf:"bytes,7,opt,name=chain33Receiver" json:"chain33Receiver,omitempty"`
Amount string `protobuf:"bytes,9,opt,name=amount" json:"amount,omitempty"`
ClaimType int32 `protobuf:"varint,10,opt,name=claimType" json:"claimType,omitempty"`
ChainName string `protobuf:"bytes,11,opt,name=chainName" json:"chainName,omitempty"`
Decimal int64 `protobuf:"varint,12,opt,name=decimal" json:"decimal,omitempty"`
}
func (m *EthBridgeClaim) Reset() { *m = EthBridgeClaim{} }
func (m *EthBridgeClaim) String() string { return proto.CompactTextString(m) }
func (*EthBridgeClaim) ProtoMessage() {}
type ImportKeyReq struct {
PrivateKey string `protobuf:"bytes,1,opt,name=privateKey" json:"privateKey,omitempty"`
}
func (m *ImportKeyReq) Reset() { *m = ImportKeyReq{} }
func (m *ImportKeyReq) String() string { return proto.CompactTextString(m) }
func (*ImportKeyReq) ProtoMessage() {}
type RelayerRunStatus struct {
Status int32 `protobuf:"varint,1,opt,name=status" json:"status,omitempty"`
Details string `protobuf:"bytes,2,opt,name=details" json:"details,omitempty"`
}
func (m *RelayerRunStatus) Reset() { *m = RelayerRunStatus{} }
func (m *RelayerRunStatus) String() string { return proto.CompactTextString(m) }
func (*RelayerRunStatus) ProtoMessage() {}
type NewProphecyClaim struct {
ClaimType uint32 `protobuf:"varint,1,opt,name=claimType" json:"claimType,omitempty"`
Chain33Sender string `protobuf:"bytes,2,opt,name=chain33Sender" json:"chain33Sender,omitempty"`
TokenAddr string `protobuf:"bytes,3,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
Symbol string `protobuf:"bytes,4,opt,name=symbol" json:"symbol,omitempty"`
EthReceiver string `protobuf:"bytes,5,opt,name=ethReceiver" json:"ethReceiver,omitempty"`
Amount string `protobuf:"bytes,6,opt,name=amount" json:"amount,omitempty"`
TxHash string `protobuf:"bytes,7,opt,name=txHash" json:"txHash,omitempty"`
}
func (m *NewProphecyClaim) Reset() { *m = NewProphecyClaim{} }
func (m *NewProphecyClaim) String() string { return proto.CompactTextString(m) }
func (*NewProphecyClaim) ProtoMessage() {}
type BalanceAddr struct {
Owner string `protobuf:"bytes,1,opt,name=owner" json:"owner,omitempty"`
TokenAddr string `protobuf:"bytes,2,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
}
func (m *BalanceAddr) Reset() { *m = BalanceAddr{} }
func (m *BalanceAddr) String() string { return proto.CompactTextString(m) }
func (*BalanceAddr) ProtoMessage() {}
type MintToken struct {
Owner string `protobuf:"bytes,1,opt,name=owner" json:"owner,omitempty"`
TokenAddr string `protobuf:"bytes,2,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
Amount string `protobuf:"bytes,3,opt,name=amount" json:"amount,omitempty"`
}
func (m *MintToken) Reset() { *m = MintToken{} }
func (m *MintToken) String() string { return proto.CompactTextString(m) }
func (*MintToken) ProtoMessage() {}
type ApproveAllowance struct {
OwnerKey string `protobuf:"bytes,1,opt,name=ownerKey" json:"ownerKey,omitempty"`
TokenAddr string `protobuf:"bytes,2,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
Amount string `protobuf:"bytes,3,opt,name=amount" json:"amount,omitempty"`
}
func (m *ApproveAllowance) Reset() { *m = ApproveAllowance{} }
func (m *ApproveAllowance) String() string { return proto.CompactTextString(m) }
func (*ApproveAllowance) ProtoMessage() {}
type LockEthErc20 struct {
OwnerKey string `protobuf:"bytes,1,opt,name=ownerKey" json:"ownerKey,omitempty"`
TokenAddr string `protobuf:"bytes,2,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
Amount string `protobuf:"bytes,3,opt,name=amount" json:"amount,omitempty"`
// 将lock住的资产跨链转移到chain33的该账户名下
Chain33Receiver string `protobuf:"bytes,4,opt,name=chain33Receiver" json:"chain33Receiver,omitempty"`
}
func (m *LockEthErc20) Reset() { *m = LockEthErc20{} }
func (m *LockEthErc20) String() string { return proto.CompactTextString(m) }
func (*LockEthErc20) ProtoMessage() {}
type ReplyAddr struct {
IsOK bool `protobuf:"varint,1,opt,name=isOK" json:"isOK,omitempty"`
Addr string `protobuf:"bytes,2,opt,name=addr" json:"addr,omitempty"`
}
func (m *ReplyAddr) Reset() { *m = ReplyAddr{} }
func (m *ReplyAddr) String() string { return proto.CompactTextString(m) }
func (*ReplyAddr) ProtoMessage() {}
type ReplyBalance struct {
IsOK bool `protobuf:"varint,1,opt,name=isOK" json:"isOK,omitempty"`
Balance string `protobuf:"bytes,2,opt,name=balance" json:"balance,omitempty"`
}
func (m *ReplyBalance) Reset() { *m = ReplyBalance{} }
func (m *ReplyBalance) String() string { return proto.CompactTextString(m) }
func (*ReplyBalance) ProtoMessage() {}
type Burn struct {
OwnerKey string `protobuf:"bytes,1,opt,name=ownerKey" json:"ownerKey,omitempty"`
TokenAddr string `protobuf:"bytes,2,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
Amount string `protobuf:"bytes,3,opt,name=amount" json:"amount,omitempty"`
Chain33Receiver string `protobuf:"bytes,4,opt,name=chain33Receiver" json:"chain33Receiver,omitempty"`
}
func (m *Burn) Reset() { *m = Burn{} }
func (m *Burn) String() string { return proto.CompactTextString(m) }
func (*Burn) ProtoMessage() {}
type StaticsRequest struct {
Owner string `protobuf:"bytes,1,opt,name=owner" json:"owner,omitempty"`
TokenAddr string `protobuf:"bytes,2,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
}
func (m *StaticsRequest) Reset() { *m = StaticsRequest{} }
func (m *StaticsRequest) String() string { return proto.CompactTextString(m) }
func (*StaticsRequest) ProtoMessage() {}
type StaticsAll struct {
}
func (m *StaticsAll) Reset() { *m = StaticsAll{} }
func (m *StaticsAll) String() string { return proto.CompactTextString(m) }
func (*StaticsAll) ProtoMessage() {}
type StaticsSingle struct {
}
func (m *StaticsSingle) Reset() { *m = StaticsSingle{} }
func (m *StaticsSingle) String() string { return proto.CompactTextString(m) }
func (*StaticsSingle) ProtoMessage() {}
type StaticsLockResponse struct {
All *StaticsLock `protobuf:"bytes,1,opt,name=all" json:"all,omitempty"`
Single *StaticsLockSingle `protobuf:"bytes,2,opt,name=single" json:"single,omitempty"`
}
func (m *StaticsLockResponse) Reset() { *m = StaticsLockResponse{} }
func (m *StaticsLockResponse) String() string { return proto.CompactTextString(m) }
func (*StaticsLockResponse) ProtoMessage() {}
func (m *StaticsLockResponse) GetAll() *StaticsLock {
if m != nil {
return m.All
}
return nil
}
func (m *StaticsLockResponse) GetSingle() *StaticsLockSingle {
if m != nil {
return m.Single
}
return nil
}
type StaticsResponse struct {
}
func (m *StaticsResponse) Reset() { *m = StaticsResponse{} }
func (m *StaticsResponse) String() string { return proto.CompactTextString(m) }
func (*StaticsResponse) ProtoMessage() {}
type StaticsLock struct {
Balance string `protobuf:"bytes,1,opt,name=balance" json:"balance,omitempty"`
}
func (m *StaticsLock) Reset() { *m = StaticsLock{} }
func (m *StaticsLock) String() string { return proto.CompactTextString(m) }
func (*StaticsLock) ProtoMessage() {}
type StaticsDeposit struct {
Supply string `protobuf:"bytes,1,opt,name=supply" json:"supply,omitempty"`
}
func (m *StaticsDeposit) Reset() { *m = StaticsDeposit{} }
func (m *StaticsDeposit) String() string { return proto.CompactTextString(m) }
func (*StaticsDeposit) ProtoMessage() {}
type StaticsLockSingle struct {
TotalLockedAccumated int64 `protobuf:"varint,1,opt,name=totalLockedAccumated" json:"totalLockedAccumated,omitempty"`
Locked []int64 `protobuf:"varint,2,rep,name=locked" json:"locked,omitempty"`
}
func (m *StaticsLockSingle) Reset() { *m = StaticsLockSingle{} }
func (m *StaticsLockSingle) String() string { return proto.CompactTextString(m) }
func (*StaticsLockSingle) ProtoMessage() {}
type TransferToken struct {
TokenAddr string `protobuf:"bytes,1,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
FromKey string `protobuf:"bytes,2,opt,name=fromKey" json:"fromKey,omitempty"`
ToAddr string `protobuf:"bytes,3,opt,name=toAddr" json:"toAddr,omitempty"`
Amount string `protobuf:"bytes,4,opt,name=amount" json:"amount,omitempty"`
}
func (m *TransferToken) Reset() { *m = TransferToken{} }
func (m *TransferToken) String() string { return proto.CompactTextString(m) }
func (*TransferToken) ProtoMessage() {}
type Uint64 struct {
Data uint64 `protobuf:"varint,1,opt,name=data" json:"data,omitempty"`
}
func (m *Uint64) Reset() { *m = Uint64{} }
func (m *Uint64) String() string { return proto.CompactTextString(m) }
func (*Uint64) ProtoMessage() {}
type TokenStatics struct {
TokenAddr string `protobuf:"bytes,1,opt,name=tokenAddr" json:"tokenAddr,omitempty"`
}
func (m *TokenStatics) Reset() { *m = TokenStatics{} }
func (m *TokenStatics) String() string { return proto.CompactTextString(m) }
func (*TokenStatics) ProtoMessage() {}
type EventLogIndex struct {
Height uint64 `protobuf:"varint,1,opt,name=height" json:"height,omitempty"`
Index uint32 `protobuf:"varint,2,opt,name=index" json:"index,omitempty"`
}
func (m *EventLogIndex) Reset() { *m = EventLogIndex{} }
func (m *EventLogIndex) String() string { return proto.CompactTextString(m) }
func (*EventLogIndex) ProtoMessage() {}
type EthTxStatus struct {
Status string `protobuf:"bytes,1,opt,name=status" json:"status,omitempty"`
Txhash string `protobuf:"bytes,2,opt,name=txhash" json:"txhash,omitempty"`
}
func (m *EthTxStatus) Reset() { *m = EthTxStatus{} }
func (m *EthTxStatus) String() string { return proto.CompactTextString(m) }
func (*EthTxStatus) ProtoMessage() {}
func init() {
}
package utils
// --------------------------------------------------------
// Utils
//
// Utils contains utility functionality for the ebrelayer.
// --------------------------------------------------------
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"strconv"
"strings"
"time"
"unicode"
simplejson "github.com/bitly/go-simplejson"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
"github.com/ethereum/go-ethereum/common"
)
const (
nullAddress = "0x0000000000000000000000000000000000000000"
)
var log = log15.New("module", "utils")
// IsZeroAddress : checks an Ethereum address and returns a bool which indicates if it is the null address
func IsZeroAddress(address common.Address) bool {
return address == common.HexToAddress(nullAddress)
}
//密码合法性校验,密码长度在8-30位之间。必须是数字+字母的组合
func IsValidPassWord(password string) bool {
pwLen := len(password)
if pwLen < 8 || pwLen > 30 {
return false
}
var char bool
var digit bool
for _, s := range password {
if unicode.IsLetter(s) {
char = true
} else if unicode.IsDigit(s) {
digit = true
} else {
return false
}
}
return char && digit
}
func decodeInt64(int64bytes []byte) (int64, error) {
var value types.Int64
err := types.Decode(int64bytes, &value)
if err != nil {
//may be old database format json...
err = json.Unmarshal(int64bytes, &value.Data)
if err != nil {
return -1, types.ErrUnmarshal
}
}
return value.Data, nil
}
func LoadInt64FromDB(key []byte, db dbm.DB) (int64, error) {
bytes, err := db.Get(key)
if bytes == nil || err != nil {
//if err != dbm.ErrNotFoundInDb {
// log.Error("LoadInt64FromDB", "error", err)
//}
return 0, types.ErrHeightNotExist
}
return decodeInt64(bytes)
}
func QueryTxhashes(prefix []byte, db dbm.DB) []string {
kvdb := dbm.NewKVDB(db)
hashes, err := kvdb.List(prefix, nil, 10, 1)
if nil != err {
return nil
}
var hashStrs []string
for _, hash := range hashes {
hashStrs = append(hashStrs, string(hash))
}
return hashStrs
}
var (
Addr2DecimalsKey = []byte("prefix_for_Addr2Decimals")
)
func CalAddr2DecimalsPrefix(tokenAddr string) []byte {
return []byte(fmt.Sprintf("%s-%s", Addr2DecimalsKey, tokenAddr))
}
func GetDecimalsFromDB(addr string, db dbm.DB) (int64, error) {
res, err := db.Get(CalAddr2DecimalsPrefix(addr))
if err != nil {
return 0, err
}
var addr2Decimals map[string]int64
err = json.Unmarshal(res, &addr2Decimals)
if err != nil {
return 0, err
}
if d, ok := addr2Decimals[addr]; ok {
return d, nil
}
return 0, types.ErrNotFound
}
func GetDecimalsFromNode(addr string, nodeAddr string) (int64, error) {
if addr == "0x0000000000000000000000000000000000000000" || addr == "" {
return 18, nil
}
Hashprefix := "0x313ce567"
postData := fmt.Sprintf(`{"id":1,"jsonrpc":"2.0","method":"eth_call","params":[{"to":"%s", "data":"%s"},"latest"]}`, addr, Hashprefix)
retryTimes := 0
RETRY:
res, err := sendToServer(nodeAddr, strings.NewReader(postData))
if err != nil {
log.Error("GetDecimals", "error:", err.Error())
if retryTimes > 3 {
return 0, err
}
retryTimes++
goto RETRY
}
js, err := simplejson.NewJson(res)
if err != nil {
log.Error("GetDecimals", "NewJson error:", err.Error())
if retryTimes > 3 {
return 0, err
}
retryTimes++
goto RETRY
}
result := js.Get("result").MustString()
decimals, err := strconv.ParseInt(result, 0, 64)
if err != nil {
if retryTimes > 3 {
return 0, err
}
retryTimes++
goto RETRY
}
return decimals, nil
}
func sendToServer(url string, req io.Reader) ([]byte, error) {
client := http.Client{
Transport: &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
deadline := time.Now().Add(10 * time.Second)
c, err := net.DialTimeout(netw, addr, time.Second*5)
if err != nil {
return nil, err
}
c.SetDeadline(deadline)
return c, nil
},
},
}
var request *http.Request
var err error
request, err = http.NewRequest("POST", url, req)
if err != nil {
return nil, err
}
request.Header.Set("Content-Type", "application/json")
resp, err := client.Do(request)
if err != nil {
return nil, err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return body, nil
}
package executor
import (
"errors"
"github.com/33cn/chain33/system/dapp"
manTy "github.com/33cn/chain33/system/dapp/manage/types"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/types"
x2eTy "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
/*
* 实现交易的链上执行接口
* 关键数据上链(statedb)并生成交易回执(log)
*/
//---------------- Ethereum(eth/erc20) --> Chain33-------------------//
// 在chain33上为ETH/ERC20铸币
func (x *x2ethereum) Exec_Eth2Chain33Lock(payload *x2eTy.Eth2Chain33, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
payload.ValidatorAddress = address.PubKeyToAddr(tx.Signature.Pubkey)
return action.procEth2Chain33_lock(payload)
}
//---------------- Chain33(eth/erc20)------> Ethereum -------------------//
// 在chain33端将铸的币销毁,返还给eth
func (x *x2ethereum) Exec_Chain33ToEthBurn(payload *x2eTy.Chain33ToEth, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
return action.procChain33ToEth_burn(payload)
}
//---------------- Ethereum (bty) --> Chain33-------------------//
// 在eth端将铸的bty币销毁,返还给chain33
func (x *x2ethereum) Exec_Eth2Chain33Burn(payload *x2eTy.Eth2Chain33, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
payload.ValidatorAddress = address.PubKeyToAddr(tx.Signature.Pubkey)
return action.procEth2Chain33_burn(payload)
}
//---------------- Chain33 --> Ethereum (bty) -------------------//
// 在 ethereum 上为 chain33 铸币
func (x *x2ethereum) Exec_Chain33ToEthLock(payload *x2eTy.Chain33ToEth, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
return action.procChain33ToEth_lock(payload)
}
// 转账功能
func (x *x2ethereum) Exec_Transfer(payload *types.AssetsTransfer, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
return action.procMsgTransfer(payload)
}
func (x *x2ethereum) Exec_TransferToExec(payload *types.AssetsTransferToExec, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
if !x2eTy.IsExecAddrMatch(payload.ExecName, tx.GetRealToAddr()) {
return nil, types.ErrToAddrNotSameToExecAddr
}
return action.procMsgTransferToExec(payload)
}
func (x *x2ethereum) Exec_WithdrawFromExec(payload *types.AssetsWithdraw, tx *types.Transaction, index int) (*types.Receipt, error) {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
if dapp.IsDriverAddress(tx.GetRealToAddr(), x.GetHeight()) || x2eTy.IsExecAddrMatch(payload.ExecName, tx.GetRealToAddr()) {
return action.procMsgWithDrawFromExec(payload)
}
return nil, errors.New("tx error")
}
//--------------------------合约管理员账户操作-------------------------//
// AddValidator是为了增加validator
func (x *x2ethereum) Exec_AddValidator(payload *x2eTy.MsgValidator, tx *types.Transaction, index int) (*types.Receipt, error) {
confManager := types.ConfSub(x.GetAPI().GetConfig(), manTy.ManageX).GStrList("superManager")
err := checkTxSignBySpecificAddr(tx, confManager)
if err == nil {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
return action.procAddValidator(payload)
}
return nil, err
}
// RemoveValidator是为了移除某一个validator
func (x *x2ethereum) Exec_RemoveValidator(payload *x2eTy.MsgValidator, tx *types.Transaction, index int) (*types.Receipt, error) {
confManager := types.ConfSub(x.GetAPI().GetConfig(), manTy.ManageX).GStrList("superManager")
err := checkTxSignBySpecificAddr(tx, confManager)
if err == nil {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
return action.procRemoveValidator(payload)
}
return nil, err
}
// ModifyPower是为了修改某个validator的power
func (x *x2ethereum) Exec_ModifyPower(payload *x2eTy.MsgValidator, tx *types.Transaction, index int) (*types.Receipt, error) {
confManager := types.ConfSub(x.GetAPI().GetConfig(), manTy.ManageX).GStrList("superManager")
err := checkTxSignBySpecificAddr(tx, confManager)
if err == nil {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
return action.procModifyValidator(payload)
}
return nil, err
}
// SetConsensusThreshold是为了修改对validator所提供的claim达成共识的阈值
func (x *x2ethereum) Exec_SetConsensusThreshold(payload *x2eTy.MsgConsensusThreshold, tx *types.Transaction, index int) (*types.Receipt, error) {
confManager := types.ConfSub(x.GetAPI().GetConfig(), manTy.ManageX).GStrList("superManager")
err := checkTxSignBySpecificAddr(tx, confManager)
if err == nil {
action := newAction(x, tx, int32(index))
if action == nil {
return nil, errors.New("Create Action Error")
}
return action.procMsgSetConsensusThreshold(payload)
}
return nil, err
}
func checkTxSignBySpecificAddr(tx *types.Transaction, addrs []string) error {
signAddr := address.PubKeyToAddr(tx.Signature.Pubkey)
var exist bool
for _, addr := range addrs {
if signAddr == addr {
exist = true
break
}
}
if !exist {
return x2eTy.ErrInvalidAdminAddress
}
if !tx.CheckSign() {
return types.ErrSign
}
return nil
}
package executor
import (
"github.com/33cn/chain33/types"
)
/*
* 实现区块回退时本地执行的数据清除
*/
// ExecDelLocal 回退自动删除,重写基类
func (x *x2ethereum) ExecDelLocal(tx *types.Transaction, receipt *types.ReceiptData, index int) (*types.LocalDBSet, error) {
kvs, err := x.DelRollbackKV(tx, tx.Execer)
if err != nil {
return nil, err
}
dbSet := &types.LocalDBSet{}
dbSet.KV = append(dbSet.KV, kvs...)
return dbSet, nil
}
package executor
import (
"strconv"
"github.com/33cn/chain33/types"
x2eTy "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
/*
* 实现交易相关数据本地执行,数据不上链
* 非关键数据,本地存储(localDB), 用于辅助查询,效率高
*/
func (x *x2ethereum) ExecLocal_Eth2Chain33Lock(payload *x2eTy.Eth2Chain33, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set, err := x.execLocal(receiptData)
if err != nil {
return set, err
}
return x.addAutoRollBack(tx, set.KV), nil
}
func (x *x2ethereum) ExecLocal_Eth2Chain33Burn(payload *x2eTy.Eth2Chain33, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set, err := x.execLocal(receiptData)
if err != nil {
return set, err
}
return x.addAutoRollBack(tx, set.KV), nil
}
func (x *x2ethereum) ExecLocal_Chain33ToEthBurn(payload *x2eTy.Chain33ToEth, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set, err := x.execLocal(receiptData)
if err != nil {
return set, err
}
return x.addAutoRollBack(tx, set.KV), nil
}
func (x *x2ethereum) ExecLocal_Chain33ToEthLock(payload *x2eTy.Chain33ToEth, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
set, err := x.execLocal(receiptData)
if err != nil {
return set, err
}
return x.addAutoRollBack(tx, set.KV), nil
}
func (x *x2ethereum) ExecLocal_AddValidator(payload *x2eTy.MsgValidator, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
//implement code
return x.addAutoRollBack(tx, dbSet.KV), nil
}
func (x *x2ethereum) ExecLocal_RemoveValidator(payload *x2eTy.MsgValidator, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
//implement code
return x.addAutoRollBack(tx, dbSet.KV), nil
}
func (x *x2ethereum) ExecLocal_ModifyPower(payload *x2eTy.MsgValidator, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
//implement code
return x.addAutoRollBack(tx, dbSet.KV), nil
}
func (x *x2ethereum) ExecLocal_SetConsensusThreshold(payload *x2eTy.MsgConsensusThreshold, tx *types.Transaction, receiptData *types.ReceiptData, index int) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
//implement code
return x.addAutoRollBack(tx, dbSet.KV), nil
}
//设置自动回滚
func (x *x2ethereum) addAutoRollBack(tx *types.Transaction, kv []*types.KeyValue) *types.LocalDBSet {
dbSet := &types.LocalDBSet{}
dbSet.KV = x.AddRollbackKV(tx, tx.Execer, kv)
return dbSet
}
func (x *x2ethereum) execLocal(receiptData *types.ReceiptData) (*types.LocalDBSet, error) {
dbSet := &types.LocalDBSet{}
for _, log := range receiptData.Logs {
switch log.Ty {
case x2eTy.TyEth2Chain33Log:
var receiptEth2Chain33 x2eTy.ReceiptEth2Chain33
err := types.Decode(log.Log, &receiptEth2Chain33)
if err != nil {
return nil, err
}
nb, err := x.GetLocalDB().Get(x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptEth2Chain33.IssuerDotSymbol, receiptEth2Chain33.TokenAddress, x2eTy.DirEth2Chain33, "lock"))
if err != nil && err != types.ErrNotFound {
return nil, err
}
var now x2eTy.ReceiptQuerySymbolAssetsByTxType
err = types.Decode(nb, &now)
if err != nil {
return nil, err
}
preAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(now.TotalAmount), 64)
nowAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(receiptEth2Chain33.Amount), 64)
TokenAssetsByTxTypeBytes := types.Encode(&x2eTy.ReceiptQuerySymbolAssetsByTxType{
TokenSymbol: receiptEth2Chain33.IssuerDotSymbol,
TxType: "lock",
TotalAmount: strconv.FormatFloat(preAmount+nowAmount, 'f', 4, 64),
Direction: 1,
})
dbSet.KV = append(dbSet.KV, &types.KeyValue{
Key: x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptEth2Chain33.IssuerDotSymbol, receiptEth2Chain33.TokenAddress, x2eTy.DirEth2Chain33, "lock"),
Value: TokenAssetsByTxTypeBytes,
})
nb, err = x.GetLocalDB().Get(x2eTy.CalTokenSymbolToTokenAddress(receiptEth2Chain33.IssuerDotSymbol))
if err != nil && err != types.ErrNotFound {
return nil, err
}
var t x2eTy.ReceiptTokenToTokenAddress
err = types.Decode(nb, &t)
if err != nil {
return nil, err
}
var exist bool
for _, addr := range t.TokenAddress {
if addr == receiptEth2Chain33.TokenAddress {
exist = true
}
}
if !exist {
t.TokenAddress = append(t.TokenAddress, receiptEth2Chain33.TokenAddress)
}
TokenToTokenAddressBytes := types.Encode(&x2eTy.ReceiptTokenToTokenAddress{
TokenAddress: t.TokenAddress,
})
dbSet.KV = append(dbSet.KV, &types.KeyValue{
Key: x2eTy.CalTokenSymbolToTokenAddress(receiptEth2Chain33.IssuerDotSymbol),
Value: TokenToTokenAddressBytes,
})
case x2eTy.TyWithdrawEthLog:
var receiptEth2Chain33 x2eTy.ReceiptEth2Chain33
err := types.Decode(log.Log, &receiptEth2Chain33)
if err != nil {
return nil, err
}
nb, err := x.GetLocalDB().Get(x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptEth2Chain33.IssuerDotSymbol, receiptEth2Chain33.TokenAddress, x2eTy.DirEth2Chain33, "withdraw"))
if err != nil && err != types.ErrNotFound {
return nil, err
}
var now x2eTy.ReceiptQuerySymbolAssetsByTxType
err = types.Decode(nb, &now)
if err != nil {
return nil, err
}
preAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(now.TotalAmount), 64)
nowAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(receiptEth2Chain33.Amount), 64)
TokenAssetsByTxTypeBytes := types.Encode(&x2eTy.ReceiptQuerySymbolAssetsByTxType{
TokenSymbol: receiptEth2Chain33.IssuerDotSymbol,
TxType: "withdraw",
TotalAmount: strconv.FormatFloat(preAmount+nowAmount, 'f', 4, 64),
Direction: 2,
})
dbSet.KV = append(dbSet.KV, &types.KeyValue{
Key: x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptEth2Chain33.IssuerDotSymbol, receiptEth2Chain33.TokenAddress, x2eTy.DirEth2Chain33, "withdraw"),
Value: TokenAssetsByTxTypeBytes,
})
case x2eTy.TyChain33ToEthLog:
var receiptChain33ToEth x2eTy.ReceiptChain33ToEth
err := types.Decode(log.Log, &receiptChain33ToEth)
if err != nil {
return nil, err
}
nb, err := x.GetLocalDB().Get(x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptChain33ToEth.IssuerDotSymbol, receiptChain33ToEth.TokenContract, x2eTy.DirChain33ToEth, "lock"))
if err != nil && err != types.ErrNotFound {
return nil, err
}
var now x2eTy.ReceiptQuerySymbolAssetsByTxType
err = types.Decode(nb, &now)
if err != nil {
return nil, err
}
preAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(now.TotalAmount), 64)
nowAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(receiptChain33ToEth.Amount), 64)
TokenAssetsByTxTypeBytes := types.Encode(&x2eTy.ReceiptQuerySymbolAssetsByTxType{
TokenSymbol: receiptChain33ToEth.IssuerDotSymbol,
TxType: "lock",
TotalAmount: strconv.FormatFloat(preAmount+nowAmount, 'f', 4, 64),
Direction: 1,
})
dbSet.KV = append(dbSet.KV, &types.KeyValue{
Key: x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptChain33ToEth.IssuerDotSymbol, receiptChain33ToEth.TokenContract, x2eTy.DirChain33ToEth, "lock"),
Value: TokenAssetsByTxTypeBytes,
})
case x2eTy.TyWithdrawChain33Log:
var receiptChain33ToEth x2eTy.ReceiptChain33ToEth
err := types.Decode(log.Log, &receiptChain33ToEth)
if err != nil {
return nil, err
}
nb, err := x.GetLocalDB().Get(x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptChain33ToEth.IssuerDotSymbol, receiptChain33ToEth.TokenContract, x2eTy.DirChain33ToEth, ""))
if err != nil && err != types.ErrNotFound {
return nil, err
}
var now x2eTy.ReceiptQuerySymbolAssetsByTxType
err = types.Decode(nb, &now)
if err != nil {
return nil, err
}
preAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(now.TotalAmount), 64)
nowAmount, _ := strconv.ParseFloat(x2eTy.TrimZeroAndDot(receiptChain33ToEth.Amount), 64)
TokenAssetsByTxTypeBytes := types.Encode(&x2eTy.ReceiptQuerySymbolAssetsByTxType{
TokenSymbol: receiptChain33ToEth.IssuerDotSymbol,
TxType: "withdraw",
TotalAmount: strconv.FormatFloat(preAmount+nowAmount, 'f', 4, 64),
Direction: 2,
})
dbSet.KV = append(dbSet.KV, &types.KeyValue{
Key: x2eTy.CalTokenSymbolTotalLockOrBurnAmount(receiptChain33ToEth.IssuerDotSymbol, receiptChain33ToEth.TokenContract, x2eTy.DirChain33ToEth, "withdraw"),
Value: TokenAssetsByTxTypeBytes,
})
default:
continue
}
}
return dbSet, nil
}
package executor
import (
"fmt"
"math"
"strconv"
//"github.com/33cn/chain33/client"
"testing"
apimock "github.com/33cn/chain33/client/mocks"
"github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/address"
"github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/common/db/mocks"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
chain33types "github.com/33cn/chain33/types"
"github.com/33cn/chain33/util"
types2 "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
"github.com/stretchr/testify/mock"
"github.com/stretchr/testify/suite"
)
var chainTestCfg = types.NewChain33Config(types.GetDefaultCfgstring())
func init() {
Init(types2.X2ethereumX, chainTestCfg, nil)
}
var (
chain33Receiver = "1BqP2vHkYNjSgdnTqm7pGbnphLhtEhuJFi"
bridgeContractAddress = "0xC4cE93a5699c68241fc2fB503Fb0f21724A624BB"
symbol = "eth"
tokenContractAddress = "0x0000000000000000000000000000000000000000"
ethereumAddr = "0x7B95B6EC7EbD73572298cEf32Bb54FA408207359"
addValidator1 = "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv"
addValidator2 = "14KEKbYtKKQm4wMthSK9J4La4nAiidGozt"
privFrom = getprivkey("4257d8692ef7fe13c68b65d6a52f03933db2fa5ce8faf210b5b8b80c721ced01") // 12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv
tx = &types.Transaction{}
sdb *db.GoMemDB
kvdb db.KVDB
)
type suiteX2Ethereum struct {
suite.Suite
kvdb *mocks.KVDB
x2eth *x2ethereum
addrX2Eth string
action *action
}
func TestRunSuiteX2Ethereum(t *testing.T) {
log := new(suiteX2Ethereum)
suite.Run(t, log)
}
func (x *suiteX2Ethereum) SetupSuite() {
x.kvdb = new(mocks.KVDB)
x2eth := &x2ethereum{drivers.DriverBase{}}
_, _, kvdb = util.CreateTestDB()
x2eth.SetLocalDB(kvdb)
api := new(apimock.QueueProtocolAPI)
api.On("GetConfig", mock.Anything).Return(chainTestCfg, nil)
x2eth.SetAPI(api)
sdb, _ = db.NewGoMemDB("x2EthereumTestDb", "test", 128)
x2eth.SetStateDB(sdb)
x2eth.SetExecutorType(types.LoadExecutorType(driverName))
x2eth.SetEnv(10, 100, 1)
x2eth.SetIsFree(false)
x2eth.SetChild(x2eth)
tx.Execer = []byte(types2.X2ethereumX)
tx.To = address.ExecAddress(types2.X2ethereumX)
tx.Nonce = 1
tx.Sign(types.SECP256K1, privFrom)
x.action = newAction(x2eth, tx, 0)
x.x2eth = x2eth
x.addrX2Eth = address.ExecAddress(driverName)
x.Equal("x2ethereum", x.x2eth.GetName())
x.accountSetup()
}
func (x *suiteX2Ethereum) Test_1_SetConsensus() {
receipt, err := x.action.procMsgSetConsensusThreshold(&types2.MsgConsensusThreshold{ConsensusThreshold: 80})
x.NoError(err)
x.NotEmpty(receipt)
x.setDb(receipt)
msg, err := x.x2eth.Query_GetConsensusThreshold(&types2.QueryConsensusThresholdParams{})
x.NoError(err)
reply := msg.(*types2.ReceiptQueryConsensusThreshold)
x.Equal(reply.ConsensusThreshold, int64(80))
}
func (x *suiteX2Ethereum) Test_2_AddValidator() {
add := &types2.MsgValidator{
Address: addValidator1,
Power: 7,
}
receipt, err := x.action.procAddValidator(add)
x.NoError(err)
x.NotEmpty(receipt)
x.setDb(receipt)
receipt, err = x.action.procAddValidator(add)
x.Error(err)
add2 := &types2.MsgValidator{
Address: addValidator2,
Power: 6,
}
receipt, err = x.action.procAddValidator(add2)
x.NoError(err)
x.NotEmpty(receipt)
x.setDb(receipt)
msg, err := x.x2eth.Query_GetTotalPower(&types2.QueryTotalPowerParams{})
x.NoError(err)
reply := msg.(*types2.ReceiptQueryTotalPower)
x.Equal(reply.TotalPower, int64(13))
msg, err = x.x2eth.Query_GetValidators(&types2.QueryValidatorsParams{})
x.NoError(err)
reply2 := msg.(*types2.ReceiptQueryValidator)
x.Equal(reply2.TotalPower, int64(13))
}
func (x *suiteX2Ethereum) Test_3_ModifyAndRemoveValidator() {
add := &types2.MsgValidator{
Address: chain33Receiver,
Power: 7,
}
receipt, err := x.action.procAddValidator(add)
x.NoError(err)
x.NotEmpty(receipt)
x.setDb(receipt)
add.Power = 8
receipt, err = x.action.procModifyValidator(add)
x.NoError(err)
x.NotEmpty(receipt)
x.setDb(receipt)
msg, err := x.x2eth.Query_GetValidators(&types2.QueryValidatorsParams{Validator: chain33Receiver})
x.NoError(err)
reply := msg.(*types2.ReceiptQueryValidator)
x.Equal(reply.Validators[0].Power, int64(8))
receipt, err = x.action.procRemoveValidator(add)
x.NoError(err)
x.NotEmpty(receipt)
x.setDb(receipt)
_, err = x.x2eth.Query_GetValidators(&types2.QueryValidatorsParams{Validator: chain33Receiver})
x.Equal(err, types2.ErrInvalidValidator)
}
func (x *suiteX2Ethereum) Test_4_Eth2Chain33() {
_, err := x.x2eth.Query_GetTotalPower(&types2.QueryTotalPowerParams{})
if err == types.ErrNotFound {
x.Test_2_AddValidator()
}
payload := &types2.Eth2Chain33{
EthereumChainID: 0,
BridgeContractAddress: bridgeContractAddress,
Nonce: 0,
IssuerDotSymbol: symbol,
TokenContractAddress: tokenContractAddress,
EthereumSender: ethereumAddr,
Chain33Receiver: addValidator1,
ValidatorAddress: addValidator1,
Amount: "10",
ClaimType: int64(types2.LockClaimType),
}
receipt, err := x.action.procEth2Chain33_lock(payload)
x.NoError(err)
x.setDb(receipt)
payload.ValidatorAddress = addValidator2
receipt, err = x.action.procEth2Chain33_lock(payload)
x.NoError(err)
x.setDb(receipt)
_, err = x.x2eth.Query_GetEthProphecy(&types2.QueryEthProphecyParams{ID: "010x7B95B6EC7EbD73572298cEf32Bb54FA408207359"})
x.Equal(err, types.ErrNotFound)
ID := strconv.Itoa(0) + strconv.Itoa(0) + ethereumAddr + tokenContractAddress + "lock"
x.queryGetEthProphecy(ID, types2.EthBridgeStatus_SuccessStatusText)
x.queryGetSymbolTotalAmountByTxType(1, symbol, "lock", "", "10")
payload1 := &types2.Chain33ToEth{
TokenContract: tokenContractAddress,
Chain33Sender: addValidator1,
EthereumReceiver: ethereumAddr,
Amount: "3",
IssuerDotSymbol: "eth",
Decimals: 8,
}
receipt, err = x.action.procChain33ToEth_burn(payload1)
x.NoError(err)
x.setDb(receipt)
x.queryGetEthProphecy("000x7B95B6EC7EbD73572298cEf32Bb54FA4082073590x0000000000000000000000000000000000000000lock", types2.EthBridgeStatus_SuccessStatusText)
x.queryGetSymbolTotalAmount(symbol, "", 7, true)
x.queryGetSymbolTotalAmountByTxType(2, symbol, "withdraw", "", "3")
payload.Amount = "1"
payload.Nonce = 1
payload.ClaimType = int64(types2.LockClaimType)
payload.ValidatorAddress = addValidator1
receipt, err = x.action.procEth2Chain33_lock(payload)
x.NoError(err)
x.setDb(receipt)
payload.ValidatorAddress = addValidator2
receipt, err = x.action.procEth2Chain33_lock(payload)
x.NoError(err)
x.setDb(receipt)
x.queryGetEthProphecy("010x7B95B6EC7EbD73572298cEf32Bb54FA4082073590x0000000000000000000000000000000000000000lock", types2.EthBridgeStatus_SuccessStatusText)
x.queryGetSymbolTotalAmountByTxType(1, symbol, "lock", "", "11")
}
func (x *suiteX2Ethereum) Test_5_Chain33ToEth() {
_, err := x.x2eth.Query_GetTotalPower(&types2.QueryTotalPowerParams{})
if err == types.ErrNotFound {
x.Test_2_AddValidator()
}
msgLock := &types2.Chain33ToEth{
TokenContract: tokenContractAddress,
Chain33Sender: addValidator1,
EthereumReceiver: ethereumAddr,
Amount: "5",
IssuerDotSymbol: "coins.bty",
}
receipt, err := x.action.procChain33ToEth_lock(msgLock)
x.NoError(err)
x.setDb(receipt)
x.queryGetSymbolTotalAmount("coins.bty", tokenContractAddress, 5, false)
x.queryGetSymbolTotalAmountByTxType(2, "coins.bty", "lock", tokenContractAddress, "5")
payload := &types2.Eth2Chain33{
EthereumChainID: 0,
BridgeContractAddress: bridgeContractAddress,
Nonce: 2,
IssuerDotSymbol: "coins.bty",
TokenContractAddress: tokenContractAddress,
EthereumSender: ethereumAddr,
Chain33Receiver: addValidator1,
ValidatorAddress: addValidator1,
Amount: "4",
ClaimType: int64(types2.BurnClaimType),
}
receipt1, err := x.action.procEth2Chain33_burn(payload)
x.NoError(err)
x.setDb(receipt1)
payload.ValidatorAddress = addValidator2
receipt1, err = x.action.procEth2Chain33_burn(payload)
x.NoError(err)
x.setDb(receipt1)
x.queryGetSymbolTotalAmount("coins.bty", tokenContractAddress, 1, false)
x.queryGetSymbolTotalAmountByTxType(1, "coins.bty", "withdraw", tokenContractAddress, "4")
x.queryGetEthProphecy("020x7B95B6EC7EbD73572298cEf32Bb54FA4082073590x0000000000000000000000000000000000000000burn", types2.EthBridgeStatus_SuccessStatusText)
}
func (x *suiteX2Ethereum) accountSetup() {
acc := x.x2eth.GetCoinsAccount()
account := &types.Account{
Balance: 1000 * 1e8,
Addr: addValidator1,
}
acc.SaveAccount(account)
account = acc.LoadAccount(addValidator1)
x.Equal(int64(1000*1e8), account.Balance)
_, err := acc.TransferToExec(addValidator1, x.addrX2Eth, 200*1e8)
x.Nil(err)
account = acc.LoadExecAccount(addValidator1, x.addrX2Eth)
x.Equal(int64(200*1e8), account.Balance)
account = &types.Account{
Balance: 1000 * 1e8,
Addr: addValidator2,
}
acc.SaveAccount(account)
account = acc.LoadAccount(addValidator2)
x.Equal(int64(1000*1e8), account.Balance)
_, err = acc.TransferToExec(addValidator2, x.addrX2Eth, 200*1e8)
x.Nil(err)
account = acc.LoadExecAccount(addValidator2, x.addrX2Eth)
x.Equal(int64(200*1e8), account.Balance)
}
func (x *suiteX2Ethereum) setDb(receipt *chain33types.Receipt) {
for _, kv := range receipt.KV {
_ = sdb.Set(kv.Key, kv.Value)
}
receiptDate := &types.ReceiptData{Ty: receipt.Ty, Logs: receipt.Logs}
set, err := x.x2eth.execLocal(receiptDate)
x.NoError(err)
for _, kv := range set.KV {
_ = kvdb.Set(kv.Key, kv.Value)
}
}
func (x *suiteX2Ethereum) queryGetSymbolTotalAmountByTxType(direction int64, tokenSymbol, txType, tokenAddr, equal string) {
params := &types2.QuerySymbolAssetsByTxTypeParams{
TokenSymbol: tokenSymbol,
Direction: direction,
TxType: txType,
TokenAddr: tokenAddr,
}
msg, err := x.x2eth.Query_GetSymbolTotalAmountByTxType(params)
x.NoError(err)
fmt.Println("***", msg, err)
symbolAmount := msg.(*types2.ReceiptQuerySymbolAssets)
x.Equal(symbolAmount.Res[0].TotalAmount, equal)
}
func (x *suiteX2Ethereum) queryGetSymbolTotalAmount(tokenSymbol, tokenAddress string, equal int64, eth2chain33 bool) {
var lock, burn *types2.ReceiptQuerySymbolAssets
if eth2chain33 {
msg, _ := x.x2eth.Query_GetSymbolTotalAmountByTxType(&types2.QuerySymbolAssetsByTxTypeParams{TokenSymbol: tokenSymbol, TokenAddr: tokenAddress, Direction: 1, TxType: types2.LockClaim})
lock = msg.(*types2.ReceiptQuerySymbolAssets)
msg, _ = x.x2eth.Query_GetSymbolTotalAmountByTxType(&types2.QuerySymbolAssetsByTxTypeParams{TokenSymbol: tokenSymbol, TokenAddr: tokenAddress, Direction: 2, TxType: "withdraw"})
burn = msg.(*types2.ReceiptQuerySymbolAssets)
} else {
msg, _ := x.x2eth.Query_GetSymbolTotalAmountByTxType(&types2.QuerySymbolAssetsByTxTypeParams{TokenSymbol: tokenSymbol, TokenAddr: tokenAddress, Direction: 2, TxType: types2.LockClaim})
lock = msg.(*types2.ReceiptQuerySymbolAssets)
msg, err := x.x2eth.Query_GetSymbolTotalAmountByTxType(&types2.QuerySymbolAssetsByTxTypeParams{TokenSymbol: tokenSymbol, TokenAddr: tokenAddress, Direction: 1, TxType: "withdraw"})
if err != nil {
burn = new(types2.ReceiptQuerySymbolAssets)
} else {
burn = msg.(*types2.ReceiptQuerySymbolAssets)
}
}
var lockAmount, burnAmount float64
if lock.Res != nil {
lockAmount, _ = strconv.ParseFloat(lock.Res[0].TotalAmount, 64)
} else {
lockAmount = 0
}
if burn.Res != nil {
burnAmount, _ = strconv.ParseFloat(burn.Res[0].TotalAmount, 64)
} else {
burnAmount = 0
}
x.Equal(math.Abs(lockAmount-burnAmount), float64(equal))
}
func (x *suiteX2Ethereum) queryGetEthProphecy(id string, statusTest types2.EthBridgeStatus) {
msg, err := x.x2eth.Query_GetEthProphecy(&types2.QueryEthProphecyParams{ID: id})
x.NoError(err)
reply := msg.(*types2.ReceiptEthProphecy)
x.Equal(reply.Status.Text, statusTest)
}
func getprivkey(key string) crypto.PrivKey {
cr, err := crypto.New(types.GetSignName("", types.SECP256K1))
if err != nil {
panic(err)
}
bkey, err := common.FromHex(key)
if err != nil {
panic(err)
}
priv, err := cr.PrivKeyFromBytes(bkey)
if err != nil {
panic(err)
}
return priv
}
package executor
import (
"fmt"
"strconv"
"github.com/33cn/chain33/types"
x2eTy "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
func NewProphecy(id string) *x2eTy.ReceiptEthProphecy {
status := new(x2eTy.ProphecyStatus)
status.Text = x2eTy.EthBridgeStatus_PendingStatusText
return &x2eTy.ReceiptEthProphecy{
ID: id,
Status: status,
ClaimValidators: *new([]*x2eTy.ClaimValidators),
ValidatorClaims: *new([]*x2eTy.ValidatorClaims),
}
}
// AddClaim adds a given claim to this prophecy
func AddClaim(prophecy *x2eTy.ReceiptEthProphecy, validator string, claim string) {
claimValidators := new(x2eTy.StringMap)
if len(prophecy.ClaimValidators) == 0 {
prophecy.ClaimValidators = append(prophecy.ClaimValidators, &x2eTy.ClaimValidators{
Claim: claim,
Validators: &x2eTy.StringMap{
Validators: []string{validator},
},
})
} else {
for index, cv := range prophecy.ClaimValidators {
if cv.Claim == claim {
claimValidators = cv.Validators
prophecy.ClaimValidators[index].Validators = x2eTy.AddToStringMap(claimValidators, validator)
break
}
}
}
prophecy.ValidatorClaims = append(prophecy.ValidatorClaims, &x2eTy.ValidatorClaims{
Validator: validator,
Claim: claim,
})
}
// 遍历该prophecy所有claim,找出获得最多票数的claim
func FindHighestClaim(prophecy *x2eTy.ReceiptEthProphecy, validators map[string]int64) (string, int64, int64) {
totalClaimsPower := int64(0)
highestClaimPower := int64(-1)
highestClaim := ""
for _, claimValidators := range prophecy.ClaimValidators {
claimPower := int64(0)
for _, validatorAddr := range claimValidators.Validators.Validators {
validatorPower := validators[validatorAddr]
claimPower += validatorPower
}
totalClaimsPower += claimPower
if claimPower > highestClaimPower {
highestClaimPower = claimPower
highestClaim = claimValidators.Claim
}
}
return highestClaim, highestClaimPower, totalClaimsPower
}
func NewOracleClaimContent(chain33Receiver string, amount string, claimType, decimals int64) x2eTy.OracleClaimContent {
return x2eTy.OracleClaimContent{
Chain33Receiver: chain33Receiver,
Amount: amount,
ClaimType: claimType,
Decimals: decimals,
}
}
func NewClaim(id string, validatorAddress string, content string) x2eTy.OracleClaim {
return x2eTy.OracleClaim{
ID: id,
ValidatorAddress: validatorAddress,
Content: content,
}
}
//通过ethchain33结构构造一个OracleClaim结构,包括生成唯一的ID
func CreateOracleClaimFromEthClaim(ethClaim x2eTy.Eth2Chain33) (x2eTy.OracleClaim, error) {
if ethClaim.ClaimType != int64(x2eTy.LockClaimType) && ethClaim.ClaimType != int64(x2eTy.BurnClaimType) {
return x2eTy.OracleClaim{}, x2eTy.ErrInvalidClaimType
}
oracleID := strconv.Itoa(int(ethClaim.EthereumChainID)) + strconv.Itoa(int(ethClaim.Nonce)) + ethClaim.EthereumSender + ethClaim.TokenContractAddress
if ethClaim.ClaimType == int64(x2eTy.LockClaimType) {
oracleID = oracleID + "lock"
} else if ethClaim.ClaimType == int64(x2eTy.BurnClaimType) {
oracleID = oracleID + "burn"
}
claimContent := NewOracleClaimContent(ethClaim.Chain33Receiver, ethClaim.Amount, ethClaim.ClaimType, ethClaim.Decimals)
claimBytes := types.Encode(&claimContent)
claimString := string(claimBytes)
claim := NewClaim(oracleID, ethClaim.ValidatorAddress, claimString)
return claim, nil
}
func CreateOracleClaimFromOracleString(oracleClaimString string) (x2eTy.OracleClaimContent, error) {
var oracleClaimContent x2eTy.OracleClaimContent
bz := []byte(oracleClaimString)
if err := types.Decode(bz, &oracleClaimContent); err != nil {
return x2eTy.OracleClaimContent{}, fmt.Errorf("failed to parse claim: %s", err.Error())
}
return oracleClaimContent, nil
}
package executor
import (
"strconv"
"strings"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/types"
x2eTy "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
func (x *x2ethereum) Query_GetEthProphecy(in *x2eTy.QueryEthProphecyParams) (types.Message, error) {
prophecyKey := x2eTy.CalProphecyPrefix(in.ID)
var dbProphecy x2eTy.ReceiptEthProphecy
val, err := x.GetStateDB().Get(prophecyKey)
if err != nil {
return nil, err
}
err = types.Decode(val, &dbProphecy)
if err != nil {
return nil, types.ErrUnmarshal
}
return &dbProphecy, nil
}
func (x *x2ethereum) Query_GetValidators(in *x2eTy.QueryValidatorsParams) (types.Message, error) {
validatorsKey := x2eTy.CalValidatorMapsPrefix()
var v x2eTy.ValidatorList
vBytes, err := x.GetStateDB().Get(validatorsKey)
if err != nil {
elog.Error("Query_GetValidators", "GetValidators Err", err)
return nil, err
}
err = types.Decode(vBytes, &v)
if err != nil {
return nil, types.ErrUnmarshal
}
if in.Validator != "" {
validatorsRes := new(x2eTy.ReceiptQueryValidator)
for _, vv := range v.Validators {
if vv.Address == in.Validator {
val := make([]*x2eTy.MsgValidator, 1)
val[0] = vv
validatorsRes = &x2eTy.ReceiptQueryValidator{
Validators: val,
TotalPower: vv.Power,
}
return validatorsRes, nil
}
}
// 未知的地址
return nil, x2eTy.ErrInvalidValidator
}
validatorsRes := new(x2eTy.ReceiptQueryValidator)
var totalPower int64
for _, vv := range v.Validators {
totalPower += vv.Power
}
validatorsRes.Validators = v.Validators
validatorsRes.TotalPower = totalPower
return validatorsRes, nil
}
func (x *x2ethereum) Query_GetTotalPower(in *x2eTy.QueryTotalPowerParams) (types.Message, error) {
totalPower := &x2eTy.ReceiptQueryTotalPower{}
totalPowerKey := x2eTy.CalLastTotalPowerPrefix()
totalPowerBytes, err := x.GetStateDB().Get(totalPowerKey)
if err != nil {
elog.Error("Query_GetTotalPower", "GetTotalPower Err", err)
return nil, err
}
err = types.Decode(totalPowerBytes, totalPower)
if err != nil {
return nil, types.ErrUnmarshal
}
return totalPower, nil
}
func (x *x2ethereum) Query_GetConsensusThreshold(in *x2eTy.QueryConsensusThresholdParams) (types.Message, error) {
consensus := &x2eTy.ReceiptQueryConsensusThreshold{}
consensusKey := x2eTy.CalConsensusThresholdPrefix()
consensusBytes, err := x.GetStateDB().Get(consensusKey)
if err != nil {
elog.Error("Query_GetConsensusNeeded", "GetConsensusNeeded Err", err)
return nil, err
}
err = types.Decode(consensusBytes, consensus)
if err != nil {
return nil, types.ErrUnmarshal
}
return consensus, nil
}
func (x *x2ethereum) Query_GetSymbolTotalAmountByTxType(in *x2eTy.QuerySymbolAssetsByTxTypeParams) (types.Message, error) {
symbolAmount := &x2eTy.ReceiptQuerySymbolAssets{}
if in.TokenAddr != "" {
var r x2eTy.ReceiptQuerySymbolAssetsByTxType
symbolAmountKey := x2eTy.CalTokenSymbolTotalLockOrBurnAmount(in.TokenSymbol, in.TokenAddr, x2eTy.DirectionType[in.Direction], in.TxType)
totalAmountBytes, err := x.GetLocalDB().Get(symbolAmountKey)
if err != nil {
elog.Error("Query_GetSymbolTotalAmountByTxType", "GetSymbolTotalAmountByTxType Err", err)
return nil, err
}
err = types.Decode(totalAmountBytes, &r)
if err != nil {
return nil, types.ErrUnmarshal
}
r.TotalAmount = x2eTy.TrimZeroAndDot(strconv.FormatFloat(x2eTy.Toeth(r.TotalAmount, in.Decimal), 'f', 4, 64))
symbolAmount.Res = append(symbolAmount.Res, &r)
} else {
tokenAddressesBytes, err := x.GetLocalDB().Get(x2eTy.CalTokenSymbolToTokenAddress(in.TokenSymbol))
if err != nil && err != types.ErrNotFound {
return nil, err
}
var tokenAddresses x2eTy.ReceiptTokenToTokenAddress
err = types.Decode(tokenAddressesBytes, &tokenAddresses)
if err != nil {
return nil, err
}
for _, addr := range tokenAddresses.TokenAddress {
var r x2eTy.ReceiptQuerySymbolAssetsByTxType
symbolAmountKey := x2eTy.CalTokenSymbolTotalLockOrBurnAmount(in.TokenSymbol, addr, x2eTy.DirectionType[in.Direction], in.TxType)
totalAmountBytes, err := x.GetLocalDB().Get(symbolAmountKey)
if err != nil {
elog.Error("Query_GetSymbolTotalAmountByTxType", "GetSymbolTotalAmountByTxType Err", err)
return nil, err
}
err = types.Decode(totalAmountBytes, &r)
if err != nil {
return nil, types.ErrUnmarshal
}
r.TotalAmount = x2eTy.TrimZeroAndDot(strconv.FormatFloat(x2eTy.Toeth(r.TotalAmount, in.Decimal), 'f', 4, 64))
symbolAmount.Res = append(symbolAmount.Res, &r)
}
}
return symbolAmount, nil
}
func (x *x2ethereum) Query_GetRelayerBalance(in *x2eTy.QueryRelayerBalance) (types.Message, error) {
symbolAmount := &x2eTy.ReceiptQueryRelayerBalance{}
// 要查询特定的tokenAddr
if in.TokenAddr != "" {
accDB, err := account.NewAccountDB(x.GetAPI().GetConfig(), x2eTy.X2ethereumX, strings.ToLower(in.TokenSymbol+in.TokenAddr), x.GetStateDB())
if err != nil {
return nil, err
}
acc := accDB.LoadAccount(in.Address)
res := new(x2eTy.ReceiptQueryRelayerBalanceForOneToken)
res.TokenAddr = in.TokenAddr
res.TokenSymbol = in.TokenSymbol
res.Balance = x2eTy.TrimZeroAndDot(strconv.FormatFloat(float64(acc.Balance)/1e8, 'f', 4, 64))
symbolAmount.Res = append(symbolAmount.Res, res)
} else {
tokenAddressesBytes, err := x.GetLocalDB().Get(x2eTy.CalTokenSymbolToTokenAddress(in.TokenSymbol))
if err != nil && err != types.ErrNotFound {
return nil, err
}
var tokenAddresses x2eTy.ReceiptTokenToTokenAddress
err = types.Decode(tokenAddressesBytes, &tokenAddresses)
if err != nil {
return nil, err
}
for _, addr := range tokenAddresses.TokenAddress {
accDB, err := account.NewAccountDB(x.GetAPI().GetConfig(), x2eTy.X2ethereumX, strings.ToLower(in.TokenSymbol+addr), x.GetStateDB())
if err != nil {
return nil, err
}
acc := accDB.LoadAccount(in.Address)
res := new(x2eTy.ReceiptQueryRelayerBalanceForOneToken)
res.TokenAddr = addr
res.TokenSymbol = in.TokenSymbol
res.Balance = x2eTy.TrimZeroAndDot(strconv.FormatFloat(float64(acc.Balance)/1e8, 'f', 4, 64))
symbolAmount.Res = append(symbolAmount.Res, res)
}
}
return symbolAmount, nil
}
package executor
import (
log "github.com/33cn/chain33/common/log/log15"
drivers "github.com/33cn/chain33/system/dapp"
"github.com/33cn/chain33/types"
x2eTy "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
/*
* 执行器相关定义
* 重载基类相关接口
*/
var (
//日志
elog = log.New("module", "x2ethereum.executor")
)
var driverName = x2eTy.X2ethereumX
// Init register dapp
func Init(name string, cfg *types.Chain33Config, sub []byte) {
drivers.Register(cfg, GetName(), newX2ethereum, cfg.GetDappFork(driverName, "Enable"))
InitExecType()
}
// InitExecType Init Exec Type
func InitExecType() {
ety := types.LoadExecutorType(driverName)
ety.InitFuncList(types.ListMethod(&x2ethereum{}))
}
type x2ethereum struct {
drivers.DriverBase
}
func newX2ethereum() drivers.Driver {
t := &x2ethereum{}
t.SetChild(t)
t.SetExecutorType(types.LoadExecutorType(driverName))
return t
}
// GetName get driver name
func GetName() string {
return newX2ethereum().GetName()
}
func (x *x2ethereum) GetDriverName() string {
return driverName
}
// CheckTx 实现自定义检验交易接口,供框架调用
// todo
// 实现
func (x *x2ethereum) CheckTx(tx *types.Transaction, index int) error {
//var action x2ethereumtypes.X2EthereumAction
//err := types.Decode(tx.Payload, &action)
//if action.Ty
return nil
}
package executor
import (
"strconv"
"strings"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/client"
"github.com/33cn/chain33/common/address"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
x2eTy "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
"github.com/pkg/errors"
)
type action struct {
api client.QueueProtocolAPI
coinsAccount *account.DB
db dbm.KV
txhash []byte
fromaddr string
blocktime int64
height int64
index int32
execaddr string
oracle *Oracle
}
func newAction(a *x2ethereum, tx *types.Transaction, index int32) *action {
hash := tx.Hash()
fromaddr := tx.From()
return &action{a.GetAPI(), a.GetCoinsAccount(), a.GetStateDB(), hash, fromaddr,
a.GetBlockTime(), a.GetHeight(), index, address.ExecAddress(string(tx.Execer)), NewOracle(a.GetStateDB(), x2eTy.DefaultConsensusNeeded)}
}
// ethereum ---> chain33
// lock
func (a *action) procEth2Chain33_lock(ethBridgeClaim *x2eTy.Eth2Chain33) (*types.Receipt, error) {
ethBridgeClaim.IssuerDotSymbol = strings.ToLower(ethBridgeClaim.IssuerDotSymbol)
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
status, err := a.oracle.ProcessClaim(*ethBridgeClaim)
if err != nil {
return nil, err
}
ID := strconv.Itoa(int(ethBridgeClaim.EthereumChainID)) + strconv.Itoa(int(ethBridgeClaim.Nonce)) + ethBridgeClaim.EthereumSender + ethBridgeClaim.TokenContractAddress + "lock"
//记录ethProphecy
bz, err := a.db.Get(x2eTy.CalProphecyPrefix(ID))
if err != nil {
return nil, x2eTy.ErrProphecyGet
}
var dbProphecy x2eTy.ReceiptEthProphecy
err = types.Decode(bz, &dbProphecy)
if err != nil {
return nil, types.ErrUnmarshal
}
receipt.KV = append(receipt.KV, &types.KeyValue{
Key: x2eTy.CalProphecyPrefix(ID),
Value: bz,
})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: x2eTy.TyProphecyLog, Log: types.Encode(&dbProphecy)})
if status.Text == x2eTy.EthBridgeStatus_SuccessStatusText {
// mavl-x2ethereum-eth+tokenAddress
// 这里为了区分相同tokensymbol不同tokenAddress做了级联处理
accDB, err := account.NewAccountDB(a.api.GetConfig(), x2eTy.X2ethereumX, strings.ToLower(ethBridgeClaim.IssuerDotSymbol+ethBridgeClaim.TokenContractAddress), a.db)
if err != nil {
return nil, errors.Wrapf(err, "relay procMsgEth2Chain33,exec=%s,sym=%s", x2eTy.X2ethereumX, ethBridgeClaim.IssuerDotSymbol)
}
r, err := a.oracle.ProcessSuccessfulClaimForLock(status.FinalClaim, a.execaddr, accDB)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
//记录成功lock的日志
msgEthBridgeClaimBytes := types.Encode(ethBridgeClaim)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalEth2Chain33Prefix(), Value: msgEthBridgeClaimBytes})
execlog := &types.ReceiptLog{Ty: x2eTy.TyEth2Chain33Log, Log: types.Encode(&x2eTy.ReceiptEth2Chain33{
EthereumChainID: ethBridgeClaim.EthereumChainID,
BridgeContractAddress: ethBridgeClaim.BridgeContractAddress,
Nonce: ethBridgeClaim.Nonce,
IssuerDotSymbol: ethBridgeClaim.IssuerDotSymbol,
EthereumSender: ethBridgeClaim.EthereumSender,
Chain33Receiver: ethBridgeClaim.Chain33Receiver,
ValidatorAddress: ethBridgeClaim.ValidatorAddress,
Amount: ethBridgeClaim.Amount,
ClaimType: ethBridgeClaim.ClaimType,
XTxHash: a.txhash,
XHeight: uint64(a.height),
ProphecyID: ID,
Decimals: ethBridgeClaim.Decimals,
TokenAddress: ethBridgeClaim.TokenContractAddress,
})}
receipt.Logs = append(receipt.Logs, execlog)
}
receipt.Ty = types.ExecOk
return receipt, nil
}
// chain33 -> ethereum
// 返还在chain33上生成的erc20代币
func (a *action) procChain33ToEth_burn(msgBurn *x2eTy.Chain33ToEth) (*types.Receipt, error) {
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
accDB, err := account.NewAccountDB(a.api.GetConfig(), x2eTy.X2ethereumX, strings.ToLower(msgBurn.IssuerDotSymbol+msgBurn.TokenContract), a.db)
if err != nil {
return nil, errors.Wrapf(err, "relay procMsgBurn,exec=%s,sym=%s", x2eTy.X2ethereumX, msgBurn.IssuerDotSymbol)
}
r, err := a.oracle.ProcessBurn(a.fromaddr, msgBurn.Amount, accDB)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
execlog := &types.ReceiptLog{Ty: x2eTy.TyWithdrawChain33Log, Log: types.Encode(&x2eTy.ReceiptChain33ToEth{
Chain33Sender: a.fromaddr,
EthereumReceiver: msgBurn.EthereumReceiver,
Amount: msgBurn.Amount,
IssuerDotSymbol: msgBurn.IssuerDotSymbol,
Decimals: msgBurn.Decimals,
TokenContract: msgBurn.TokenContract,
})}
receipt.Logs = append(receipt.Logs, execlog)
msgBurnBytes := types.Encode(msgBurn)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalWithdrawChain33Prefix(), Value: msgBurnBytes})
receipt.Ty = types.ExecOk
return receipt, nil
}
func (a *action) procChain33ToEth_lock(msgLock *x2eTy.Chain33ToEth) (*types.Receipt, error) {
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
var accDB *account.DB
exec, symbol, _ := x2eTy.DivideDot(msgLock.IssuerDotSymbol)
if exec == "coins" {
accDB = account.NewCoinsAccount(a.api.GetConfig())
accDB.SetDB(a.db)
} else {
accDB, err = account.NewAccountDB(a.api.GetConfig(), exec, strings.ToLower(symbol), a.db)
}
r, err := a.oracle.ProcessLock(a.fromaddr, address.ExecAddress(symbol), a.execaddr, msgLock.Amount, accDB)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
execlog := &types.ReceiptLog{Ty: x2eTy.TyChain33ToEthLog, Log: types.Encode(&x2eTy.ReceiptChain33ToEth{
Chain33Sender: a.fromaddr,
EthereumReceiver: msgLock.EthereumReceiver,
Amount: msgLock.Amount,
IssuerDotSymbol: msgLock.IssuerDotSymbol,
Decimals: msgLock.Decimals,
TokenContract: msgLock.TokenContract,
})}
receipt.Logs = append(receipt.Logs, execlog)
msgLockBytes := types.Encode(msgLock)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalChain33ToEthPrefix(), Value: msgLockBytes})
receipt.Ty = types.ExecOk
return receipt, nil
}
// ethereum -> chain33
// burn
func (a *action) procEth2Chain33_burn(withdrawEth *x2eTy.Eth2Chain33) (*types.Receipt, error) {
elog.Info("procWithdrawEth", "receive a procWithdrawEth tx", "start")
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
status, err := a.oracle.ProcessClaim(*withdrawEth)
if err != nil {
return nil, err
}
ID := strconv.Itoa(int(withdrawEth.EthereumChainID)) + strconv.Itoa(int(withdrawEth.Nonce)) + withdrawEth.EthereumSender + withdrawEth.TokenContractAddress + "burn"
//记录ethProphecy
bz, err := a.db.Get(x2eTy.CalProphecyPrefix(ID))
if err != nil {
return nil, x2eTy.ErrProphecyGet
}
var dbProphecy x2eTy.ReceiptEthProphecy
err = types.Decode(bz, &dbProphecy)
if err != nil {
return nil, types.ErrUnmarshal
}
receipt.KV = append(receipt.KV, &types.KeyValue{
Key: x2eTy.CalProphecyPrefix(ID),
Value: bz,
})
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: x2eTy.TyProphecyLog, Log: types.Encode(&dbProphecy)})
if status.Text == x2eTy.EthBridgeStatus_SuccessStatusText {
var accDB *account.DB
exec, symbol, _ := x2eTy.DivideDot(withdrawEth.IssuerDotSymbol)
if exec == "coins" {
accDB = account.NewCoinsAccount(a.api.GetConfig())
accDB.SetDB(a.db)
} else {
accDB, err = account.NewAccountDB(a.api.GetConfig(), exec, strings.ToLower(symbol), a.db)
}
r, err := a.oracle.ProcessSuccessfulClaimForBurn(status.FinalClaim, a.execaddr, symbol, accDB)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
msgWithdrawEthBytes := types.Encode(withdrawEth)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalWithdrawEthPrefix(), Value: msgWithdrawEthBytes})
execlog := &types.ReceiptLog{Ty: x2eTy.TyWithdrawEthLog, Log: types.Encode(&x2eTy.ReceiptEth2Chain33{
EthereumChainID: withdrawEth.EthereumChainID,
BridgeContractAddress: withdrawEth.BridgeContractAddress,
Nonce: withdrawEth.Nonce,
IssuerDotSymbol: withdrawEth.IssuerDotSymbol,
EthereumSender: withdrawEth.EthereumSender,
Chain33Receiver: withdrawEth.Chain33Receiver,
ValidatorAddress: withdrawEth.ValidatorAddress,
Amount: withdrawEth.Amount,
ClaimType: withdrawEth.ClaimType,
XTxHash: a.txhash,
XHeight: uint64(a.height),
ProphecyID: ID,
Decimals: withdrawEth.Decimals,
TokenAddress: withdrawEth.TokenContractAddress,
})}
receipt.Logs = append(receipt.Logs, execlog)
}
receipt.Ty = types.ExecOk
return receipt, nil
}
func (a *action) procMsgTransfer(msgTransfer *types.AssetsTransfer) (*types.Receipt, error) {
token := msgTransfer.GetCointoken()
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
accDB, err := account.NewAccountDB(a.api.GetConfig(), x2eTy.X2ethereumX, token, a.db)
if err != nil {
return nil, err
}
r, err := accDB.ExecTransfer(a.fromaddr, msgTransfer.To, address.ExecAddress(x2eTy.X2ethereumX), msgTransfer.Amount)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
receipt.Ty = types.ExecOk
return receipt, nil
}
func (a *action) procMsgTransferToExec(msgTransferToExec *types.AssetsTransferToExec) (*types.Receipt, error) {
token := msgTransferToExec.GetCointoken()
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
accDB, err := account.NewAccountDB(a.api.GetConfig(), x2eTy.X2ethereumX, token, a.db)
if err != nil {
return nil, err
}
r, err := accDB.TransferToExec(a.fromaddr, address.ExecAddress(msgTransferToExec.ExecName), msgTransferToExec.Amount)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
}
func (a *action) procMsgWithDrawFromExec(msgWithdrawFromExec *types.AssetsWithdraw) (*types.Receipt, error) {
token := msgWithdrawFromExec.GetCointoken()
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
accDB, err := account.NewAccountDB(a.api.GetConfig(), x2eTy.X2ethereumX, token, a.db)
if err != nil {
return nil, err
}
r, err := accDB.TransferWithdraw(a.fromaddr, address.ExecAddress(msgWithdrawFromExec.ExecName), msgWithdrawFromExec.Amount)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
return receipt, nil
}
//需要一笔交易来注册validator
//这里注册的validator的power之和可能不为1,需要在内部进行加权
//返回的回执中,KV包含所有validator的power值,Log中包含本次注册的validator的power值
func (a *action) procAddValidator(msgAddValidator *x2eTy.MsgValidator) (*types.Receipt, error) {
elog.Info("procAddValidator", "start", msgAddValidator)
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
if !x2eTy.CheckPower(msgAddValidator.Power) {
return nil, x2eTy.ErrInvalidPower
}
r, err := a.oracle.ProcessAddValidator(msgAddValidator.Address, msgAddValidator.Power)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
execlog := &types.ReceiptLog{Ty: x2eTy.TyAddValidatorLog, Log: types.Encode(&x2eTy.ReceiptValidator{
Address: msgAddValidator.Address,
Power: msgAddValidator.Power,
XTxHash: a.txhash,
XHeight: uint64(a.height),
})}
receipt.Logs = append(receipt.Logs, execlog)
receipt.Ty = types.ExecOk
return receipt, nil
}
func (a *action) procRemoveValidator(msgRemoveValidator *x2eTy.MsgValidator) (*types.Receipt, error) {
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
r, err := a.oracle.ProcessRemoveValidator(msgRemoveValidator.Address)
if err != nil {
return nil, err
}
receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...)
execlog := &types.ReceiptLog{Ty: x2eTy.TyRemoveValidatorLog, Log: types.Encode(&x2eTy.ReceiptValidator{
Address: msgRemoveValidator.Address,
Power: msgRemoveValidator.Power,
XTxHash: a.txhash,
XHeight: uint64(a.height),
})}
receipt.Logs = append(receipt.Logs, execlog)
receipt.Ty = types.ExecOk
return receipt, nil
}
func (a *action) procModifyValidator(msgModifyValidator *x2eTy.MsgValidator) (*types.Receipt, error) {
receipt, err := a.checkConsensusThreshold()
if err != nil {
return nil, err
}
if !x2eTy.CheckPower(msgModifyValidator.Power) {
return nil, x2eTy.ErrInvalidPower
}
receipt, err = a.oracle.ProcessModifyValidator(msgModifyValidator.Address, msgModifyValidator.Power)
if err != nil {
return nil, err
}
execlog := &types.ReceiptLog{Ty: x2eTy.TyModifyPowerLog, Log: types.Encode(&x2eTy.ReceiptValidator{
Address: msgModifyValidator.Address,
Power: msgModifyValidator.Power,
XTxHash: a.txhash,
XHeight: uint64(a.height),
})}
receipt.Logs = append(receipt.Logs, execlog)
receipt.Ty = types.ExecOk
return receipt, nil
}
func (a *action) procMsgSetConsensusThreshold(msgSetConsensusThreshold *x2eTy.MsgConsensusThreshold) (*types.Receipt, error) {
receipt := new(types.Receipt)
if !x2eTy.CheckPower(msgSetConsensusThreshold.ConsensusThreshold) {
return nil, x2eTy.ErrInvalidPower
}
preConsensusNeeded, nowConsensusNeeded, err := a.oracle.ProcessSetConsensusNeeded(msgSetConsensusThreshold.ConsensusThreshold)
if err != nil {
return nil, err
}
setConsensusThreshold := &x2eTy.ReceiptSetConsensusThreshold{
PreConsensusThreshold: preConsensusNeeded,
NowConsensusThreshold: nowConsensusNeeded,
XTxHash: a.txhash,
XHeight: uint64(a.height),
}
execlog := &types.ReceiptLog{Ty: x2eTy.TySetConsensusThresholdLog, Log: types.Encode(setConsensusThreshold)}
receipt.Logs = append(receipt.Logs, execlog)
msgSetConsensusThresholdBytes := types.Encode(&x2eTy.ReceiptQueryConsensusThreshold{
ConsensusThreshold: nowConsensusNeeded,
})
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalConsensusThresholdPrefix(), Value: msgSetConsensusThresholdBytes})
receipt.Ty = types.ExecOk
return receipt, nil
}
func (a *action) checkConsensusThreshold() (*types.Receipt, error) {
receipt := new(types.Receipt)
consensusNeededBytes, err := a.db.Get(x2eTy.CalConsensusThresholdPrefix())
if err != nil {
if err == types.ErrNotFound {
setConsensusThreshold := &x2eTy.ReceiptQueryConsensusThreshold{ConsensusThreshold: x2eTy.DefaultConsensusNeeded}
msgSetConsensusThresholdBytes := types.Encode(setConsensusThreshold)
receipt.KV = append(receipt.KV, &types.KeyValue{
Key: x2eTy.CalConsensusThresholdPrefix(),
Value: msgSetConsensusThresholdBytes,
})
consensusThreshold := &x2eTy.ReceiptSetConsensusThreshold{
PreConsensusThreshold: int64(0),
NowConsensusThreshold: x2eTy.DefaultConsensusNeeded,
XTxHash: a.txhash,
XHeight: uint64(a.height),
}
receipt.Logs = append(receipt.Logs, &types.ReceiptLog{Ty: x2eTy.TySetConsensusThresholdLog, Log: types.Encode(consensusThreshold)})
} else {
return nil, err
}
} else {
var mc x2eTy.ReceiptQueryConsensusThreshold
_ = types.Decode(consensusNeededBytes, &mc)
_, _, err = a.oracle.ProcessSetConsensusNeeded(mc.ConsensusThreshold)
if err != nil {
return nil, err
}
}
return receipt, nil
}
package executor
import (
"strconv"
"strings"
"github.com/33cn/chain33/account"
"github.com/33cn/chain33/common/address"
dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/types"
x2eTy "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
type Oracle struct {
db dbm.KV
consensusThreshold int64
}
func NewOracle(db dbm.KV, consensusThreshold int64) *Oracle {
if consensusThreshold <= 0 || consensusThreshold > 100 {
return nil
}
return &Oracle{
consensusThreshold: consensusThreshold,
db: db,
}
}
// 处理经过审核的关于Lock的claim
func (o *Oracle) ProcessSuccessfulClaimForLock(claim, execAddr string, accDB *account.DB) (*types.Receipt, error) {
var receipt *types.Receipt
oracleClaim, err := CreateOracleClaimFromOracleString(claim)
if err != nil {
elog.Error("CreateEthClaimFromOracleString", "CreateOracleClaimFromOracleString error", err)
return nil, err
}
receiverAddress := oracleClaim.Chain33Receiver
if oracleClaim.ClaimType == int64(x2eTy.LockClaimType) {
//铸币到相关的tokenSymbolBank账户下
amount, _ := strconv.ParseInt(x2eTy.TrimZeroAndDot(oracleClaim.Amount), 10, 64)
receipt, err = accDB.Mint(receiverAddress, amount)
if err != nil {
return nil, err
}
return receipt, nil
}
return nil, x2eTy.ErrInvalidClaimType
}
// 处理经过审核的关于Burn的claim
func (o *Oracle) ProcessSuccessfulClaimForBurn(claim, execAddr, tokenSymbol string, accDB *account.DB) (*types.Receipt, error) {
receipt := new(types.Receipt)
oracleClaim, err := CreateOracleClaimFromOracleString(claim)
if err != nil {
elog.Error("CreateEthClaimFromOracleString", "CreateOracleClaimFromOracleString error", err)
return nil, err
}
senderAddr := oracleClaim.Chain33Receiver
if oracleClaim.ClaimType == int64(x2eTy.BurnClaimType) {
amount, _ := strconv.ParseInt(x2eTy.TrimZeroAndDot(oracleClaim.Amount), 10, 64)
receipt, err = accDB.ExecTransfer(address.ExecAddress(tokenSymbol), senderAddr, execAddr, amount)
if err != nil {
return nil, err
}
return receipt, nil
}
return nil, x2eTy.ErrInvalidClaimType
}
// ProcessBurn processes the burn of bridged coins from the given sender
func (o *Oracle) ProcessBurn(address, amount string, accDB *account.DB) (*types.Receipt, error) {
var a int64
a, _ = strconv.ParseInt(x2eTy.TrimZeroAndDot(amount), 10, 64)
receipt, err := accDB.Burn(address, a)
if err != nil {
return nil, err
}
return receipt, nil
}
// ProcessLock processes the lockup of cosmos coins from the given sender
// accDB = mavl-coins-bty-addr
func (o *Oracle) ProcessLock(address, to, execAddr, amount string, accDB *account.DB) (*types.Receipt, error) {
// 转到 mavl-coins-bty-execAddr:addr
a, _ := strconv.ParseInt(x2eTy.TrimZeroAndDot(amount), 10, 64)
receipt, err := accDB.ExecTransfer(address, to, execAddr, a)
if err != nil {
return nil, err
}
return receipt, nil
}
// 对于相同的地址该如何处理?
// 现有方案是相同地址就报错
func (o *Oracle) ProcessAddValidator(address string, power int64) (*types.Receipt, error) {
receipt := new(types.Receipt)
validatorMaps, err := o.GetValidatorArray()
if err != nil && err != types.ErrNotFound {
return nil, err
}
if validatorMaps == nil {
validatorMaps = new(x2eTy.ValidatorList)
}
elog.Info("ProcessLogInValidator", "pre validatorMaps", validatorMaps, "Add Address", address, "Add power", power)
var totalPower int64
for _, p := range validatorMaps.Validators {
if p.Address != address {
totalPower += p.Power
} else {
return nil, x2eTy.ErrAddressExists
}
}
vs := append(validatorMaps.Validators, &x2eTy.MsgValidator{
Address: address,
Power: power,
})
validatorMaps.Validators = vs
v := types.Encode(validatorMaps)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalValidatorMapsPrefix(), Value: v})
totalPower += power
totalP := x2eTy.ReceiptQueryTotalPower{
TotalPower: totalPower,
}
totalPBytes := types.Encode(&totalP)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalLastTotalPowerPrefix(), Value: totalPBytes})
return receipt, nil
}
func (o *Oracle) ProcessRemoveValidator(address string) (*types.Receipt, error) {
var exist bool
receipt := new(types.Receipt)
validatorMaps, err := o.GetValidatorArray()
if err != nil {
return nil, err
}
elog.Info("ProcessLogOutValidator", "pre validatorMaps", validatorMaps, "Delete Address", address)
var totalPower int64
validatorRes := new(x2eTy.ValidatorList)
for _, p := range validatorMaps.Validators {
if address != p.Address {
v := append(validatorRes.Validators, p)
validatorRes.Validators = v
totalPower += p.Power
} else {
exist = true
continue
}
}
if !exist {
return nil, x2eTy.ErrAddressNotExist
}
v := types.Encode(validatorRes)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalValidatorMapsPrefix(), Value: v})
totalP := x2eTy.ReceiptQueryTotalPower{
TotalPower: totalPower,
}
totalPBytes := types.Encode(&totalP)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalLastTotalPowerPrefix(), Value: totalPBytes})
return receipt, nil
}
//这里的power指的是修改后的power
func (o *Oracle) ProcessModifyValidator(address string, power int64) (*types.Receipt, error) {
var exist bool
receipt := new(types.Receipt)
validatorMaps, err := o.GetValidatorArray()
if err != nil {
return nil, err
}
elog.Info("ProcessModifyValidator", "pre validatorMaps", validatorMaps, "Modify Address", address, "Modify power", power)
var totalPower int64
for index, p := range validatorMaps.Validators {
if address != p.Address {
totalPower += p.Power
} else {
validatorMaps.Validators[index].Power = power
exist = true
totalPower += power
}
}
if !exist {
return nil, x2eTy.ErrAddressNotExist
}
v := types.Encode(validatorMaps)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalValidatorMapsPrefix(), Value: v})
totalP := x2eTy.ReceiptQueryTotalPower{
TotalPower: totalPower,
}
totalPBytes := types.Encode(&totalP)
receipt.KV = append(receipt.KV, &types.KeyValue{Key: x2eTy.CalLastTotalPowerPrefix(), Value: totalPBytes})
return receipt, nil
}
func (o *Oracle) ProcessSetConsensusNeeded(ConsensusThreshold int64) (int64, int64, error) {
preCon := o.GetConsensusThreshold()
o.SetConsensusThreshold(ConsensusThreshold)
nowCon := o.GetConsensusThreshold()
elog.Info("ProcessSetConsensusNeeded", "pre ConsensusThreshold", preCon, "now ConsensusThreshold", nowCon)
return preCon, nowCon, nil
}
func (o *Oracle) GetProphecy(id string) (*x2eTy.ReceiptEthProphecy, error) {
if id == "" {
return nil, x2eTy.ErrInvalidIdentifier
}
bz, err := o.db.Get(x2eTy.CalProphecyPrefix(id))
if err != nil && err != types.ErrNotFound {
return nil, x2eTy.ErrProphecyGet
} else if err == types.ErrNotFound {
return nil, x2eTy.ErrProphecyNotFound
}
var dbProphecy x2eTy.ReceiptEthProphecy
err = types.Decode(bz, &dbProphecy)
if err != nil {
return nil, types.ErrUnmarshal
}
return &dbProphecy, nil
}
// setProphecy saves a prophecy with an initial claim
func (o *Oracle) setProphecy(prophecy *x2eTy.ReceiptEthProphecy) error {
err := o.checkProphecy(prophecy)
if err != nil {
return err
}
bz, err := o.db.Get(x2eTy.CalProphecyPrefix(prophecy.ID))
if err != nil && err != types.ErrNotFound {
return x2eTy.ErrProphecyGet
}
var dbProphecy x2eTy.ReceiptEthProphecy
if err != types.ErrNotFound {
err = types.Decode(bz, &dbProphecy)
if err != nil {
return types.ErrUnmarshal
}
}
dbProphecy = *prophecy
serializedProphecyBytes := types.Encode(&dbProphecy)
err = o.db.Set(x2eTy.CalProphecyPrefix(prophecy.ID), serializedProphecyBytes)
if err != nil {
return x2eTy.ErrSetKV
}
return nil
}
func (o *Oracle) checkProphecy(prophecy *x2eTy.ReceiptEthProphecy) error {
if prophecy.ID == "" {
return x2eTy.ErrInvalidIdentifier
}
if len(prophecy.ClaimValidators) == 0 {
return x2eTy.ErrNoClaims
}
return nil
}
// 处理接收到的ethchain33请求
func (o *Oracle) ProcessClaim(claim x2eTy.Eth2Chain33) (*x2eTy.ProphecyStatus, error) {
oracleClaim, err := CreateOracleClaimFromEthClaim(claim)
if err != nil {
elog.Error("CreateEthClaimFromOracleString", "CreateOracleClaimFromOracleString error", err)
return nil, err
}
activeValidator := o.checkActiveValidator(oracleClaim.ValidatorAddress)
if !activeValidator {
return nil, x2eTy.ErrInvalidValidator
}
if strings.TrimSpace(oracleClaim.Content) == "" {
return nil, x2eTy.ErrInvalidClaim
}
var claimContent x2eTy.OracleClaimContent
err = types.Decode([]byte(oracleClaim.Content), &claimContent)
if err != nil {
return nil, types.ErrUnmarshal
}
prophecy, err := o.GetProphecy(oracleClaim.ID)
if err != nil {
if err != x2eTy.ErrProphecyNotFound {
return nil, err
}
prophecy = NewProphecy(oracleClaim.ID)
} else {
var exist bool
for _, vc := range prophecy.ValidatorClaims {
if vc.Claim == oracleClaim.Content {
exist = true
}
}
if !exist {
prophecy.Status.Text = x2eTy.EthBridgeStatus_FailedStatusText
return nil, x2eTy.ErrClaimInconsist
}
if prophecy.Status.Text == x2eTy.EthBridgeStatus_FailedStatusText {
return nil, x2eTy.ErrProphecyFinalized
}
for _, vc := range prophecy.ValidatorClaims {
if vc.Validator == claim.ValidatorAddress && vc.Claim != "" {
return nil, x2eTy.ErrDuplicateMessage
}
}
}
AddClaim(prophecy, oracleClaim.ValidatorAddress, oracleClaim.Content)
prophecy, err = o.processCompletion(prophecy, claimContent.ClaimType)
if err != nil {
return nil, err
}
err = o.setProphecy(prophecy)
if err != nil {
return nil, err
}
return prophecy.Status, nil
}
func (o *Oracle) checkActiveValidator(validatorAddress string) bool {
validatorMap, err := o.GetValidatorArray()
if err != nil {
return false
}
for _, v := range validatorMap.Validators {
if v.Address == validatorAddress {
return true
}
}
return false
}
// 计算该prophecy是否达标
func (o *Oracle) processCompletion(prophecy *x2eTy.ReceiptEthProphecy, claimType int64) (*x2eTy.ReceiptEthProphecy, error) {
address2power := make(map[string]int64)
validatorArrays, err := o.GetValidatorArray()
if err != nil {
return nil, err
}
for _, validator := range validatorArrays.Validators {
address2power[validator.Address] = validator.Power
}
highestClaim, highestClaimPower, totalClaimsPower := FindHighestClaim(prophecy, address2power)
totalPower, err := o.GetLastTotalPower()
if err != nil {
return nil, err
}
highestConsensusRatio := highestClaimPower * 100
remainingPossibleClaimPower := totalPower - totalClaimsPower
highestPossibleClaimPower := highestClaimPower + remainingPossibleClaimPower
highestPossibleConsensusRatio := highestPossibleClaimPower * 100
elog.Info("processCompletion", "highestConsensusRatio", highestConsensusRatio/totalPower, "ConsensusThreshold", o.consensusThreshold, "highestPossibleConsensusRatio", highestPossibleConsensusRatio/totalPower)
if highestConsensusRatio >= o.consensusThreshold*totalPower {
prophecy.Status.Text = x2eTy.EthBridgeStatus_SuccessStatusText
prophecy.Status.FinalClaim = highestClaim
} else if highestPossibleConsensusRatio < o.consensusThreshold*totalPower {
prophecy.Status.Text = x2eTy.EthBridgeStatus_FailedStatusText
}
return prophecy, nil
}
// Load the last total validator power.
func (o *Oracle) GetLastTotalPower() (int64, error) {
b, err := o.db.Get(x2eTy.CalLastTotalPowerPrefix())
if err != nil && err != types.ErrNotFound {
return 0, err
} else if err == types.ErrNotFound {
return 0, nil
}
var powers x2eTy.ReceiptQueryTotalPower
err = types.Decode(b, &powers)
if err != nil {
return 0, types.ErrUnmarshal
}
return powers.TotalPower, nil
}
// Set the last total validator power.
func (o *Oracle) SetLastTotalPower() error {
var totalPower int64
validatorArrays, err := o.GetValidatorArray()
if err != nil {
return err
}
for _, validator := range validatorArrays.Validators {
totalPower += validator.Power
}
totalP := x2eTy.ReceiptQueryTotalPower{
TotalPower: totalPower,
}
totalPBytes := types.Encode(&totalP)
err = o.db.Set(x2eTy.CalLastTotalPowerPrefix(), totalPBytes)
if err != nil {
return x2eTy.ErrSetKV
}
return nil
}
func (o *Oracle) GetValidatorArray() (*x2eTy.ValidatorList, error) {
validatorsBytes, err := o.db.Get(x2eTy.CalValidatorMapsPrefix())
if err != nil {
return nil, err
}
var validatorArrays x2eTy.ValidatorList
err = types.Decode(validatorsBytes, &validatorArrays)
if err != nil {
return nil, types.ErrUnmarshal
}
return &validatorArrays, nil
}
func (o *Oracle) SetConsensusThreshold(ConsensusThreshold int64) {
o.consensusThreshold = ConsensusThreshold
elog.Info("SetConsensusNeeded", "nowConsensusNeeded", o.consensusThreshold)
}
func (o *Oracle) GetConsensusThreshold() int64 {
return o.consensusThreshold
}
package x2ethereum
import (
"github.com/33cn/chain33/pluginmgr"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/commands"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/executor"
"github.com/33cn/plugin/plugin/dapp/x2ethereum/rpc"
x2ethereumtypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
/*
* 初始化dapp相关的组件
*/
func init() {
pluginmgr.Register(&pluginmgr.PluginBase{
Name: x2ethereumtypes.X2ethereumX,
ExecName: executor.GetName(),
Exec: executor.Init,
Cmd: commands.Cmd,
RPC: rpc.Init,
})
}
#!/bin/sh
# proto生成命令,将pb.go文件生成到types/目录下, chain33_path支持引用chain33框架的proto文件
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";
import "x2ethereum.proto";
package types;
// EthBridgeClaim is a structure that contains all the data for a particular bridge claim
message OracleClaim {
string ID = 1;
string ValidatorAddress = 2;
string Content = 3;
}
message Prophecy {
string ID = 1;
ProphecyStatus Status = 2;
repeated ClaimValidators ClaimValidators = 3;
repeated ValidatorClaims ValidatorClaims = 4;
}
syntax = "proto3";
package types;
import "transaction.proto";
import "account.proto";
enum EthBridgeStatus {
PendingStatusText = 0;
SuccessStatusText = 1;
FailedStatusText = 2;
}
message X2ethereumAction {
oneof value {
Eth2Chain33 eth2Chain33Lock = 1;
Eth2Chain33 eth2Chain33Burn = 2;
Chain33ToEth chain33ToEthBurn = 3;
Chain33ToEth chain33ToEthLock = 4;
MsgValidator addValidator = 5;
MsgValidator removeValidator = 6;
MsgValidator modifyPower = 7;
MsgConsensusThreshold setConsensusThreshold = 8;
AssetsTransfer transfer = 9;
AssetsTransferToExec transferToExec = 10;
AssetsWithdraw withdrawFromExec = 11;
}
int32 ty = 12;
}
message MsgConsensusThreshold {
int64 consensusThreshold = 1;
}
message MsgValidator {
string address = 1;
int64 power = 2;
}
// EthBridgeClaim is a structure that contains all the data for a particular bridge claim
message Eth2Chain33 {
int64 EthereumChainID = 1;
string BridgeContractAddress = 2;
int64 Nonce = 3;
string IssuerDotSymbol = 4;
string TokenContractAddress = 6;
string EthereumSender = 7;
string Chain33Receiver = 8;
string ValidatorAddress = 9;
string Amount = 10;
int64 ClaimType = 11;
int64 Decimals = 12;
}
// OracleClaimContent is the details of how the content of the claim for each validator will be stored in the oracle
message OracleClaimContent {
string Chain33Receiver = 1;
string Amount = 2;
int64 ClaimType = 3;
int64 Decimals = 4;
}
// MsgBurn defines a message for burning coins and triggering a related event
message Chain33ToEth {
string TokenContract = 1;
string Chain33Sender = 2;
string EthereumReceiver = 3;
string Amount = 4;
string IssuerDotSymbol = 5;
int64 Decimals = 7;
}
// 回执接口定义
message ReceiptEth2Chain33 {
int64 EthereumChainID = 1;
string BridgeContractAddress = 2;
int64 Nonce = 3;
string IssuerDotSymbol = 4;
string TokenAddress = 5;
string EthereumSender = 7;
string Chain33Receiver = 8;
string ValidatorAddress = 9;
string Amount = 10;
int64 ClaimType = 11;
bytes xTxHash = 12;
uint64 xHeight = 13;
string ProphecyID = 14;
int64 Decimals = 15;
}
message ReceiptChain33ToEth {
string TokenContract = 1;
string Chain33Sender = 2;
string EthereumReceiver = 3;
string Amount = 4;
string IssuerDotSymbol = 5;
int64 Decimals = 6;
}
message ReceiptValidator {
string address = 1;
int64 power = 2;
bytes xTxHash = 3;
uint64 xHeight = 4;
}
message ReceiptSetConsensusThreshold {
int64 preConsensusThreshold = 1;
int64 nowConsensusThreshold = 2;
bytes xTxHash = 3;
uint64 xHeight = 4;
}
// 查询接口定义
message QueryEthProphecyParams {
string ID = 1;
}
message ReceiptEthProphecy {
string ID = 1;
ProphecyStatus Status = 2;
repeated ClaimValidators ClaimValidators = 3;
repeated ValidatorClaims ValidatorClaims = 4;
}
message ClaimValidators {
string claim = 1;
StringMap validators = 2;
}
message ValidatorClaims {
string validator = 1;
string claim = 2;
}
message StringMap {
repeated string validators = 1;
}
message ValidatorList {
repeated MsgValidator validators = 1;
}
message ProphecyStatus {
EthBridgeStatus Text = 1;
string FinalClaim = 2;
}
message QueryValidatorsParams {
string validator = 1;
}
message ReceiptQueryValidator {
repeated MsgValidator validators = 1;
int64 totalPower = 2;
}
message QueryTotalPowerParams {
}
message ReceiptQueryTotalPower {
int64 totalPower = 1;
}
message QueryConsensusThresholdParams {
}
message ReceiptQueryConsensusThreshold {
int64 consensusThreshold = 1;
}
message QuerySymbolAssetsByTxTypeParams {
string tokenSymbol = 1;
int64 direction = 2;
string txType = 3;
string tokenAddr = 4;
int64 decimal = 5;
}
message ReceiptQuerySymbolAssets {
repeated ReceiptQuerySymbolAssetsByTxType res = 1;
}
message ReceiptQuerySymbolAssetsByTxType {
string tokenSymbol = 1;
string totalAmount = 2;
string txType = 3;
int64 direction = 4;
string tokenAddr = 5;
}
message QueryRelayerBalance {
string tokenSymbol = 1;
string address = 2;
string tokenAddr = 3;
}
message ReceiptQueryRelayerBalance {
repeated ReceiptQueryRelayerBalanceForOneToken res = 1;
}
message ReceiptQueryRelayerBalanceForOneToken {
string balance = 1;
string tokenSymbol = 2;
string tokenAddr = 3;
}
message ReceiptTokenToTokenAddress {
repeated string tokenAddress = 1;
}
service x2ethereum {
}
package rpc
/*
* 实现json rpc和grpc service接口
* json rpc用Jrpc结构作为接收实例
* grpc使用channelClient结构作为接收实例
*/
// all query methods
//func (c *channelClient) queryEthProphecy(in types.QueryEthProphecyParams) (*types.ReceiptEthProphecy,error) {
//
//}
package rpc
import (
rpctypes "github.com/33cn/chain33/rpc/types"
x2ethereumtypes "github.com/33cn/plugin/plugin/dapp/x2ethereum/types"
)
/*
* rpc相关结构定义和初始化
*/
// 实现grpc的service接口
type channelClient struct {
rpctypes.ChannelClient
}
// Jrpc 实现json rpc调用实例
type Jrpc struct {
cli *channelClient
}
// Grpc grpc
type Grpc struct {
*channelClient
}
// Init init rpc
func Init(name string, s rpctypes.RPCServer) {
cli := &channelClient{}
grpc := &Grpc{channelClient: cli}
cli.Init(name, s, &Jrpc{cli: cli}, grpc)
//存在grpc service时注册grpc server,需要生成对应的pb.go文件
x2ethereumtypes.RegisterX2EthereumServer(s.GRPC(), grpc)
}
package types
var (
ProphecyKey = []byte("prefix_for_Prophecy")
Eth2Chain33Key = []byte("prefix_for_Eth2Chain33")
WithdrawEthKey = []byte("prefix_for_WithdrawEth")
Chain33ToEthKey = []byte("prefix_for_Chain33ToEth")
WithdrawChain33Key = []byte("prefix_for_WithdrawChain33")
LastTotalPowerKey = []byte("prefix_for_LastTotalPower")
ValidatorMapsKey = []byte("prefix_for_ValidatorMaps")
ConsensusThresholdKey = []byte("prefix_for_ConsensusThreshold")
TokenSymbolTotalLockOrBurnAmountKey = []byte("prefix_for_TokenSymbolTotalLockOrBurnAmount-")
TokenSymbolToTokenAddressKey = []byte("prefix_for_TokenSymbolToTokenAddress-")
)
// log for x2ethereum
// log类型id值
const (
TyUnknownLog = iota + 100
TyEth2Chain33Log
TyWithdrawEthLog
TyWithdrawChain33Log
TyChain33ToEthLog
TyAddValidatorLog
TyRemoveValidatorLog
TyModifyPowerLog
TySetConsensusThresholdLog
TyProphecyLog
TyTransferLog
TyTransferToExecLog
TyWithdrawFromExecLog
)
// action类型id和name,这些常量可以自定义修改
const (
TyUnknowAction = iota + 100
TyEth2Chain33Action
TyWithdrawEthAction
TyWithdrawChain33Action
TyChain33ToEthAction
TyAddValidatorAction
TyRemoveValidatorAction
TyModifyPowerAction
TySetConsensusThresholdAction
TyTransferAction
TyTransferToExecAction
TyWithdrawFromExecAction
NameEth2Chain33Action = "Eth2Chain33Lock"
NameWithdrawEthAction = "Eth2Chain33Burn"
NameWithdrawChain33Action = "Chain33ToEthBurn"
NameChain33ToEthAction = "Chain33ToEthLock"
NameAddValidatorAction = "AddValidator"
NameRemoveValidatorAction = "RemoveValidator"
NameModifyPowerAction = "ModifyPower"
NameSetConsensusThresholdAction = "SetConsensusThreshold"
NameTransferAction = "Transfer"
NameTransferToExecAction = "TransferToExec"
NameWithdrawFromExecAction = "WithdrawFromExec"
)
const DefaultConsensusNeeded = int64(70)
const (
DirEth2Chain33 = "eth2chain33"
DirChain33ToEth = "chain33toeth"
LockClaim = "lock"
BurnClaim = "burn"
)
var DirectionType = [3]string{"", DirEth2Chain33, DirChain33ToEth}
// query function name
const (
FuncQueryEthProphecy = "GetEthProphecy"
FuncQueryValidators = "GetValidators"
FuncQueryTotalPower = "GetTotalPower"
FuncQueryConsensusThreshold = "GetConsensusThreshold"
FuncQuerySymbolTotalAmountByTxType = "GetSymbolTotalAmountByTxType"
FuncQueryRelayerBalance = "GetRelayerBalance"
)
const (
LockClaimType = int32(1)
BurnClaimType = int32(2)
)
package types
import "errors"
var (
ErrInvalidClaimType = errors.New("invalid claim type provided")
ErrInvalidEthSymbol = errors.New("invalid symbol provided, symbol \"eth\" must have null address set as token contract address")
ErrInvalidChainID = errors.New("invalid ethereum chain id")
ErrInvalidEthAddress = errors.New("invalid ethereum address provided, must be a valid hex-encoded Ethereum address")
ErrInvalidEthNonce = errors.New("invalid ethereum nonce provided, must be >= 0")
ErrInvalidAddress = errors.New("invalid Chain33 address")
ErrInvalidIdentifier = errors.New("invalid identifier provided, must be a nonempty string")
ErrProphecyNotFound = errors.New("prophecy with given id not found")
ErrProphecyGet = errors.New("prophecy with given id find error")
ErrinternalDB = errors.New("internal error serializing/deserializing prophecy")
ErrNoClaims = errors.New("cannot create prophecy without initial claim")
ErrInvalidClaim = errors.New("claim cannot be empty string")
ErrProphecyFinalized = errors.New("prophecy already finalized")
ErrProphecyFailed = errors.New("prophecy failed so you can't burn this prophecy")
ErrDuplicateMessage = errors.New("already processed message from validator for this id")
ErrMinimumConsensusNeededInvalid = errors.New("minimum consensus proportion of validator staking power must be > 0 and <= 1")
ErrInvalidValidator = errors.New("validator is invalid")
ErrUnknownAddress = errors.New("module account does not exist")
ErrPowerIsNotEnough = errors.New("remove power is more than which this address saves")
ErrAddressNotExist = errors.New("this address doesn't exist in DB")
ErrInvalidProphecyID = errors.New("Prophecy ID is invalid")
ErrAddressExists = errors.New("This address already exists")
ErrInvalidAdminAddress = errors.New("This address is not admin address")
ErrClaimInconsist = errors.New("This claim does not consist with others")
ErrInvalidPower = errors.New("This power is invalid")
)
//common
var (
ErrSetKV = errors.New("Set KV error")
)
package types
import "strings"
/*
* 用户合约存取kv数据时,key值前缀需要满足一定规范
* 即key = keyPrefix + userKey
* 需要字段前缀查询时,使用’-‘作为分割符号
*/
var (
//KeyPrefixStateDB state db key必须前缀
KeyPrefixStateDB = "mavl-x2ethereum-"
//KeyPrefixLocalDB local db的key必须前缀
KeyPrefixLocalDB = "LODB-x2ethereum-"
)
func CalProphecyPrefix(id string) []byte {
return []byte(KeyPrefixStateDB + string(ProphecyKey) + id)
}
func CalEth2Chain33Prefix() []byte {
return []byte(KeyPrefixStateDB + string(Eth2Chain33Key))
}
func CalWithdrawEthPrefix() []byte {
return []byte(KeyPrefixStateDB + string(WithdrawEthKey))
}
func CalChain33ToEthPrefix() []byte {
return []byte(KeyPrefixStateDB + string(Chain33ToEthKey))
}
func CalWithdrawChain33Prefix() []byte {
return []byte(KeyPrefixStateDB + string(WithdrawChain33Key))
}
func CalValidatorMapsPrefix() []byte {
return []byte(KeyPrefixStateDB + string(ValidatorMapsKey))
}
func CalLastTotalPowerPrefix() []byte {
return []byte(KeyPrefixStateDB + string(LastTotalPowerKey))
}
func CalConsensusThresholdPrefix() []byte {
return []byte(KeyPrefixStateDB + string(ConsensusThresholdKey))
}
func CalTokenSymbolTotalLockOrBurnAmount(symbol, tokenAddress, direction, txType string) []byte {
return []byte(KeyPrefixLocalDB + string(TokenSymbolTotalLockOrBurnAmountKey) + direction + "-" + txType + "-" + strings.ToLower(symbol) + "-" + strings.ToLower(tokenAddress))
}
func CalTokenSymbolToTokenAddress(symbol string) []byte {
return []byte(KeyPrefixLocalDB + string(TokenSymbolToTokenAddressKey) + strings.ToLower(symbol))
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: oracle.proto
package types
import (
fmt "fmt"
math "math"
proto "github.com/golang/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// EthBridgeClaim is a structure that contains all the data for a particular bridge claim
type OracleClaim struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
ValidatorAddress string `protobuf:"bytes,2,opt,name=ValidatorAddress,proto3" json:"ValidatorAddress,omitempty"`
Content string `protobuf:"bytes,3,opt,name=Content,proto3" json:"Content,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OracleClaim) Reset() { *m = OracleClaim{} }
func (m *OracleClaim) String() string { return proto.CompactTextString(m) }
func (*OracleClaim) ProtoMessage() {}
func (*OracleClaim) Descriptor() ([]byte, []int) {
return fileDescriptor_b544994cdab50f02, []int{0}
}
func (m *OracleClaim) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OracleClaim.Unmarshal(m, b)
}
func (m *OracleClaim) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_OracleClaim.Marshal(b, m, deterministic)
}
func (m *OracleClaim) XXX_Merge(src proto.Message) {
xxx_messageInfo_OracleClaim.Merge(m, src)
}
func (m *OracleClaim) XXX_Size() int {
return xxx_messageInfo_OracleClaim.Size(m)
}
func (m *OracleClaim) XXX_DiscardUnknown() {
xxx_messageInfo_OracleClaim.DiscardUnknown(m)
}
var xxx_messageInfo_OracleClaim proto.InternalMessageInfo
func (m *OracleClaim) GetID() string {
if m != nil {
return m.ID
}
return ""
}
func (m *OracleClaim) GetValidatorAddress() string {
if m != nil {
return m.ValidatorAddress
}
return ""
}
func (m *OracleClaim) GetContent() string {
if m != nil {
return m.Content
}
return ""
}
type Prophecy struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Status *ProphecyStatus `protobuf:"bytes,2,opt,name=Status,proto3" json:"Status,omitempty"`
ClaimValidators []*ClaimValidators `protobuf:"bytes,3,rep,name=ClaimValidators,proto3" json:"ClaimValidators,omitempty"`
ValidatorClaims []*ValidatorClaims `protobuf:"bytes,4,rep,name=ValidatorClaims,proto3" json:"ValidatorClaims,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Prophecy) Reset() { *m = Prophecy{} }
func (m *Prophecy) String() string { return proto.CompactTextString(m) }
func (*Prophecy) ProtoMessage() {}
func (*Prophecy) Descriptor() ([]byte, []int) {
return fileDescriptor_b544994cdab50f02, []int{1}
}
func (m *Prophecy) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Prophecy.Unmarshal(m, b)
}
func (m *Prophecy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Prophecy.Marshal(b, m, deterministic)
}
func (m *Prophecy) XXX_Merge(src proto.Message) {
xxx_messageInfo_Prophecy.Merge(m, src)
}
func (m *Prophecy) XXX_Size() int {
return xxx_messageInfo_Prophecy.Size(m)
}
func (m *Prophecy) XXX_DiscardUnknown() {
xxx_messageInfo_Prophecy.DiscardUnknown(m)
}
var xxx_messageInfo_Prophecy proto.InternalMessageInfo
func (m *Prophecy) GetID() string {
if m != nil {
return m.ID
}
return ""
}
func (m *Prophecy) GetStatus() *ProphecyStatus {
if m != nil {
return m.Status
}
return nil
}
func (m *Prophecy) GetClaimValidators() []*ClaimValidators {
if m != nil {
return m.ClaimValidators
}
return nil
}
func (m *Prophecy) GetValidatorClaims() []*ValidatorClaims {
if m != nil {
return m.ValidatorClaims
}
return nil
}
func init() {
proto.RegisterType((*OracleClaim)(nil), "types.OracleClaim")
proto.RegisterType((*Prophecy)(nil), "types.Prophecy")
}
func init() {
proto.RegisterFile("oracle.proto", fileDescriptor_b544994cdab50f02)
}
var fileDescriptor_b544994cdab50f02 = []byte{
// 215 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xc9, 0x2f, 0x4a, 0x4c,
0xce, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x2d, 0xa9, 0x2c, 0x48, 0x2d, 0x96,
0x12, 0xa8, 0x30, 0x4a, 0x2d, 0xc9, 0x48, 0x2d, 0x4a, 0x2d, 0xcd, 0x85, 0x48, 0x28, 0x25, 0x73,
0x71, 0xfb, 0x83, 0x15, 0x3a, 0xe7, 0x24, 0x66, 0xe6, 0x0a, 0xf1, 0x71, 0x31, 0x79, 0xba, 0x48,
0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06, 0x31, 0x79, 0xba, 0x08, 0x69, 0x71, 0x09, 0x84, 0x25, 0xe6,
0x64, 0xa6, 0x24, 0x96, 0xe4, 0x17, 0x39, 0xa6, 0xa4, 0x14, 0xa5, 0x16, 0x17, 0x4b, 0x30, 0x81,
0x65, 0x31, 0xc4, 0x85, 0x24, 0xb8, 0xd8, 0x9d, 0xf3, 0xf3, 0x4a, 0x52, 0xf3, 0x4a, 0x24, 0x98,
0xc1, 0x4a, 0x60, 0x5c, 0xa5, 0xb3, 0x8c, 0x5c, 0x1c, 0x01, 0x45, 0xf9, 0x05, 0x19, 0xa9, 0xc9,
0x95, 0x18, 0x56, 0xe8, 0x72, 0xb1, 0x05, 0x97, 0x24, 0x96, 0x94, 0x42, 0x0c, 0xe6, 0x36, 0x12,
0xd5, 0x03, 0xbb, 0x55, 0x0f, 0xa6, 0x01, 0x22, 0x19, 0x04, 0x55, 0x24, 0xe4, 0xc0, 0xc5, 0x0f,
0x76, 0x2a, 0xdc, 0xfa, 0x62, 0x09, 0x66, 0x05, 0x66, 0x0d, 0x6e, 0x23, 0x31, 0xa8, 0x3e, 0x34,
0xd9, 0x20, 0x74, 0xe5, 0x20, 0x13, 0xe0, 0x3c, 0xb0, 0x5c, 0xb1, 0x04, 0x0b, 0x8a, 0x09, 0x68,
0xb2, 0x41, 0xe8, 0xca, 0x93, 0xd8, 0xc0, 0x61, 0x67, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, 0xaa,
0xc9, 0xe8, 0x1d, 0x64, 0x01, 0x00, 0x00,
}
package types
import (
"encoding/binary"
"errors"
"fmt"
"math"
"math/big"
"strings"
"github.com/33cn/chain33/common/address"
)
func Float64ToBytes(float float64) []byte {
result := make([]byte, 8)
binary.LittleEndian.PutUint64(result, math.Float64bits(float))
return result
}
func BytesToFloat64(bytes []byte) float64 {
return math.Float64frombits(binary.LittleEndian.Uint64(bytes))
}
func AddressIsEmpty(address string) bool {
if address == "" {
return true
}
var aa2 string
return address == aa2
}
func AddToStringMap(in *StringMap, validator string) *StringMap {
inStringMap := append(in.GetValidators(), validator)
stringMapRes := new(StringMap)
stringMapRes.Validators = inStringMap
return stringMapRes
}
func DivideSpecifyTimes(start, time int64) int64 {
for i := 0; i < int(time); i++ {
start /= 10
}
return start
}
func MultiplySpecifyTimes(start float64, time int64) float64 {
for i := 0; i < int(time); i++ {
start *= 10
}
return start
}
func Toeth(amount string, decimal int64) float64 {
bf := big.NewFloat(0)
var ok bool
bf, ok = bf.SetString(TrimZeroAndDot(amount))
if !ok {
return 0
}
bf = bf.Quo(bf, big.NewFloat(MultiplySpecifyTimes(1, decimal)))
f, _ := bf.Float64()
return f
}
//将eth单位的金额转为wei单位
func ToWei(amount float64, decimal int64) *big.Int {
var ok bool
bn := big.NewInt(1)
if decimal > 4 {
bn, ok = bn.SetString(TrimZeroAndDot(fmt.Sprintf("%.0f", MultiplySpecifyTimes(math.Trunc(amount*1e4), decimal-4))), 10)
} else {
bn, ok = bn.SetString(TrimZeroAndDot(fmt.Sprintf("%.0f", MultiplySpecifyTimes(amount, decimal))), 10)
}
if ok {
return bn
}
return nil
}
func TrimZeroAndDot(s string) string {
if strings.Contains(s, ".") {
var trimDotStr string
trimZeroStr := strings.TrimRight(s, "0")
trimDotStr = strings.TrimRight(trimZeroStr, ".")
return trimDotStr
}
return s
}
func CheckPower(power int64) bool {
if power <= 0 || power > 100 {
return false
}
return true
}
func DivideDot(in string) (left, right string, err error) {
if strings.Contains(in, ".") {
ss := strings.Split(in, ".")
return ss[0], ss[1], nil
}
return "", "", errors.New("Divide error")
}
func IsExecAddrMatch(name string, to string) bool {
toaddr := address.ExecAddress(name)
return toaddr == to
}
package types
import (
"encoding/json"
"reflect"
log "github.com/33cn/chain33/common/log/log15"
"github.com/33cn/chain33/types"
)
/*
* 交易相关类型定义
* 交易action通常有对应的log结构,用于交易回执日志记录
* 每一种action和log需要用id数值和name名称加以区分
*/
var (
//X2ethereumX 执行器名称定义
X2ethereumX = "x2ethereum"
//定义actionMap
actionMap = map[string]int32{
NameEth2Chain33Action: TyEth2Chain33Action,
NameWithdrawEthAction: TyWithdrawEthAction,
NameWithdrawChain33Action: TyWithdrawChain33Action,
NameChain33ToEthAction: TyChain33ToEthAction,
NameAddValidatorAction: TyAddValidatorAction,
NameRemoveValidatorAction: TyRemoveValidatorAction,
NameModifyPowerAction: TyModifyPowerAction,
NameSetConsensusThresholdAction: TySetConsensusThresholdAction,
NameTransferAction: TyTransferAction,
NameTransferToExecAction: TyTransferToExecAction,
NameWithdrawFromExecAction: TyWithdrawFromExecAction,
}
//定义log的id和具体log类型及名称,填入具体自定义log类型
logMap = map[int64]*types.LogInfo{
TyEth2Chain33Log: {Ty: reflect.TypeOf(ReceiptEth2Chain33{}), Name: "LogEth2Chain33"},
TyWithdrawEthLog: {Ty: reflect.TypeOf(ReceiptEth2Chain33{}), Name: "LogWithdrawEth"},
TyWithdrawChain33Log: {Ty: reflect.TypeOf(ReceiptChain33ToEth{}), Name: "LogWithdrawChain33"},
TyChain33ToEthLog: {Ty: reflect.TypeOf(ReceiptChain33ToEth{}), Name: "LogChain33ToEth"},
TyAddValidatorLog: {Ty: reflect.TypeOf(ReceiptValidator{}), Name: "LogAddValidator"},
TyRemoveValidatorLog: {Ty: reflect.TypeOf(ReceiptValidator{}), Name: "LogRemoveValidator"},
TyModifyPowerLog: {Ty: reflect.TypeOf(ReceiptValidator{}), Name: "LogModifyPower"},
TySetConsensusThresholdLog: {Ty: reflect.TypeOf(ReceiptSetConsensusThreshold{}), Name: "LogSetConsensusThreshold"},
TyProphecyLog: {Ty: reflect.TypeOf(ReceiptEthProphecy{}), Name: "LogEthProphecy"},
TyTransferLog: {Ty: reflect.TypeOf(types.ReceiptAccountTransfer{}), Name: "LogTransfer"},
TyTransferToExecLog: {Ty: reflect.TypeOf(types.ReceiptExecAccountTransfer{}), Name: "LogTokenExecTransfer"},
TyWithdrawFromExecLog: {Ty: reflect.TypeOf(types.ReceiptExecAccountTransfer{}), Name: "LogTokenExecWithdraw"},
}
tlog = log.New("module", "x2ethereum.types")
)
// init defines a register function
func init() {
types.AllowUserExec = append(types.AllowUserExec, []byte(X2ethereumX))
//注册合约启用高度
types.RegFork(X2ethereumX, InitFork)
types.RegExec(X2ethereumX, InitExecutor)
}
// InitFork defines register fork
func InitFork(cfg *types.Chain33Config) {
cfg.RegisterDappFork(X2ethereumX, "Enable", 0)
}
// InitExecutor defines register executor
func InitExecutor(cfg *types.Chain33Config) {
types.RegistorExecutor(X2ethereumX, NewType(cfg))
}
type X2ethereumType struct {
types.ExecTypeBase
}
func NewType(cfg *types.Chain33Config) *X2ethereumType {
c := &X2ethereumType{}
c.SetChild(c)
c.SetConfig(cfg)
return c
}
func (x *X2ethereumType) GetName() string {
return X2ethereumX
}
// GetPayload 获取合约action结构
func (x *X2ethereumType) GetPayload() types.Message {
return &X2EthereumAction{}
}
// GeTypeMap 获取合约action的id和name信息
func (x *X2ethereumType) GetTypeMap() map[string]int32 {
return actionMap
}
// GetLogMap 获取合约log相关信息
func (x *X2ethereumType) GetLogMap() map[int64]*types.LogInfo {
return logMap
}
// ActionName get PrivacyType action name
func (x X2ethereumType) ActionName(tx *types.Transaction) string {
var action X2EthereumAction
err := types.Decode(tx.Payload, &action)
if err != nil {
return "unknown-x2ethereum-err"
}
tlog.Info("ActionName", "ActionName", action.GetActionName())
return action.GetActionName()
}
// GetActionName get action name
func (action *X2EthereumAction) GetActionName() string {
if action.Ty == TyEth2Chain33Action && action.GetEth2Chain33Lock() != nil {
return "Eth2Chain33Lock"
} else if action.Ty == TyWithdrawEthAction && action.GetEth2Chain33Burn() != nil {
return "Eth2Chain33Burn"
} else if action.Ty == TyWithdrawChain33Action && action.GetChain33ToEthBurn() != nil {
return "Chain33ToEthBurn"
} else if action.Ty == TyChain33ToEthAction && action.GetChain33ToEthLock() != nil {
return "Chain33ToEthLock"
} else if action.Ty == TyAddValidatorAction && action.GetAddValidator() != nil {
return "AddValidator"
} else if action.Ty == TyRemoveValidatorAction && action.GetRemoveValidator() != nil {
return "RemoveValidator"
} else if action.Ty == TyModifyPowerAction && action.GetModifyPower() != nil {
return "ModifyPower"
} else if action.Ty == TySetConsensusThresholdAction && action.GetSetConsensusThreshold() != nil {
return "SetConsensusThreshold"
} else if action.Ty == TyTransferAction && action.GetTransfer() != nil {
return "Transfer"
} else if action.Ty == TyTransferToExecAction && action.GetTransferToExec() != nil {
return "TransferToExec"
} else if action.Ty == TyWithdrawFromExecAction && action.GetWithdrawFromExec() != nil {
return "WithdrawFromExec"
}
return "unknown-x2ethereum"
}
// CreateTx token 创建合约
func (x *X2ethereumType) CreateTx(action string, msg json.RawMessage) (*types.Transaction, error) {
tx, err := x.ExecTypeBase.CreateTx(action, msg)
if err != nil {
tlog.Error("token CreateTx failed", "err", err, "action", action, "msg", string(msg))
return nil, err
}
cfg := x.GetConfig()
if !cfg.IsPara() {
var transfer X2EthereumAction
err = types.Decode(tx.Payload, &transfer)
if err != nil {
tlog.Error("token CreateTx failed", "decode payload err", err, "action", action, "msg", string(msg))
return nil, err
}
if action == "Transfer" {
tx.To = transfer.GetTransfer().To
} else if action == "Withdraw" {
tx.To = transfer.GetWithdrawFromExec().To
} else if action == "TransferToExec" {
tx.To = transfer.GetTransferToExec().To
}
}
return tx, nil
}
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: x2ethereum.proto
package types
import (
context "context"
fmt "fmt"
math "math"
types "github.com/33cn/chain33/types"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type EthBridgeStatus int32
const (
EthBridgeStatus_PendingStatusText EthBridgeStatus = 0
EthBridgeStatus_SuccessStatusText EthBridgeStatus = 1
EthBridgeStatus_FailedStatusText EthBridgeStatus = 2
)
var EthBridgeStatus_name = map[int32]string{
0: "PendingStatusText",
1: "SuccessStatusText",
2: "FailedStatusText",
}
var EthBridgeStatus_value = map[string]int32{
"PendingStatusText": 0,
"SuccessStatusText": 1,
"FailedStatusText": 2,
}
func (x EthBridgeStatus) String() string {
return proto.EnumName(EthBridgeStatus_name, int32(x))
}
func (EthBridgeStatus) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{0}
}
type X2EthereumAction struct {
// Types that are valid to be assigned to Value:
// *X2EthereumAction_Eth2Chain33Lock
// *X2EthereumAction_Eth2Chain33Burn
// *X2EthereumAction_Chain33ToEthBurn
// *X2EthereumAction_Chain33ToEthLock
// *X2EthereumAction_AddValidator
// *X2EthereumAction_RemoveValidator
// *X2EthereumAction_ModifyPower
// *X2EthereumAction_SetConsensusThreshold
// *X2EthereumAction_Transfer
// *X2EthereumAction_TransferToExec
// *X2EthereumAction_WithdrawFromExec
Value isX2EthereumAction_Value `protobuf_oneof:"value"`
Ty int32 `protobuf:"varint,12,opt,name=ty,proto3" json:"ty,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *X2EthereumAction) Reset() { *m = X2EthereumAction{} }
func (m *X2EthereumAction) String() string { return proto.CompactTextString(m) }
func (*X2EthereumAction) ProtoMessage() {}
func (*X2EthereumAction) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{0}
}
func (m *X2EthereumAction) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_X2EthereumAction.Unmarshal(m, b)
}
func (m *X2EthereumAction) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_X2EthereumAction.Marshal(b, m, deterministic)
}
func (m *X2EthereumAction) XXX_Merge(src proto.Message) {
xxx_messageInfo_X2EthereumAction.Merge(m, src)
}
func (m *X2EthereumAction) XXX_Size() int {
return xxx_messageInfo_X2EthereumAction.Size(m)
}
func (m *X2EthereumAction) XXX_DiscardUnknown() {
xxx_messageInfo_X2EthereumAction.DiscardUnknown(m)
}
var xxx_messageInfo_X2EthereumAction proto.InternalMessageInfo
type isX2EthereumAction_Value interface {
isX2EthereumAction_Value()
}
type X2EthereumAction_Eth2Chain33Lock struct {
Eth2Chain33Lock *Eth2Chain33 `protobuf:"bytes,1,opt,name=eth2Chain33Lock,proto3,oneof"`
}
type X2EthereumAction_Eth2Chain33Burn struct {
Eth2Chain33Burn *Eth2Chain33 `protobuf:"bytes,2,opt,name=eth2Chain33Burn,proto3,oneof"`
}
type X2EthereumAction_Chain33ToEthBurn struct {
Chain33ToEthBurn *Chain33ToEth `protobuf:"bytes,3,opt,name=chain33ToEthBurn,proto3,oneof"`
}
type X2EthereumAction_Chain33ToEthLock struct {
Chain33ToEthLock *Chain33ToEth `protobuf:"bytes,4,opt,name=chain33ToEthLock,proto3,oneof"`
}
type X2EthereumAction_AddValidator struct {
AddValidator *MsgValidator `protobuf:"bytes,5,opt,name=addValidator,proto3,oneof"`
}
type X2EthereumAction_RemoveValidator struct {
RemoveValidator *MsgValidator `protobuf:"bytes,6,opt,name=removeValidator,proto3,oneof"`
}
type X2EthereumAction_ModifyPower struct {
ModifyPower *MsgValidator `protobuf:"bytes,7,opt,name=modifyPower,proto3,oneof"`
}
type X2EthereumAction_SetConsensusThreshold struct {
SetConsensusThreshold *MsgConsensusThreshold `protobuf:"bytes,8,opt,name=setConsensusThreshold,proto3,oneof"`
}
type X2EthereumAction_Transfer struct {
Transfer *types.AssetsTransfer `protobuf:"bytes,9,opt,name=transfer,proto3,oneof"`
}
type X2EthereumAction_TransferToExec struct {
TransferToExec *types.AssetsTransferToExec `protobuf:"bytes,10,opt,name=transferToExec,proto3,oneof"`
}
type X2EthereumAction_WithdrawFromExec struct {
WithdrawFromExec *types.AssetsWithdraw `protobuf:"bytes,11,opt,name=withdrawFromExec,proto3,oneof"`
}
func (*X2EthereumAction_Eth2Chain33Lock) isX2EthereumAction_Value() {}
func (*X2EthereumAction_Eth2Chain33Burn) isX2EthereumAction_Value() {}
func (*X2EthereumAction_Chain33ToEthBurn) isX2EthereumAction_Value() {}
func (*X2EthereumAction_Chain33ToEthLock) isX2EthereumAction_Value() {}
func (*X2EthereumAction_AddValidator) isX2EthereumAction_Value() {}
func (*X2EthereumAction_RemoveValidator) isX2EthereumAction_Value() {}
func (*X2EthereumAction_ModifyPower) isX2EthereumAction_Value() {}
func (*X2EthereumAction_SetConsensusThreshold) isX2EthereumAction_Value() {}
func (*X2EthereumAction_Transfer) isX2EthereumAction_Value() {}
func (*X2EthereumAction_TransferToExec) isX2EthereumAction_Value() {}
func (*X2EthereumAction_WithdrawFromExec) isX2EthereumAction_Value() {}
func (m *X2EthereumAction) GetValue() isX2EthereumAction_Value {
if m != nil {
return m.Value
}
return nil
}
func (m *X2EthereumAction) GetEth2Chain33Lock() *Eth2Chain33 {
if x, ok := m.GetValue().(*X2EthereumAction_Eth2Chain33Lock); ok {
return x.Eth2Chain33Lock
}
return nil
}
func (m *X2EthereumAction) GetEth2Chain33Burn() *Eth2Chain33 {
if x, ok := m.GetValue().(*X2EthereumAction_Eth2Chain33Burn); ok {
return x.Eth2Chain33Burn
}
return nil
}
func (m *X2EthereumAction) GetChain33ToEthBurn() *Chain33ToEth {
if x, ok := m.GetValue().(*X2EthereumAction_Chain33ToEthBurn); ok {
return x.Chain33ToEthBurn
}
return nil
}
func (m *X2EthereumAction) GetChain33ToEthLock() *Chain33ToEth {
if x, ok := m.GetValue().(*X2EthereumAction_Chain33ToEthLock); ok {
return x.Chain33ToEthLock
}
return nil
}
func (m *X2EthereumAction) GetAddValidator() *MsgValidator {
if x, ok := m.GetValue().(*X2EthereumAction_AddValidator); ok {
return x.AddValidator
}
return nil
}
func (m *X2EthereumAction) GetRemoveValidator() *MsgValidator {
if x, ok := m.GetValue().(*X2EthereumAction_RemoveValidator); ok {
return x.RemoveValidator
}
return nil
}
func (m *X2EthereumAction) GetModifyPower() *MsgValidator {
if x, ok := m.GetValue().(*X2EthereumAction_ModifyPower); ok {
return x.ModifyPower
}
return nil
}
func (m *X2EthereumAction) GetSetConsensusThreshold() *MsgConsensusThreshold {
if x, ok := m.GetValue().(*X2EthereumAction_SetConsensusThreshold); ok {
return x.SetConsensusThreshold
}
return nil
}
func (m *X2EthereumAction) GetTransfer() *types.AssetsTransfer {
if x, ok := m.GetValue().(*X2EthereumAction_Transfer); ok {
return x.Transfer
}
return nil
}
func (m *X2EthereumAction) GetTransferToExec() *types.AssetsTransferToExec {
if x, ok := m.GetValue().(*X2EthereumAction_TransferToExec); ok {
return x.TransferToExec
}
return nil
}
func (m *X2EthereumAction) GetWithdrawFromExec() *types.AssetsWithdraw {
if x, ok := m.GetValue().(*X2EthereumAction_WithdrawFromExec); ok {
return x.WithdrawFromExec
}
return nil
}
func (m *X2EthereumAction) GetTy() int32 {
if m != nil {
return m.Ty
}
return 0
}
// XXX_OneofWrappers is for the internal use of the proto package.
func (*X2EthereumAction) XXX_OneofWrappers() []interface{} {
return []interface{}{
(*X2EthereumAction_Eth2Chain33Lock)(nil),
(*X2EthereumAction_Eth2Chain33Burn)(nil),
(*X2EthereumAction_Chain33ToEthBurn)(nil),
(*X2EthereumAction_Chain33ToEthLock)(nil),
(*X2EthereumAction_AddValidator)(nil),
(*X2EthereumAction_RemoveValidator)(nil),
(*X2EthereumAction_ModifyPower)(nil),
(*X2EthereumAction_SetConsensusThreshold)(nil),
(*X2EthereumAction_Transfer)(nil),
(*X2EthereumAction_TransferToExec)(nil),
(*X2EthereumAction_WithdrawFromExec)(nil),
}
}
type MsgConsensusThreshold struct {
ConsensusThreshold int64 `protobuf:"varint,1,opt,name=consensusThreshold,proto3" json:"consensusThreshold,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MsgConsensusThreshold) Reset() { *m = MsgConsensusThreshold{} }
func (m *MsgConsensusThreshold) String() string { return proto.CompactTextString(m) }
func (*MsgConsensusThreshold) ProtoMessage() {}
func (*MsgConsensusThreshold) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{1}
}
func (m *MsgConsensusThreshold) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MsgConsensusThreshold.Unmarshal(m, b)
}
func (m *MsgConsensusThreshold) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_MsgConsensusThreshold.Marshal(b, m, deterministic)
}
func (m *MsgConsensusThreshold) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgConsensusThreshold.Merge(m, src)
}
func (m *MsgConsensusThreshold) XXX_Size() int {
return xxx_messageInfo_MsgConsensusThreshold.Size(m)
}
func (m *MsgConsensusThreshold) XXX_DiscardUnknown() {
xxx_messageInfo_MsgConsensusThreshold.DiscardUnknown(m)
}
var xxx_messageInfo_MsgConsensusThreshold proto.InternalMessageInfo
func (m *MsgConsensusThreshold) GetConsensusThreshold() int64 {
if m != nil {
return m.ConsensusThreshold
}
return 0
}
type MsgValidator struct {
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *MsgValidator) Reset() { *m = MsgValidator{} }
func (m *MsgValidator) String() string { return proto.CompactTextString(m) }
func (*MsgValidator) ProtoMessage() {}
func (*MsgValidator) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{2}
}
func (m *MsgValidator) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_MsgValidator.Unmarshal(m, b)
}
func (m *MsgValidator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_MsgValidator.Marshal(b, m, deterministic)
}
func (m *MsgValidator) XXX_Merge(src proto.Message) {
xxx_messageInfo_MsgValidator.Merge(m, src)
}
func (m *MsgValidator) XXX_Size() int {
return xxx_messageInfo_MsgValidator.Size(m)
}
func (m *MsgValidator) XXX_DiscardUnknown() {
xxx_messageInfo_MsgValidator.DiscardUnknown(m)
}
var xxx_messageInfo_MsgValidator proto.InternalMessageInfo
func (m *MsgValidator) GetAddress() string {
if m != nil {
return m.Address
}
return ""
}
func (m *MsgValidator) GetPower() int64 {
if m != nil {
return m.Power
}
return 0
}
// EthBridgeClaim is a structure that contains all the data for a particular bridge claim
type Eth2Chain33 struct {
EthereumChainID int64 `protobuf:"varint,1,opt,name=EthereumChainID,proto3" json:"EthereumChainID,omitempty"`
BridgeContractAddress string `protobuf:"bytes,2,opt,name=BridgeContractAddress,proto3" json:"BridgeContractAddress,omitempty"`
Nonce int64 `protobuf:"varint,3,opt,name=Nonce,proto3" json:"Nonce,omitempty"`
IssuerDotSymbol string `protobuf:"bytes,4,opt,name=IssuerDotSymbol,proto3" json:"IssuerDotSymbol,omitempty"`
TokenContractAddress string `protobuf:"bytes,6,opt,name=TokenContractAddress,proto3" json:"TokenContractAddress,omitempty"`
EthereumSender string `protobuf:"bytes,7,opt,name=EthereumSender,proto3" json:"EthereumSender,omitempty"`
Chain33Receiver string `protobuf:"bytes,8,opt,name=Chain33Receiver,proto3" json:"Chain33Receiver,omitempty"`
ValidatorAddress string `protobuf:"bytes,9,opt,name=ValidatorAddress,proto3" json:"ValidatorAddress,omitempty"`
Amount string `protobuf:"bytes,10,opt,name=Amount,proto3" json:"Amount,omitempty"`
ClaimType int64 `protobuf:"varint,11,opt,name=ClaimType,proto3" json:"ClaimType,omitempty"`
Decimals int64 `protobuf:"varint,12,opt,name=Decimals,proto3" json:"Decimals,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Eth2Chain33) Reset() { *m = Eth2Chain33{} }
func (m *Eth2Chain33) String() string { return proto.CompactTextString(m) }
func (*Eth2Chain33) ProtoMessage() {}
func (*Eth2Chain33) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{3}
}
func (m *Eth2Chain33) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Eth2Chain33.Unmarshal(m, b)
}
func (m *Eth2Chain33) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Eth2Chain33.Marshal(b, m, deterministic)
}
func (m *Eth2Chain33) XXX_Merge(src proto.Message) {
xxx_messageInfo_Eth2Chain33.Merge(m, src)
}
func (m *Eth2Chain33) XXX_Size() int {
return xxx_messageInfo_Eth2Chain33.Size(m)
}
func (m *Eth2Chain33) XXX_DiscardUnknown() {
xxx_messageInfo_Eth2Chain33.DiscardUnknown(m)
}
var xxx_messageInfo_Eth2Chain33 proto.InternalMessageInfo
func (m *Eth2Chain33) GetEthereumChainID() int64 {
if m != nil {
return m.EthereumChainID
}
return 0
}
func (m *Eth2Chain33) GetBridgeContractAddress() string {
if m != nil {
return m.BridgeContractAddress
}
return ""
}
func (m *Eth2Chain33) GetNonce() int64 {
if m != nil {
return m.Nonce
}
return 0
}
func (m *Eth2Chain33) GetIssuerDotSymbol() string {
if m != nil {
return m.IssuerDotSymbol
}
return ""
}
func (m *Eth2Chain33) GetTokenContractAddress() string {
if m != nil {
return m.TokenContractAddress
}
return ""
}
func (m *Eth2Chain33) GetEthereumSender() string {
if m != nil {
return m.EthereumSender
}
return ""
}
func (m *Eth2Chain33) GetChain33Receiver() string {
if m != nil {
return m.Chain33Receiver
}
return ""
}
func (m *Eth2Chain33) GetValidatorAddress() string {
if m != nil {
return m.ValidatorAddress
}
return ""
}
func (m *Eth2Chain33) GetAmount() string {
if m != nil {
return m.Amount
}
return ""
}
func (m *Eth2Chain33) GetClaimType() int64 {
if m != nil {
return m.ClaimType
}
return 0
}
func (m *Eth2Chain33) GetDecimals() int64 {
if m != nil {
return m.Decimals
}
return 0
}
// OracleClaimContent is the details of how the content of the claim for each validator will be stored in the oracle
type OracleClaimContent struct {
Chain33Receiver string `protobuf:"bytes,1,opt,name=Chain33Receiver,proto3" json:"Chain33Receiver,omitempty"`
Amount string `protobuf:"bytes,2,opt,name=Amount,proto3" json:"Amount,omitempty"`
ClaimType int64 `protobuf:"varint,3,opt,name=ClaimType,proto3" json:"ClaimType,omitempty"`
Decimals int64 `protobuf:"varint,4,opt,name=Decimals,proto3" json:"Decimals,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *OracleClaimContent) Reset() { *m = OracleClaimContent{} }
func (m *OracleClaimContent) String() string { return proto.CompactTextString(m) }
func (*OracleClaimContent) ProtoMessage() {}
func (*OracleClaimContent) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{4}
}
func (m *OracleClaimContent) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_OracleClaimContent.Unmarshal(m, b)
}
func (m *OracleClaimContent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_OracleClaimContent.Marshal(b, m, deterministic)
}
func (m *OracleClaimContent) XXX_Merge(src proto.Message) {
xxx_messageInfo_OracleClaimContent.Merge(m, src)
}
func (m *OracleClaimContent) XXX_Size() int {
return xxx_messageInfo_OracleClaimContent.Size(m)
}
func (m *OracleClaimContent) XXX_DiscardUnknown() {
xxx_messageInfo_OracleClaimContent.DiscardUnknown(m)
}
var xxx_messageInfo_OracleClaimContent proto.InternalMessageInfo
func (m *OracleClaimContent) GetChain33Receiver() string {
if m != nil {
return m.Chain33Receiver
}
return ""
}
func (m *OracleClaimContent) GetAmount() string {
if m != nil {
return m.Amount
}
return ""
}
func (m *OracleClaimContent) GetClaimType() int64 {
if m != nil {
return m.ClaimType
}
return 0
}
func (m *OracleClaimContent) GetDecimals() int64 {
if m != nil {
return m.Decimals
}
return 0
}
// MsgBurn defines a message for burning coins and triggering a related event
type Chain33ToEth struct {
TokenContract string `protobuf:"bytes,1,opt,name=TokenContract,proto3" json:"TokenContract,omitempty"`
Chain33Sender string `protobuf:"bytes,2,opt,name=Chain33Sender,proto3" json:"Chain33Sender,omitempty"`
EthereumReceiver string `protobuf:"bytes,3,opt,name=EthereumReceiver,proto3" json:"EthereumReceiver,omitempty"`
Amount string `protobuf:"bytes,4,opt,name=Amount,proto3" json:"Amount,omitempty"`
IssuerDotSymbol string `protobuf:"bytes,5,opt,name=IssuerDotSymbol,proto3" json:"IssuerDotSymbol,omitempty"`
Decimals int64 `protobuf:"varint,7,opt,name=Decimals,proto3" json:"Decimals,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Chain33ToEth) Reset() { *m = Chain33ToEth{} }
func (m *Chain33ToEth) String() string { return proto.CompactTextString(m) }
func (*Chain33ToEth) ProtoMessage() {}
func (*Chain33ToEth) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{5}
}
func (m *Chain33ToEth) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Chain33ToEth.Unmarshal(m, b)
}
func (m *Chain33ToEth) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Chain33ToEth.Marshal(b, m, deterministic)
}
func (m *Chain33ToEth) XXX_Merge(src proto.Message) {
xxx_messageInfo_Chain33ToEth.Merge(m, src)
}
func (m *Chain33ToEth) XXX_Size() int {
return xxx_messageInfo_Chain33ToEth.Size(m)
}
func (m *Chain33ToEth) XXX_DiscardUnknown() {
xxx_messageInfo_Chain33ToEth.DiscardUnknown(m)
}
var xxx_messageInfo_Chain33ToEth proto.InternalMessageInfo
func (m *Chain33ToEth) GetTokenContract() string {
if m != nil {
return m.TokenContract
}
return ""
}
func (m *Chain33ToEth) GetChain33Sender() string {
if m != nil {
return m.Chain33Sender
}
return ""
}
func (m *Chain33ToEth) GetEthereumReceiver() string {
if m != nil {
return m.EthereumReceiver
}
return ""
}
func (m *Chain33ToEth) GetAmount() string {
if m != nil {
return m.Amount
}
return ""
}
func (m *Chain33ToEth) GetIssuerDotSymbol() string {
if m != nil {
return m.IssuerDotSymbol
}
return ""
}
func (m *Chain33ToEth) GetDecimals() int64 {
if m != nil {
return m.Decimals
}
return 0
}
// 回执接口定义
type ReceiptEth2Chain33 struct {
EthereumChainID int64 `protobuf:"varint,1,opt,name=EthereumChainID,proto3" json:"EthereumChainID,omitempty"`
BridgeContractAddress string `protobuf:"bytes,2,opt,name=BridgeContractAddress,proto3" json:"BridgeContractAddress,omitempty"`
Nonce int64 `protobuf:"varint,3,opt,name=Nonce,proto3" json:"Nonce,omitempty"`
IssuerDotSymbol string `protobuf:"bytes,4,opt,name=IssuerDotSymbol,proto3" json:"IssuerDotSymbol,omitempty"`
TokenAddress string `protobuf:"bytes,5,opt,name=TokenAddress,proto3" json:"TokenAddress,omitempty"`
EthereumSender string `protobuf:"bytes,7,opt,name=EthereumSender,proto3" json:"EthereumSender,omitempty"`
Chain33Receiver string `protobuf:"bytes,8,opt,name=Chain33Receiver,proto3" json:"Chain33Receiver,omitempty"`
ValidatorAddress string `protobuf:"bytes,9,opt,name=ValidatorAddress,proto3" json:"ValidatorAddress,omitempty"`
Amount string `protobuf:"bytes,10,opt,name=Amount,proto3" json:"Amount,omitempty"`
ClaimType int64 `protobuf:"varint,11,opt,name=ClaimType,proto3" json:"ClaimType,omitempty"`
XTxHash []byte `protobuf:"bytes,12,opt,name=xTxHash,proto3" json:"xTxHash,omitempty"`
XHeight uint64 `protobuf:"varint,13,opt,name=xHeight,proto3" json:"xHeight,omitempty"`
ProphecyID string `protobuf:"bytes,14,opt,name=ProphecyID,proto3" json:"ProphecyID,omitempty"`
Decimals int64 `protobuf:"varint,15,opt,name=Decimals,proto3" json:"Decimals,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptEth2Chain33) Reset() { *m = ReceiptEth2Chain33{} }
func (m *ReceiptEth2Chain33) String() string { return proto.CompactTextString(m) }
func (*ReceiptEth2Chain33) ProtoMessage() {}
func (*ReceiptEth2Chain33) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{6}
}
func (m *ReceiptEth2Chain33) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptEth2Chain33.Unmarshal(m, b)
}
func (m *ReceiptEth2Chain33) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptEth2Chain33.Marshal(b, m, deterministic)
}
func (m *ReceiptEth2Chain33) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptEth2Chain33.Merge(m, src)
}
func (m *ReceiptEth2Chain33) XXX_Size() int {
return xxx_messageInfo_ReceiptEth2Chain33.Size(m)
}
func (m *ReceiptEth2Chain33) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptEth2Chain33.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptEth2Chain33 proto.InternalMessageInfo
func (m *ReceiptEth2Chain33) GetEthereumChainID() int64 {
if m != nil {
return m.EthereumChainID
}
return 0
}
func (m *ReceiptEth2Chain33) GetBridgeContractAddress() string {
if m != nil {
return m.BridgeContractAddress
}
return ""
}
func (m *ReceiptEth2Chain33) GetNonce() int64 {
if m != nil {
return m.Nonce
}
return 0
}
func (m *ReceiptEth2Chain33) GetIssuerDotSymbol() string {
if m != nil {
return m.IssuerDotSymbol
}
return ""
}
func (m *ReceiptEth2Chain33) GetTokenAddress() string {
if m != nil {
return m.TokenAddress
}
return ""
}
func (m *ReceiptEth2Chain33) GetEthereumSender() string {
if m != nil {
return m.EthereumSender
}
return ""
}
func (m *ReceiptEth2Chain33) GetChain33Receiver() string {
if m != nil {
return m.Chain33Receiver
}
return ""
}
func (m *ReceiptEth2Chain33) GetValidatorAddress() string {
if m != nil {
return m.ValidatorAddress
}
return ""
}
func (m *ReceiptEth2Chain33) GetAmount() string {
if m != nil {
return m.Amount
}
return ""
}
func (m *ReceiptEth2Chain33) GetClaimType() int64 {
if m != nil {
return m.ClaimType
}
return 0
}
func (m *ReceiptEth2Chain33) GetXTxHash() []byte {
if m != nil {
return m.XTxHash
}
return nil
}
func (m *ReceiptEth2Chain33) GetXHeight() uint64 {
if m != nil {
return m.XHeight
}
return 0
}
func (m *ReceiptEth2Chain33) GetProphecyID() string {
if m != nil {
return m.ProphecyID
}
return ""
}
func (m *ReceiptEth2Chain33) GetDecimals() int64 {
if m != nil {
return m.Decimals
}
return 0
}
type ReceiptChain33ToEth struct {
TokenContract string `protobuf:"bytes,1,opt,name=TokenContract,proto3" json:"TokenContract,omitempty"`
Chain33Sender string `protobuf:"bytes,2,opt,name=Chain33Sender,proto3" json:"Chain33Sender,omitempty"`
EthereumReceiver string `protobuf:"bytes,3,opt,name=EthereumReceiver,proto3" json:"EthereumReceiver,omitempty"`
Amount string `protobuf:"bytes,4,opt,name=Amount,proto3" json:"Amount,omitempty"`
IssuerDotSymbol string `protobuf:"bytes,5,opt,name=IssuerDotSymbol,proto3" json:"IssuerDotSymbol,omitempty"`
Decimals int64 `protobuf:"varint,6,opt,name=Decimals,proto3" json:"Decimals,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptChain33ToEth) Reset() { *m = ReceiptChain33ToEth{} }
func (m *ReceiptChain33ToEth) String() string { return proto.CompactTextString(m) }
func (*ReceiptChain33ToEth) ProtoMessage() {}
func (*ReceiptChain33ToEth) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{7}
}
func (m *ReceiptChain33ToEth) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptChain33ToEth.Unmarshal(m, b)
}
func (m *ReceiptChain33ToEth) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptChain33ToEth.Marshal(b, m, deterministic)
}
func (m *ReceiptChain33ToEth) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptChain33ToEth.Merge(m, src)
}
func (m *ReceiptChain33ToEth) XXX_Size() int {
return xxx_messageInfo_ReceiptChain33ToEth.Size(m)
}
func (m *ReceiptChain33ToEth) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptChain33ToEth.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptChain33ToEth proto.InternalMessageInfo
func (m *ReceiptChain33ToEth) GetTokenContract() string {
if m != nil {
return m.TokenContract
}
return ""
}
func (m *ReceiptChain33ToEth) GetChain33Sender() string {
if m != nil {
return m.Chain33Sender
}
return ""
}
func (m *ReceiptChain33ToEth) GetEthereumReceiver() string {
if m != nil {
return m.EthereumReceiver
}
return ""
}
func (m *ReceiptChain33ToEth) GetAmount() string {
if m != nil {
return m.Amount
}
return ""
}
func (m *ReceiptChain33ToEth) GetIssuerDotSymbol() string {
if m != nil {
return m.IssuerDotSymbol
}
return ""
}
func (m *ReceiptChain33ToEth) GetDecimals() int64 {
if m != nil {
return m.Decimals
}
return 0
}
type ReceiptValidator struct {
Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
Power int64 `protobuf:"varint,2,opt,name=power,proto3" json:"power,omitempty"`
XTxHash []byte `protobuf:"bytes,3,opt,name=xTxHash,proto3" json:"xTxHash,omitempty"`
XHeight uint64 `protobuf:"varint,4,opt,name=xHeight,proto3" json:"xHeight,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptValidator) Reset() { *m = ReceiptValidator{} }
func (m *ReceiptValidator) String() string { return proto.CompactTextString(m) }
func (*ReceiptValidator) ProtoMessage() {}
func (*ReceiptValidator) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{8}
}
func (m *ReceiptValidator) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptValidator.Unmarshal(m, b)
}
func (m *ReceiptValidator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptValidator.Marshal(b, m, deterministic)
}
func (m *ReceiptValidator) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptValidator.Merge(m, src)
}
func (m *ReceiptValidator) XXX_Size() int {
return xxx_messageInfo_ReceiptValidator.Size(m)
}
func (m *ReceiptValidator) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptValidator.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptValidator proto.InternalMessageInfo
func (m *ReceiptValidator) GetAddress() string {
if m != nil {
return m.Address
}
return ""
}
func (m *ReceiptValidator) GetPower() int64 {
if m != nil {
return m.Power
}
return 0
}
func (m *ReceiptValidator) GetXTxHash() []byte {
if m != nil {
return m.XTxHash
}
return nil
}
func (m *ReceiptValidator) GetXHeight() uint64 {
if m != nil {
return m.XHeight
}
return 0
}
type ReceiptSetConsensusThreshold struct {
PreConsensusThreshold int64 `protobuf:"varint,1,opt,name=preConsensusThreshold,proto3" json:"preConsensusThreshold,omitempty"`
NowConsensusThreshold int64 `protobuf:"varint,2,opt,name=nowConsensusThreshold,proto3" json:"nowConsensusThreshold,omitempty"`
XTxHash []byte `protobuf:"bytes,3,opt,name=xTxHash,proto3" json:"xTxHash,omitempty"`
XHeight uint64 `protobuf:"varint,4,opt,name=xHeight,proto3" json:"xHeight,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptSetConsensusThreshold) Reset() { *m = ReceiptSetConsensusThreshold{} }
func (m *ReceiptSetConsensusThreshold) String() string { return proto.CompactTextString(m) }
func (*ReceiptSetConsensusThreshold) ProtoMessage() {}
func (*ReceiptSetConsensusThreshold) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{9}
}
func (m *ReceiptSetConsensusThreshold) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptSetConsensusThreshold.Unmarshal(m, b)
}
func (m *ReceiptSetConsensusThreshold) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptSetConsensusThreshold.Marshal(b, m, deterministic)
}
func (m *ReceiptSetConsensusThreshold) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptSetConsensusThreshold.Merge(m, src)
}
func (m *ReceiptSetConsensusThreshold) XXX_Size() int {
return xxx_messageInfo_ReceiptSetConsensusThreshold.Size(m)
}
func (m *ReceiptSetConsensusThreshold) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptSetConsensusThreshold.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptSetConsensusThreshold proto.InternalMessageInfo
func (m *ReceiptSetConsensusThreshold) GetPreConsensusThreshold() int64 {
if m != nil {
return m.PreConsensusThreshold
}
return 0
}
func (m *ReceiptSetConsensusThreshold) GetNowConsensusThreshold() int64 {
if m != nil {
return m.NowConsensusThreshold
}
return 0
}
func (m *ReceiptSetConsensusThreshold) GetXTxHash() []byte {
if m != nil {
return m.XTxHash
}
return nil
}
func (m *ReceiptSetConsensusThreshold) GetXHeight() uint64 {
if m != nil {
return m.XHeight
}
return 0
}
// 查询接口定义
type QueryEthProphecyParams struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QueryEthProphecyParams) Reset() { *m = QueryEthProphecyParams{} }
func (m *QueryEthProphecyParams) String() string { return proto.CompactTextString(m) }
func (*QueryEthProphecyParams) ProtoMessage() {}
func (*QueryEthProphecyParams) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{10}
}
func (m *QueryEthProphecyParams) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryEthProphecyParams.Unmarshal(m, b)
}
func (m *QueryEthProphecyParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QueryEthProphecyParams.Marshal(b, m, deterministic)
}
func (m *QueryEthProphecyParams) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryEthProphecyParams.Merge(m, src)
}
func (m *QueryEthProphecyParams) XXX_Size() int {
return xxx_messageInfo_QueryEthProphecyParams.Size(m)
}
func (m *QueryEthProphecyParams) XXX_DiscardUnknown() {
xxx_messageInfo_QueryEthProphecyParams.DiscardUnknown(m)
}
var xxx_messageInfo_QueryEthProphecyParams proto.InternalMessageInfo
func (m *QueryEthProphecyParams) GetID() string {
if m != nil {
return m.ID
}
return ""
}
type ReceiptEthProphecy struct {
ID string `protobuf:"bytes,1,opt,name=ID,proto3" json:"ID,omitempty"`
Status *ProphecyStatus `protobuf:"bytes,2,opt,name=Status,proto3" json:"Status,omitempty"`
ClaimValidators []*ClaimValidators `protobuf:"bytes,3,rep,name=ClaimValidators,proto3" json:"ClaimValidators,omitempty"`
ValidatorClaims []*ValidatorClaims `protobuf:"bytes,4,rep,name=ValidatorClaims,proto3" json:"ValidatorClaims,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptEthProphecy) Reset() { *m = ReceiptEthProphecy{} }
func (m *ReceiptEthProphecy) String() string { return proto.CompactTextString(m) }
func (*ReceiptEthProphecy) ProtoMessage() {}
func (*ReceiptEthProphecy) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{11}
}
func (m *ReceiptEthProphecy) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptEthProphecy.Unmarshal(m, b)
}
func (m *ReceiptEthProphecy) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptEthProphecy.Marshal(b, m, deterministic)
}
func (m *ReceiptEthProphecy) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptEthProphecy.Merge(m, src)
}
func (m *ReceiptEthProphecy) XXX_Size() int {
return xxx_messageInfo_ReceiptEthProphecy.Size(m)
}
func (m *ReceiptEthProphecy) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptEthProphecy.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptEthProphecy proto.InternalMessageInfo
func (m *ReceiptEthProphecy) GetID() string {
if m != nil {
return m.ID
}
return ""
}
func (m *ReceiptEthProphecy) GetStatus() *ProphecyStatus {
if m != nil {
return m.Status
}
return nil
}
func (m *ReceiptEthProphecy) GetClaimValidators() []*ClaimValidators {
if m != nil {
return m.ClaimValidators
}
return nil
}
func (m *ReceiptEthProphecy) GetValidatorClaims() []*ValidatorClaims {
if m != nil {
return m.ValidatorClaims
}
return nil
}
type ClaimValidators struct {
Claim string `protobuf:"bytes,1,opt,name=claim,proto3" json:"claim,omitempty"`
Validators *StringMap `protobuf:"bytes,2,opt,name=validators,proto3" json:"validators,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ClaimValidators) Reset() { *m = ClaimValidators{} }
func (m *ClaimValidators) String() string { return proto.CompactTextString(m) }
func (*ClaimValidators) ProtoMessage() {}
func (*ClaimValidators) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{12}
}
func (m *ClaimValidators) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ClaimValidators.Unmarshal(m, b)
}
func (m *ClaimValidators) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ClaimValidators.Marshal(b, m, deterministic)
}
func (m *ClaimValidators) XXX_Merge(src proto.Message) {
xxx_messageInfo_ClaimValidators.Merge(m, src)
}
func (m *ClaimValidators) XXX_Size() int {
return xxx_messageInfo_ClaimValidators.Size(m)
}
func (m *ClaimValidators) XXX_DiscardUnknown() {
xxx_messageInfo_ClaimValidators.DiscardUnknown(m)
}
var xxx_messageInfo_ClaimValidators proto.InternalMessageInfo
func (m *ClaimValidators) GetClaim() string {
if m != nil {
return m.Claim
}
return ""
}
func (m *ClaimValidators) GetValidators() *StringMap {
if m != nil {
return m.Validators
}
return nil
}
type ValidatorClaims struct {
Validator string `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator,omitempty"`
Claim string `protobuf:"bytes,2,opt,name=claim,proto3" json:"claim,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ValidatorClaims) Reset() { *m = ValidatorClaims{} }
func (m *ValidatorClaims) String() string { return proto.CompactTextString(m) }
func (*ValidatorClaims) ProtoMessage() {}
func (*ValidatorClaims) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{13}
}
func (m *ValidatorClaims) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ValidatorClaims.Unmarshal(m, b)
}
func (m *ValidatorClaims) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ValidatorClaims.Marshal(b, m, deterministic)
}
func (m *ValidatorClaims) XXX_Merge(src proto.Message) {
xxx_messageInfo_ValidatorClaims.Merge(m, src)
}
func (m *ValidatorClaims) XXX_Size() int {
return xxx_messageInfo_ValidatorClaims.Size(m)
}
func (m *ValidatorClaims) XXX_DiscardUnknown() {
xxx_messageInfo_ValidatorClaims.DiscardUnknown(m)
}
var xxx_messageInfo_ValidatorClaims proto.InternalMessageInfo
func (m *ValidatorClaims) GetValidator() string {
if m != nil {
return m.Validator
}
return ""
}
func (m *ValidatorClaims) GetClaim() string {
if m != nil {
return m.Claim
}
return ""
}
type StringMap struct {
Validators []string `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *StringMap) Reset() { *m = StringMap{} }
func (m *StringMap) String() string { return proto.CompactTextString(m) }
func (*StringMap) ProtoMessage() {}
func (*StringMap) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{14}
}
func (m *StringMap) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StringMap.Unmarshal(m, b)
}
func (m *StringMap) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_StringMap.Marshal(b, m, deterministic)
}
func (m *StringMap) XXX_Merge(src proto.Message) {
xxx_messageInfo_StringMap.Merge(m, src)
}
func (m *StringMap) XXX_Size() int {
return xxx_messageInfo_StringMap.Size(m)
}
func (m *StringMap) XXX_DiscardUnknown() {
xxx_messageInfo_StringMap.DiscardUnknown(m)
}
var xxx_messageInfo_StringMap proto.InternalMessageInfo
func (m *StringMap) GetValidators() []string {
if m != nil {
return m.Validators
}
return nil
}
type ValidatorList struct {
Validators []*MsgValidator `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ValidatorList) Reset() { *m = ValidatorList{} }
func (m *ValidatorList) String() string { return proto.CompactTextString(m) }
func (*ValidatorList) ProtoMessage() {}
func (*ValidatorList) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{15}
}
func (m *ValidatorList) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ValidatorList.Unmarshal(m, b)
}
func (m *ValidatorList) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ValidatorList.Marshal(b, m, deterministic)
}
func (m *ValidatorList) XXX_Merge(src proto.Message) {
xxx_messageInfo_ValidatorList.Merge(m, src)
}
func (m *ValidatorList) XXX_Size() int {
return xxx_messageInfo_ValidatorList.Size(m)
}
func (m *ValidatorList) XXX_DiscardUnknown() {
xxx_messageInfo_ValidatorList.DiscardUnknown(m)
}
var xxx_messageInfo_ValidatorList proto.InternalMessageInfo
func (m *ValidatorList) GetValidators() []*MsgValidator {
if m != nil {
return m.Validators
}
return nil
}
type ProphecyStatus struct {
Text EthBridgeStatus `protobuf:"varint,1,opt,name=Text,proto3,enum=types.EthBridgeStatus" json:"Text,omitempty"`
FinalClaim string `protobuf:"bytes,2,opt,name=FinalClaim,proto3" json:"FinalClaim,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ProphecyStatus) Reset() { *m = ProphecyStatus{} }
func (m *ProphecyStatus) String() string { return proto.CompactTextString(m) }
func (*ProphecyStatus) ProtoMessage() {}
func (*ProphecyStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{16}
}
func (m *ProphecyStatus) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ProphecyStatus.Unmarshal(m, b)
}
func (m *ProphecyStatus) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ProphecyStatus.Marshal(b, m, deterministic)
}
func (m *ProphecyStatus) XXX_Merge(src proto.Message) {
xxx_messageInfo_ProphecyStatus.Merge(m, src)
}
func (m *ProphecyStatus) XXX_Size() int {
return xxx_messageInfo_ProphecyStatus.Size(m)
}
func (m *ProphecyStatus) XXX_DiscardUnknown() {
xxx_messageInfo_ProphecyStatus.DiscardUnknown(m)
}
var xxx_messageInfo_ProphecyStatus proto.InternalMessageInfo
func (m *ProphecyStatus) GetText() EthBridgeStatus {
if m != nil {
return m.Text
}
return EthBridgeStatus_PendingStatusText
}
func (m *ProphecyStatus) GetFinalClaim() string {
if m != nil {
return m.FinalClaim
}
return ""
}
type QueryValidatorsParams struct {
Validator string `protobuf:"bytes,1,opt,name=validator,proto3" json:"validator,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QueryValidatorsParams) Reset() { *m = QueryValidatorsParams{} }
func (m *QueryValidatorsParams) String() string { return proto.CompactTextString(m) }
func (*QueryValidatorsParams) ProtoMessage() {}
func (*QueryValidatorsParams) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{17}
}
func (m *QueryValidatorsParams) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryValidatorsParams.Unmarshal(m, b)
}
func (m *QueryValidatorsParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QueryValidatorsParams.Marshal(b, m, deterministic)
}
func (m *QueryValidatorsParams) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryValidatorsParams.Merge(m, src)
}
func (m *QueryValidatorsParams) XXX_Size() int {
return xxx_messageInfo_QueryValidatorsParams.Size(m)
}
func (m *QueryValidatorsParams) XXX_DiscardUnknown() {
xxx_messageInfo_QueryValidatorsParams.DiscardUnknown(m)
}
var xxx_messageInfo_QueryValidatorsParams proto.InternalMessageInfo
func (m *QueryValidatorsParams) GetValidator() string {
if m != nil {
return m.Validator
}
return ""
}
type ReceiptQueryValidator struct {
Validators []*MsgValidator `protobuf:"bytes,1,rep,name=validators,proto3" json:"validators,omitempty"`
TotalPower int64 `protobuf:"varint,2,opt,name=totalPower,proto3" json:"totalPower,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptQueryValidator) Reset() { *m = ReceiptQueryValidator{} }
func (m *ReceiptQueryValidator) String() string { return proto.CompactTextString(m) }
func (*ReceiptQueryValidator) ProtoMessage() {}
func (*ReceiptQueryValidator) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{18}
}
func (m *ReceiptQueryValidator) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptQueryValidator.Unmarshal(m, b)
}
func (m *ReceiptQueryValidator) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptQueryValidator.Marshal(b, m, deterministic)
}
func (m *ReceiptQueryValidator) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptQueryValidator.Merge(m, src)
}
func (m *ReceiptQueryValidator) XXX_Size() int {
return xxx_messageInfo_ReceiptQueryValidator.Size(m)
}
func (m *ReceiptQueryValidator) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptQueryValidator.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptQueryValidator proto.InternalMessageInfo
func (m *ReceiptQueryValidator) GetValidators() []*MsgValidator {
if m != nil {
return m.Validators
}
return nil
}
func (m *ReceiptQueryValidator) GetTotalPower() int64 {
if m != nil {
return m.TotalPower
}
return 0
}
type QueryTotalPowerParams struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QueryTotalPowerParams) Reset() { *m = QueryTotalPowerParams{} }
func (m *QueryTotalPowerParams) String() string { return proto.CompactTextString(m) }
func (*QueryTotalPowerParams) ProtoMessage() {}
func (*QueryTotalPowerParams) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{19}
}
func (m *QueryTotalPowerParams) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryTotalPowerParams.Unmarshal(m, b)
}
func (m *QueryTotalPowerParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QueryTotalPowerParams.Marshal(b, m, deterministic)
}
func (m *QueryTotalPowerParams) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryTotalPowerParams.Merge(m, src)
}
func (m *QueryTotalPowerParams) XXX_Size() int {
return xxx_messageInfo_QueryTotalPowerParams.Size(m)
}
func (m *QueryTotalPowerParams) XXX_DiscardUnknown() {
xxx_messageInfo_QueryTotalPowerParams.DiscardUnknown(m)
}
var xxx_messageInfo_QueryTotalPowerParams proto.InternalMessageInfo
type ReceiptQueryTotalPower struct {
TotalPower int64 `protobuf:"varint,1,opt,name=totalPower,proto3" json:"totalPower,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptQueryTotalPower) Reset() { *m = ReceiptQueryTotalPower{} }
func (m *ReceiptQueryTotalPower) String() string { return proto.CompactTextString(m) }
func (*ReceiptQueryTotalPower) ProtoMessage() {}
func (*ReceiptQueryTotalPower) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{20}
}
func (m *ReceiptQueryTotalPower) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptQueryTotalPower.Unmarshal(m, b)
}
func (m *ReceiptQueryTotalPower) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptQueryTotalPower.Marshal(b, m, deterministic)
}
func (m *ReceiptQueryTotalPower) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptQueryTotalPower.Merge(m, src)
}
func (m *ReceiptQueryTotalPower) XXX_Size() int {
return xxx_messageInfo_ReceiptQueryTotalPower.Size(m)
}
func (m *ReceiptQueryTotalPower) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptQueryTotalPower.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptQueryTotalPower proto.InternalMessageInfo
func (m *ReceiptQueryTotalPower) GetTotalPower() int64 {
if m != nil {
return m.TotalPower
}
return 0
}
type QueryConsensusThresholdParams struct {
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QueryConsensusThresholdParams) Reset() { *m = QueryConsensusThresholdParams{} }
func (m *QueryConsensusThresholdParams) String() string { return proto.CompactTextString(m) }
func (*QueryConsensusThresholdParams) ProtoMessage() {}
func (*QueryConsensusThresholdParams) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{21}
}
func (m *QueryConsensusThresholdParams) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryConsensusThresholdParams.Unmarshal(m, b)
}
func (m *QueryConsensusThresholdParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QueryConsensusThresholdParams.Marshal(b, m, deterministic)
}
func (m *QueryConsensusThresholdParams) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryConsensusThresholdParams.Merge(m, src)
}
func (m *QueryConsensusThresholdParams) XXX_Size() int {
return xxx_messageInfo_QueryConsensusThresholdParams.Size(m)
}
func (m *QueryConsensusThresholdParams) XXX_DiscardUnknown() {
xxx_messageInfo_QueryConsensusThresholdParams.DiscardUnknown(m)
}
var xxx_messageInfo_QueryConsensusThresholdParams proto.InternalMessageInfo
type ReceiptQueryConsensusThreshold struct {
ConsensusThreshold int64 `protobuf:"varint,1,opt,name=consensusThreshold,proto3" json:"consensusThreshold,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptQueryConsensusThreshold) Reset() { *m = ReceiptQueryConsensusThreshold{} }
func (m *ReceiptQueryConsensusThreshold) String() string { return proto.CompactTextString(m) }
func (*ReceiptQueryConsensusThreshold) ProtoMessage() {}
func (*ReceiptQueryConsensusThreshold) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{22}
}
func (m *ReceiptQueryConsensusThreshold) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptQueryConsensusThreshold.Unmarshal(m, b)
}
func (m *ReceiptQueryConsensusThreshold) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptQueryConsensusThreshold.Marshal(b, m, deterministic)
}
func (m *ReceiptQueryConsensusThreshold) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptQueryConsensusThreshold.Merge(m, src)
}
func (m *ReceiptQueryConsensusThreshold) XXX_Size() int {
return xxx_messageInfo_ReceiptQueryConsensusThreshold.Size(m)
}
func (m *ReceiptQueryConsensusThreshold) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptQueryConsensusThreshold.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptQueryConsensusThreshold proto.InternalMessageInfo
func (m *ReceiptQueryConsensusThreshold) GetConsensusThreshold() int64 {
if m != nil {
return m.ConsensusThreshold
}
return 0
}
type QuerySymbolAssetsByTxTypeParams struct {
TokenSymbol string `protobuf:"bytes,1,opt,name=tokenSymbol,proto3" json:"tokenSymbol,omitempty"`
Direction int64 `protobuf:"varint,2,opt,name=direction,proto3" json:"direction,omitempty"`
TxType string `protobuf:"bytes,3,opt,name=txType,proto3" json:"txType,omitempty"`
TokenAddr string `protobuf:"bytes,4,opt,name=tokenAddr,proto3" json:"tokenAddr,omitempty"`
Decimal int64 `protobuf:"varint,5,opt,name=decimal,proto3" json:"decimal,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QuerySymbolAssetsByTxTypeParams) Reset() { *m = QuerySymbolAssetsByTxTypeParams{} }
func (m *QuerySymbolAssetsByTxTypeParams) String() string { return proto.CompactTextString(m) }
func (*QuerySymbolAssetsByTxTypeParams) ProtoMessage() {}
func (*QuerySymbolAssetsByTxTypeParams) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{23}
}
func (m *QuerySymbolAssetsByTxTypeParams) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QuerySymbolAssetsByTxTypeParams.Unmarshal(m, b)
}
func (m *QuerySymbolAssetsByTxTypeParams) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QuerySymbolAssetsByTxTypeParams.Marshal(b, m, deterministic)
}
func (m *QuerySymbolAssetsByTxTypeParams) XXX_Merge(src proto.Message) {
xxx_messageInfo_QuerySymbolAssetsByTxTypeParams.Merge(m, src)
}
func (m *QuerySymbolAssetsByTxTypeParams) XXX_Size() int {
return xxx_messageInfo_QuerySymbolAssetsByTxTypeParams.Size(m)
}
func (m *QuerySymbolAssetsByTxTypeParams) XXX_DiscardUnknown() {
xxx_messageInfo_QuerySymbolAssetsByTxTypeParams.DiscardUnknown(m)
}
var xxx_messageInfo_QuerySymbolAssetsByTxTypeParams proto.InternalMessageInfo
func (m *QuerySymbolAssetsByTxTypeParams) GetTokenSymbol() string {
if m != nil {
return m.TokenSymbol
}
return ""
}
func (m *QuerySymbolAssetsByTxTypeParams) GetDirection() int64 {
if m != nil {
return m.Direction
}
return 0
}
func (m *QuerySymbolAssetsByTxTypeParams) GetTxType() string {
if m != nil {
return m.TxType
}
return ""
}
func (m *QuerySymbolAssetsByTxTypeParams) GetTokenAddr() string {
if m != nil {
return m.TokenAddr
}
return ""
}
func (m *QuerySymbolAssetsByTxTypeParams) GetDecimal() int64 {
if m != nil {
return m.Decimal
}
return 0
}
type ReceiptQuerySymbolAssets struct {
Res []*ReceiptQuerySymbolAssetsByTxType `protobuf:"bytes,1,rep,name=res,proto3" json:"res,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptQuerySymbolAssets) Reset() { *m = ReceiptQuerySymbolAssets{} }
func (m *ReceiptQuerySymbolAssets) String() string { return proto.CompactTextString(m) }
func (*ReceiptQuerySymbolAssets) ProtoMessage() {}
func (*ReceiptQuerySymbolAssets) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{24}
}
func (m *ReceiptQuerySymbolAssets) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptQuerySymbolAssets.Unmarshal(m, b)
}
func (m *ReceiptQuerySymbolAssets) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptQuerySymbolAssets.Marshal(b, m, deterministic)
}
func (m *ReceiptQuerySymbolAssets) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptQuerySymbolAssets.Merge(m, src)
}
func (m *ReceiptQuerySymbolAssets) XXX_Size() int {
return xxx_messageInfo_ReceiptQuerySymbolAssets.Size(m)
}
func (m *ReceiptQuerySymbolAssets) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptQuerySymbolAssets.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptQuerySymbolAssets proto.InternalMessageInfo
func (m *ReceiptQuerySymbolAssets) GetRes() []*ReceiptQuerySymbolAssetsByTxType {
if m != nil {
return m.Res
}
return nil
}
type ReceiptQuerySymbolAssetsByTxType struct {
TokenSymbol string `protobuf:"bytes,1,opt,name=tokenSymbol,proto3" json:"tokenSymbol,omitempty"`
TotalAmount string `protobuf:"bytes,2,opt,name=totalAmount,proto3" json:"totalAmount,omitempty"`
TxType string `protobuf:"bytes,3,opt,name=txType,proto3" json:"txType,omitempty"`
Direction int64 `protobuf:"varint,4,opt,name=direction,proto3" json:"direction,omitempty"`
TokenAddr string `protobuf:"bytes,5,opt,name=tokenAddr,proto3" json:"tokenAddr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptQuerySymbolAssetsByTxType) Reset() { *m = ReceiptQuerySymbolAssetsByTxType{} }
func (m *ReceiptQuerySymbolAssetsByTxType) String() string { return proto.CompactTextString(m) }
func (*ReceiptQuerySymbolAssetsByTxType) ProtoMessage() {}
func (*ReceiptQuerySymbolAssetsByTxType) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{25}
}
func (m *ReceiptQuerySymbolAssetsByTxType) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptQuerySymbolAssetsByTxType.Unmarshal(m, b)
}
func (m *ReceiptQuerySymbolAssetsByTxType) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptQuerySymbolAssetsByTxType.Marshal(b, m, deterministic)
}
func (m *ReceiptQuerySymbolAssetsByTxType) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptQuerySymbolAssetsByTxType.Merge(m, src)
}
func (m *ReceiptQuerySymbolAssetsByTxType) XXX_Size() int {
return xxx_messageInfo_ReceiptQuerySymbolAssetsByTxType.Size(m)
}
func (m *ReceiptQuerySymbolAssetsByTxType) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptQuerySymbolAssetsByTxType.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptQuerySymbolAssetsByTxType proto.InternalMessageInfo
func (m *ReceiptQuerySymbolAssetsByTxType) GetTokenSymbol() string {
if m != nil {
return m.TokenSymbol
}
return ""
}
func (m *ReceiptQuerySymbolAssetsByTxType) GetTotalAmount() string {
if m != nil {
return m.TotalAmount
}
return ""
}
func (m *ReceiptQuerySymbolAssetsByTxType) GetTxType() string {
if m != nil {
return m.TxType
}
return ""
}
func (m *ReceiptQuerySymbolAssetsByTxType) GetDirection() int64 {
if m != nil {
return m.Direction
}
return 0
}
func (m *ReceiptQuerySymbolAssetsByTxType) GetTokenAddr() string {
if m != nil {
return m.TokenAddr
}
return ""
}
type QueryRelayerBalance struct {
TokenSymbol string `protobuf:"bytes,1,opt,name=tokenSymbol,proto3" json:"tokenSymbol,omitempty"`
Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"`
TokenAddr string `protobuf:"bytes,3,opt,name=tokenAddr,proto3" json:"tokenAddr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *QueryRelayerBalance) Reset() { *m = QueryRelayerBalance{} }
func (m *QueryRelayerBalance) String() string { return proto.CompactTextString(m) }
func (*QueryRelayerBalance) ProtoMessage() {}
func (*QueryRelayerBalance) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{26}
}
func (m *QueryRelayerBalance) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_QueryRelayerBalance.Unmarshal(m, b)
}
func (m *QueryRelayerBalance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_QueryRelayerBalance.Marshal(b, m, deterministic)
}
func (m *QueryRelayerBalance) XXX_Merge(src proto.Message) {
xxx_messageInfo_QueryRelayerBalance.Merge(m, src)
}
func (m *QueryRelayerBalance) XXX_Size() int {
return xxx_messageInfo_QueryRelayerBalance.Size(m)
}
func (m *QueryRelayerBalance) XXX_DiscardUnknown() {
xxx_messageInfo_QueryRelayerBalance.DiscardUnknown(m)
}
var xxx_messageInfo_QueryRelayerBalance proto.InternalMessageInfo
func (m *QueryRelayerBalance) GetTokenSymbol() string {
if m != nil {
return m.TokenSymbol
}
return ""
}
func (m *QueryRelayerBalance) GetAddress() string {
if m != nil {
return m.Address
}
return ""
}
func (m *QueryRelayerBalance) GetTokenAddr() string {
if m != nil {
return m.TokenAddr
}
return ""
}
type ReceiptQueryRelayerBalance struct {
Res []*ReceiptQueryRelayerBalanceForOneToken `protobuf:"bytes,1,rep,name=res,proto3" json:"res,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptQueryRelayerBalance) Reset() { *m = ReceiptQueryRelayerBalance{} }
func (m *ReceiptQueryRelayerBalance) String() string { return proto.CompactTextString(m) }
func (*ReceiptQueryRelayerBalance) ProtoMessage() {}
func (*ReceiptQueryRelayerBalance) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{27}
}
func (m *ReceiptQueryRelayerBalance) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptQueryRelayerBalance.Unmarshal(m, b)
}
func (m *ReceiptQueryRelayerBalance) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptQueryRelayerBalance.Marshal(b, m, deterministic)
}
func (m *ReceiptQueryRelayerBalance) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptQueryRelayerBalance.Merge(m, src)
}
func (m *ReceiptQueryRelayerBalance) XXX_Size() int {
return xxx_messageInfo_ReceiptQueryRelayerBalance.Size(m)
}
func (m *ReceiptQueryRelayerBalance) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptQueryRelayerBalance.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptQueryRelayerBalance proto.InternalMessageInfo
func (m *ReceiptQueryRelayerBalance) GetRes() []*ReceiptQueryRelayerBalanceForOneToken {
if m != nil {
return m.Res
}
return nil
}
type ReceiptQueryRelayerBalanceForOneToken struct {
Balance string `protobuf:"bytes,1,opt,name=balance,proto3" json:"balance,omitempty"`
TokenSymbol string `protobuf:"bytes,2,opt,name=tokenSymbol,proto3" json:"tokenSymbol,omitempty"`
TokenAddr string `protobuf:"bytes,3,opt,name=tokenAddr,proto3" json:"tokenAddr,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptQueryRelayerBalanceForOneToken) Reset() { *m = ReceiptQueryRelayerBalanceForOneToken{} }
func (m *ReceiptQueryRelayerBalanceForOneToken) String() string { return proto.CompactTextString(m) }
func (*ReceiptQueryRelayerBalanceForOneToken) ProtoMessage() {}
func (*ReceiptQueryRelayerBalanceForOneToken) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{28}
}
func (m *ReceiptQueryRelayerBalanceForOneToken) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptQueryRelayerBalanceForOneToken.Unmarshal(m, b)
}
func (m *ReceiptQueryRelayerBalanceForOneToken) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptQueryRelayerBalanceForOneToken.Marshal(b, m, deterministic)
}
func (m *ReceiptQueryRelayerBalanceForOneToken) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptQueryRelayerBalanceForOneToken.Merge(m, src)
}
func (m *ReceiptQueryRelayerBalanceForOneToken) XXX_Size() int {
return xxx_messageInfo_ReceiptQueryRelayerBalanceForOneToken.Size(m)
}
func (m *ReceiptQueryRelayerBalanceForOneToken) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptQueryRelayerBalanceForOneToken.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptQueryRelayerBalanceForOneToken proto.InternalMessageInfo
func (m *ReceiptQueryRelayerBalanceForOneToken) GetBalance() string {
if m != nil {
return m.Balance
}
return ""
}
func (m *ReceiptQueryRelayerBalanceForOneToken) GetTokenSymbol() string {
if m != nil {
return m.TokenSymbol
}
return ""
}
func (m *ReceiptQueryRelayerBalanceForOneToken) GetTokenAddr() string {
if m != nil {
return m.TokenAddr
}
return ""
}
type ReceiptTokenToTokenAddress struct {
TokenAddress []string `protobuf:"bytes,1,rep,name=tokenAddress,proto3" json:"tokenAddress,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ReceiptTokenToTokenAddress) Reset() { *m = ReceiptTokenToTokenAddress{} }
func (m *ReceiptTokenToTokenAddress) String() string { return proto.CompactTextString(m) }
func (*ReceiptTokenToTokenAddress) ProtoMessage() {}
func (*ReceiptTokenToTokenAddress) Descriptor() ([]byte, []int) {
return fileDescriptor_1dd1834a817ceb21, []int{29}
}
func (m *ReceiptTokenToTokenAddress) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReceiptTokenToTokenAddress.Unmarshal(m, b)
}
func (m *ReceiptTokenToTokenAddress) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_ReceiptTokenToTokenAddress.Marshal(b, m, deterministic)
}
func (m *ReceiptTokenToTokenAddress) XXX_Merge(src proto.Message) {
xxx_messageInfo_ReceiptTokenToTokenAddress.Merge(m, src)
}
func (m *ReceiptTokenToTokenAddress) XXX_Size() int {
return xxx_messageInfo_ReceiptTokenToTokenAddress.Size(m)
}
func (m *ReceiptTokenToTokenAddress) XXX_DiscardUnknown() {
xxx_messageInfo_ReceiptTokenToTokenAddress.DiscardUnknown(m)
}
var xxx_messageInfo_ReceiptTokenToTokenAddress proto.InternalMessageInfo
func (m *ReceiptTokenToTokenAddress) GetTokenAddress() []string {
if m != nil {
return m.TokenAddress
}
return nil
}
func init() {
proto.RegisterEnum("types.EthBridgeStatus", EthBridgeStatus_name, EthBridgeStatus_value)
proto.RegisterType((*X2EthereumAction)(nil), "types.X2ethereumAction")
proto.RegisterType((*MsgConsensusThreshold)(nil), "types.MsgConsensusThreshold")
proto.RegisterType((*MsgValidator)(nil), "types.MsgValidator")
proto.RegisterType((*Eth2Chain33)(nil), "types.Eth2Chain33")
proto.RegisterType((*OracleClaimContent)(nil), "types.OracleClaimContent")
proto.RegisterType((*Chain33ToEth)(nil), "types.Chain33ToEth")
proto.RegisterType((*ReceiptEth2Chain33)(nil), "types.ReceiptEth2Chain33")
proto.RegisterType((*ReceiptChain33ToEth)(nil), "types.ReceiptChain33ToEth")
proto.RegisterType((*ReceiptValidator)(nil), "types.ReceiptValidator")
proto.RegisterType((*ReceiptSetConsensusThreshold)(nil), "types.ReceiptSetConsensusThreshold")
proto.RegisterType((*QueryEthProphecyParams)(nil), "types.QueryEthProphecyParams")
proto.RegisterType((*ReceiptEthProphecy)(nil), "types.ReceiptEthProphecy")
proto.RegisterType((*ClaimValidators)(nil), "types.ClaimValidators")
proto.RegisterType((*ValidatorClaims)(nil), "types.ValidatorClaims")
proto.RegisterType((*StringMap)(nil), "types.StringMap")
proto.RegisterType((*ValidatorList)(nil), "types.ValidatorList")
proto.RegisterType((*ProphecyStatus)(nil), "types.ProphecyStatus")
proto.RegisterType((*QueryValidatorsParams)(nil), "types.QueryValidatorsParams")
proto.RegisterType((*ReceiptQueryValidator)(nil), "types.ReceiptQueryValidator")
proto.RegisterType((*QueryTotalPowerParams)(nil), "types.QueryTotalPowerParams")
proto.RegisterType((*ReceiptQueryTotalPower)(nil), "types.ReceiptQueryTotalPower")
proto.RegisterType((*QueryConsensusThresholdParams)(nil), "types.QueryConsensusThresholdParams")
proto.RegisterType((*ReceiptQueryConsensusThreshold)(nil), "types.ReceiptQueryConsensusThreshold")
proto.RegisterType((*QuerySymbolAssetsByTxTypeParams)(nil), "types.QuerySymbolAssetsByTxTypeParams")
proto.RegisterType((*ReceiptQuerySymbolAssets)(nil), "types.ReceiptQuerySymbolAssets")
proto.RegisterType((*ReceiptQuerySymbolAssetsByTxType)(nil), "types.ReceiptQuerySymbolAssetsByTxType")
proto.RegisterType((*QueryRelayerBalance)(nil), "types.QueryRelayerBalance")
proto.RegisterType((*ReceiptQueryRelayerBalance)(nil), "types.ReceiptQueryRelayerBalance")
proto.RegisterType((*ReceiptQueryRelayerBalanceForOneToken)(nil), "types.ReceiptQueryRelayerBalanceForOneToken")
proto.RegisterType((*ReceiptTokenToTokenAddress)(nil), "types.ReceiptTokenToTokenAddress")
}
func init() {
proto.RegisterFile("x2ethereum.proto", fileDescriptor_1dd1834a817ceb21)
}
var fileDescriptor_1dd1834a817ceb21 = []byte{
// 1379 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xdc, 0x58, 0xcd, 0x6e, 0xdb, 0x46,
0x10, 0x16, 0x45, 0xc9, 0x8e, 0xc6, 0xb2, 0xad, 0x6c, 0x22, 0x97, 0x70, 0xd3, 0x44, 0x20, 0xfa,
0x63, 0xa4, 0xad, 0x51, 0xd8, 0x29, 0xda, 0x5c, 0xd2, 0xd8, 0xb2, 0x5c, 0x19, 0x48, 0x1a, 0x77,
0xcd, 0xf4, 0x07, 0xc8, 0x65, 0x4d, 0x6e, 0x2c, 0x22, 0x14, 0x29, 0x2c, 0x57, 0xb6, 0x74, 0xec,
0x1b, 0xf4, 0x55, 0x72, 0xed, 0xa1, 0xaf, 0xd1, 0x17, 0xe8, 0xad, 0xaf, 0xd0, 0x02, 0xc5, 0x2e,
0x97, 0xe4, 0x92, 0xa2, 0x1d, 0x23, 0xe8, 0x25, 0xbd, 0x69, 0x67, 0xbe, 0xf9, 0x9f, 0x9d, 0x1d,
0x0a, 0x3a, 0xb3, 0x1d, 0xca, 0x47, 0x94, 0xd1, 0xe9, 0x78, 0x7b, 0xc2, 0x22, 0x1e, 0xa1, 0x26,
0x9f, 0x4f, 0x68, 0xbc, 0x79, 0x93, 0x33, 0x12, 0xc6, 0xc4, 0xe5, 0x7e, 0x14, 0x26, 0x9c, 0xcd,
0x55, 0xe2, 0xba, 0xd1, 0x34, 0xe4, 0xc9, 0xd1, 0xfe, 0xa7, 0x09, 0x9d, 0x9f, 0x32, 0xe9, 0x3d,
0x89, 0x44, 0x8f, 0x60, 0x9d, 0xf2, 0xd1, 0x4e, 0x7f, 0x44, 0xfc, 0x70, 0x77, 0xf7, 0x49, 0xe4,
0xbe, 0xb2, 0x8c, 0x9e, 0xb1, 0xb5, 0xb2, 0x83, 0xb6, 0xa5, 0xde, 0xed, 0x41, 0xce, 0x1d, 0xd6,
0x70, 0x19, 0x5c, 0x92, 0xdf, 0x9f, 0xb2, 0xd0, 0xaa, 0x5f, 0x53, 0x5e, 0x80, 0xd1, 0x1e, 0x74,
0xdc, 0xe4, 0xe8, 0x44, 0x03, 0x3e, 0x92, 0x0a, 0x4c, 0xa9, 0xe0, 0x96, 0x52, 0xd0, 0xd7, 0xd8,
0xc3, 0x1a, 0x5e, 0x80, 0x97, 0x55, 0xc8, 0x18, 0x1a, 0xd7, 0x56, 0x21, 0xa3, 0x78, 0x08, 0x6d,
0xe2, 0x79, 0x3f, 0x90, 0xc0, 0xf7, 0x08, 0x8f, 0x98, 0xd5, 0x2c, 0x88, 0x3f, 0x8d, 0xcf, 0x32,
0xd6, 0xb0, 0x86, 0x0b, 0x50, 0xf4, 0x0d, 0xac, 0x33, 0x3a, 0x8e, 0xce, 0x69, 0x2e, 0xbd, 0x74,
0x95, 0x74, 0x19, 0x8d, 0xbe, 0x82, 0x95, 0x71, 0xe4, 0xf9, 0x2f, 0xe7, 0xc7, 0xd1, 0x05, 0x65,
0xd6, 0xf2, 0x55, 0xc2, 0x3a, 0x12, 0x39, 0xd0, 0x8d, 0x29, 0xef, 0x47, 0x61, 0x4c, 0xc3, 0x78,
0x1a, 0x3b, 0x23, 0x46, 0xe3, 0x51, 0x14, 0x78, 0xd6, 0x0d, 0xa9, 0xe2, 0x4e, 0xae, 0x62, 0x11,
0x33, 0xac, 0xe1, 0x6a, 0x61, 0xb4, 0x0b, 0x37, 0x64, 0x27, 0xbd, 0xa4, 0xcc, 0x6a, 0x49, 0x45,
0x5d, 0xa5, 0x68, 0x2f, 0x8e, 0x29, 0x8f, 0x1d, 0xc5, 0x1c, 0xd6, 0x70, 0x06, 0x44, 0x03, 0x58,
0x4b, 0x7f, 0x3b, 0xd1, 0x60, 0x46, 0x5d, 0x0b, 0xa4, 0xe8, 0xfb, 0x95, 0xa2, 0x09, 0x64, 0x58,
0xc3, 0x25, 0x21, 0xd4, 0x87, 0xce, 0x85, 0xcf, 0x47, 0x1e, 0x23, 0x17, 0x87, 0x2c, 0x1a, 0x4b,
0x45, 0x2b, 0x15, 0x3e, 0xfc, 0xa8, 0x40, 0xa2, 0x96, 0x65, 0x01, 0xb4, 0x06, 0x75, 0x3e, 0xb7,
0xda, 0x3d, 0x63, 0xab, 0x89, 0xeb, 0x7c, 0xbe, 0xbf, 0x0c, 0xcd, 0x73, 0x12, 0x4c, 0xa9, 0xfd,
0x2d, 0x74, 0x2b, 0x73, 0x81, 0xb6, 0x01, 0xb9, 0x8b, 0x59, 0x14, 0xd7, 0xc0, 0xc4, 0x15, 0x1c,
0xfb, 0x11, 0xb4, 0xf5, 0xba, 0x20, 0x0b, 0x96, 0x89, 0xe7, 0x31, 0x1a, 0xc7, 0x52, 0xa8, 0x85,
0xd3, 0x23, 0xba, 0x0d, 0xcd, 0x89, 0xac, 0x6a, 0x5d, 0x2a, 0x4b, 0x0e, 0xf6, 0x6b, 0x13, 0x56,
0xb4, 0x6b, 0x81, 0xb6, 0x60, 0x7d, 0xa0, 0x6e, 0xa5, 0x24, 0x1d, 0x1d, 0x28, 0xe3, 0x65, 0x32,
0x7a, 0x00, 0xdd, 0x7d, 0xe6, 0x7b, 0x67, 0xb4, 0x1f, 0x85, 0x9c, 0x11, 0x97, 0xef, 0x29, 0xbb,
0x75, 0x69, 0xb7, 0x9a, 0x29, 0xbc, 0xf8, 0x2e, 0x0a, 0x5d, 0x2a, 0x2f, 0x96, 0x89, 0x93, 0x83,
0xb0, 0x7a, 0x14, 0xc7, 0x53, 0xca, 0x0e, 0x22, 0x7e, 0x32, 0x1f, 0x9f, 0x46, 0x81, 0xbc, 0x35,
0x2d, 0x5c, 0x26, 0xa3, 0x1d, 0xb8, 0xed, 0x44, 0xaf, 0x68, 0x58, 0x36, 0xba, 0x24, 0xe1, 0x95,
0x3c, 0xf4, 0x31, 0xac, 0xa5, 0xce, 0x9f, 0xd0, 0xd0, 0x53, 0x8d, 0xdd, 0xc2, 0x25, 0xaa, 0xf0,
0x42, 0xa5, 0x01, 0x53, 0x97, 0xfa, 0xe7, 0x94, 0xc9, 0xf6, 0x6d, 0xe1, 0x32, 0x19, 0xdd, 0x87,
0x4e, 0x96, 0xf2, 0xd4, 0x83, 0x96, 0x84, 0x2e, 0xd0, 0xd1, 0x06, 0x2c, 0xed, 0x8d, 0xc5, 0xe8,
0x93, 0x7d, 0xd8, 0xc2, 0xea, 0x84, 0xee, 0x40, 0xab, 0x1f, 0x10, 0x7f, 0xec, 0xcc, 0x27, 0x54,
0x76, 0x96, 0x89, 0x73, 0x02, 0xda, 0x84, 0x1b, 0x07, 0xd4, 0xf5, 0xc7, 0x24, 0x88, 0x65, 0xff,
0x98, 0x38, 0x3b, 0xdb, 0xbf, 0x1a, 0x80, 0x9e, 0x31, 0xe2, 0x06, 0x54, 0xe2, 0x45, 0xb8, 0x34,
0xe4, 0x55, 0xee, 0x1b, 0xd5, 0xee, 0xe7, 0x2e, 0xd5, 0x2f, 0x77, 0xc9, 0xbc, 0xca, 0xa5, 0x46,
0xc9, 0xa5, 0x3f, 0x0d, 0x68, 0xeb, 0x93, 0x0d, 0x7d, 0x08, 0xab, 0x85, 0x5a, 0x28, 0x57, 0x8a,
0x44, 0x81, 0x52, 0x52, 0xaa, 0x30, 0x89, 0x3f, 0x45, 0xa2, 0xc8, 0x76, 0x5a, 0xa9, 0x2c, 0x32,
0x33, 0xc9, 0x76, 0x99, 0xae, 0x85, 0xd6, 0x28, 0x84, 0x56, 0xd1, 0x61, 0xcd, 0xea, 0x0e, 0xd3,
0xc3, 0x5c, 0x2e, 0x85, 0xf9, 0xb7, 0x09, 0x48, 0x9a, 0x9a, 0xf0, 0x77, 0xe9, 0xd2, 0xd8, 0xd0,
0x96, 0x79, 0x4f, 0x8d, 0x25, 0x91, 0x17, 0x68, 0xef, 0xe4, 0x25, 0xb1, 0x60, 0x79, 0xe6, 0xcc,
0x86, 0x24, 0x1e, 0xc9, 0x3b, 0xd2, 0xc6, 0xe9, 0x51, 0x72, 0x86, 0xd4, 0x3f, 0x1b, 0x71, 0x6b,
0xb5, 0x67, 0x6c, 0x35, 0x70, 0x7a, 0x44, 0x77, 0x01, 0x8e, 0x59, 0x34, 0x19, 0x51, 0x77, 0x7e,
0x74, 0x60, 0xad, 0x49, 0x6b, 0x1a, 0xa5, 0x50, 0xfe, 0xf5, 0x52, 0xf9, 0xff, 0x32, 0xe0, 0x96,
0x2a, 0xff, 0xff, 0xb0, 0xd9, 0x97, 0x4a, 0xd1, 0x9e, 0x43, 0x47, 0x05, 0xfb, 0xd6, 0xcf, 0x8b,
0x5e, 0x21, 0xf3, 0xd2, 0x0a, 0x35, 0x0a, 0x15, 0xb2, 0x7f, 0x37, 0xe0, 0x8e, 0x32, 0x7c, 0x52,
0xb9, 0x16, 0x3c, 0x80, 0xee, 0x84, 0xd1, 0xfe, 0x65, 0xcf, 0x64, 0x35, 0x53, 0x48, 0x85, 0xd1,
0x45, 0x85, 0x54, 0xe2, 0x70, 0x35, 0xf3, 0xad, 0x02, 0xd8, 0x82, 0x8d, 0xef, 0xa7, 0x94, 0xcd,
0x07, 0x7c, 0x94, 0x36, 0xd6, 0x31, 0x61, 0x64, 0x1c, 0x8b, 0x7d, 0x40, 0xcd, 0x86, 0x16, 0xae,
0x1f, 0x1d, 0xd8, 0x7f, 0x18, 0xfa, 0x3c, 0x49, 0xc1, 0x65, 0x18, 0xfa, 0x1c, 0x96, 0x4e, 0x38,
0xe1, 0xd3, 0x58, 0xed, 0xb3, 0xe9, 0x06, 0x92, 0x0a, 0x24, 0x4c, 0xac, 0x40, 0xe8, 0x31, 0xac,
0xcb, 0x3b, 0x92, 0x95, 0x2d, 0xb6, 0xcc, 0x9e, 0xb9, 0xb5, 0xb2, 0xb3, 0x91, 0xee, 0xa0, 0x45,
0x2e, 0x2e, 0xc3, 0x85, 0x86, 0xec, 0x24, 0x79, 0x62, 0xe2, 0xeb, 0x1a, 0x4a, 0x5c, 0x5c, 0x86,
0xdb, 0x3f, 0x2f, 0xf8, 0x20, 0x3a, 0xc4, 0x15, 0x24, 0x15, 0x58, 0x72, 0x40, 0x5f, 0x00, 0x9c,
0xe7, 0x7e, 0x26, 0xf1, 0x75, 0x94, 0x95, 0x13, 0xce, 0xfc, 0xf0, 0xec, 0x29, 0x99, 0x60, 0x0d,
0x63, 0x0f, 0x16, 0x9c, 0x13, 0x63, 0x22, 0x03, 0x28, 0xf5, 0x39, 0x21, 0x37, 0x5c, 0xd7, 0x0c,
0xdb, 0x9f, 0x42, 0x2b, 0xd3, 0x2f, 0xa6, 0x82, 0xe6, 0x85, 0xd1, 0x33, 0xc5, 0x54, 0xd0, 0x6c,
0x1e, 0xc0, 0x6a, 0x66, 0xf3, 0x89, 0x1f, 0x73, 0xb4, 0xbb, 0x20, 0x50, 0xbd, 0x28, 0x17, 0xb4,
0xbc, 0x80, 0xb5, 0x62, 0xc9, 0xd0, 0x7d, 0x68, 0x38, 0x74, 0x96, 0x0c, 0x8c, 0xb5, 0x2c, 0xbb,
0xe2, 0x6b, 0x42, 0x3e, 0x04, 0xaa, 0xb0, 0x12, 0x23, 0x7c, 0x3c, 0xf4, 0x43, 0x12, 0xf4, 0xb5,
0x58, 0x34, 0x8a, 0xfd, 0x25, 0x74, 0x65, 0xdb, 0xe5, 0x29, 0x57, 0x5d, 0x77, 0x65, 0x76, 0xec,
0x00, 0xba, 0xaa, 0x05, 0x8b, 0xd2, 0x6f, 0x15, 0xa2, 0x70, 0x92, 0x47, 0x9c, 0x04, 0xc7, 0xda,
0x2c, 0xd0, 0x28, 0xf6, 0x7b, 0xca, 0x49, 0x27, 0x23, 0x25, 0x4e, 0xda, 0x5f, 0xc3, 0x86, 0xee,
0x46, 0xce, 0x2f, 0xa9, 0x34, 0x16, 0x54, 0xde, 0x83, 0x0f, 0xa4, 0xc8, 0xe2, 0xed, 0x55, 0xaa,
0x8f, 0xe1, 0xae, 0xae, 0xfa, 0x3f, 0xd8, 0xba, 0x5f, 0x1b, 0x70, 0x4f, 0xea, 0x4a, 0xc6, 0x68,
0xf2, 0x25, 0xb0, 0x3f, 0x77, 0x66, 0xe2, 0x59, 0x52, 0x59, 0xef, 0xc1, 0x0a, 0x17, 0xf3, 0x5f,
0x0d, 0xe0, 0x24, 0xef, 0x3a, 0x49, 0xd4, 0xc5, 0xf3, 0x19, 0x95, 0x1f, 0xbf, 0x2a, 0x55, 0x39,
0x41, 0x0c, 0x77, 0x3e, 0xcb, 0x36, 0xb1, 0x16, 0x56, 0x27, 0x21, 0xc5, 0xd3, 0x87, 0x5b, 0xcd,
0xfd, 0x9c, 0x20, 0xa6, 0x92, 0x97, 0x0c, 0x70, 0x39, 0xf2, 0x4d, 0x9c, 0x1e, 0xed, 0xe7, 0x60,
0xe9, 0x59, 0xd0, 0x3d, 0x47, 0x0f, 0xc1, 0x64, 0x34, 0xad, 0xf1, 0x27, 0xaa, 0xc6, 0x97, 0xa1,
0xd3, 0x38, 0xb1, 0x90, 0xb1, 0x7f, 0x33, 0xa0, 0xf7, 0x26, 0xe4, 0x35, 0x72, 0x21, 0x11, 0x9c,
0x04, 0x85, 0xbd, 0x54, 0x27, 0x5d, 0x95, 0x8f, 0x3c, 0x8b, 0x8d, 0x72, 0x16, 0x0b, 0xd9, 0x6a,
0x96, 0xb2, 0x65, 0x47, 0x70, 0x4b, 0x3a, 0x8d, 0x69, 0x40, 0xe6, 0x94, 0xed, 0x93, 0x80, 0x88,
0xcd, 0xea, 0xcd, 0xee, 0x6a, 0xef, 0x60, 0xbd, 0xf8, 0x0e, 0x16, 0x0c, 0x9a, 0x65, 0x83, 0x2f,
0x60, 0x53, 0x4f, 0x56, 0xc9, 0xee, 0x23, 0xbd, 0x0c, 0x9f, 0x55, 0x94, 0xa1, 0x88, 0x3f, 0x8c,
0xd8, 0xb3, 0x90, 0xca, 0x25, 0x23, 0xa9, 0xc5, 0x2f, 0x06, 0x7c, 0x74, 0x2d, 0xb8, 0xf0, 0xff,
0x34, 0xa1, 0xa6, 0xef, 0xf8, 0x69, 0x75, 0xec, 0xf5, 0xca, 0xb6, 0xbd, 0x22, 0xc2, 0xc7, 0x59,
0x84, 0xd2, 0x92, 0x13, 0x15, 0xb6, 0x4c, 0x1b, 0xda, 0x5c, 0xdf, 0x44, 0x93, 0x49, 0x5b, 0xa0,
0xdd, 0x7f, 0x2e, 0xb7, 0x69, 0x7d, 0x00, 0xa2, 0x2e, 0xdc, 0x3c, 0xa6, 0xa1, 0xe7, 0x87, 0x67,
0x09, 0x41, 0xcc, 0xc3, 0x4e, 0x4d, 0x90, 0x4f, 0xa6, 0xae, 0x4b, 0xe3, 0x58, 0x23, 0x1b, 0xe8,
0x36, 0x74, 0x0e, 0x89, 0x1f, 0x50, 0x4f, 0xa3, 0xd6, 0x77, 0xda, 0x00, 0xf9, 0xff, 0x55, 0xa7,
0x4b, 0xf2, 0x7f, 0xa8, 0xdd, 0x7f, 0x03, 0x00, 0x00, 0xff, 0xff, 0x3a, 0xa6, 0xbf, 0xaf, 0xc4,
0x12, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
var _ context.Context
var _ grpc.ClientConnInterface
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
const _ = grpc.SupportPackageIsVersion6
// X2EthereumClient is the client API for X2Ethereum service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type X2EthereumClient interface {
}
type x2EthereumClient struct {
cc grpc.ClientConnInterface
}
func NewX2EthereumClient(cc grpc.ClientConnInterface) X2EthereumClient {
return &x2EthereumClient{cc}
}
// X2EthereumServer is the server API for X2Ethereum service.
type X2EthereumServer interface {
}
// UnimplementedX2EthereumServer can be embedded to have forward compatible implementations.
type UnimplementedX2EthereumServer struct {
}
func RegisterX2EthereumServer(s *grpc.Server, srv X2EthereumServer) {
s.RegisterService(&_X2Ethereum_serviceDesc, srv)
}
var _X2Ethereum_serviceDesc = grpc.ServiceDesc{
ServiceName: "types.x2ethereum",
HandlerType: (*X2EthereumServer)(nil),
Methods: []grpc.MethodDesc{},
Streams: []grpc.StreamDesc{},
Metadata: "x2ethereum.proto",
}
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