diff --git a/.gitignore b/.gitignore index 327b7042f..ea29cef88 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ docker/payload config.json peers.recent .vscode +poly \ No newline at end of file diff --git a/go.mod b/go.mod index 7b090dab4..927d176f0 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.14 require ( github.com/Zilliqa/gozilliqa-sdk v1.2.1-0.20210329093354-1b8e0a7a2e25 - github.com/btcsuite/btcd v0.20.1-beta + github.com/btcsuite/btcd v0.21.0-beta github.com/btcsuite/btcutil v1.0.2 github.com/cosmos/cosmos-sdk v0.39.1 github.com/ethereum/go-ethereum v1.9.15 @@ -15,18 +15,22 @@ require ( github.com/hashicorp/golang-lru v0.5.4 github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c github.com/itchyny/base58-go v0.1.0 - github.com/joeqian10/neo-gogogo v0.0.0-20200716075409-923bd4879b43 + github.com/joeqian10/neo-gogogo v1.1.0 + github.com/joeqian10/neo3-gogogo v0.3.3 + github.com/kardiachain/go-kaiclient v1.0.2-0.20210525090440-5f0648f4d185 // indirect + github.com/kardiachain/go-kardia v1.2.3-0.20210525082104-2913103edf92 // indirect github.com/ontio/ontology v1.11.1-0.20200812075204-26cf1fa5dd47 github.com/ontio/ontology-crypto v1.0.9 github.com/ontio/ontology-eventbus v0.9.1 github.com/pborman/uuid v1.2.0 github.com/polynetwork/poly-io-test v0.0.0-20200819093740-8cf514b07750 - github.com/stretchr/testify v1.6.1 - github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d + github.com/prometheus/tsdb v0.10.0 // indirect + github.com/stretchr/testify v1.7.0 + github.com/syndtr/goleveldb v1.0.1-0.20200815110645-5c35d600f0ca github.com/tendermint/tendermint v0.33.7 github.com/urfave/cli v1.22.4 github.com/valyala/bytebufferpool v1.0.0 - golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de - golang.org/x/net v0.0.0-20200822124328-c89045814202 + golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 + golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 gotest.tools v2.2.0+incompatible ) diff --git a/go.sum b/go.sum index 936b56289..f0ec9ada9 100644 --- a/go.sum +++ b/go.sum @@ -77,12 +77,17 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8= github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/antlr/antlr4 v0.0.0-20190819145818-b43a4c3a8015/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y= github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/apache/thrift v0.13.0/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/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015 h1:7ABPr1+uJdqESAdlVevnc/2FJGiC/K3uMg1JiELeF+0= +github.com/aristanetworks/goarista v0.0.0-20190712234253-ed1100a1c015/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= @@ -104,6 +109,8 @@ github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BR github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8= github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.21.0-beta h1:At9hIZdJW0s9E/fAz28nrz6AmcNlSVucCH796ZteX1M= +github.com/btcsuite/btcd v0.21.0-beta/go.mod h1:ZSWyehm27aAuS9bvkATT+Xte3hjHZ+MRgMY/8NJ7K94= 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= @@ -125,6 +132,7 @@ github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= 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/cp v1.1.1/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= @@ -169,11 +177,15 @@ github.com/dchest/siphash v1.2.1 h1:4cLinnzVJDKxTCl9B01807Yiy+W7ZzVHj/KIroQRvT4= github.com/dchest/siphash v1.2.1/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= 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/deckarep/golang-set v1.7.1 h1:SCQV0S6gTtp6itiFrTqI+pfmJ4LN85S1YzhDf9rTHJQ= +github.com/deckarep/golang-set v1.7.1/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= 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/docker/docker v17.12.0-ce-rc1.0.20200531234253-77e06fda0c94+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -182,6 +194,8 @@ github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJ github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/ebuchman/fail-test v0.0.0-20170303061230-95f809107225 h1:7TXT8REobzZUI9GzsRtAD29efTY/HgKRU2xYnV1zlaM= +github.com/ebuchman/fail-test v0.0.0-20170303061230-95f809107225/go.mod h1:OFTBW14UVJS8P0shpX7OdPY0qpkTdA7AWGYFacMC2D8= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= @@ -200,6 +214,8 @@ github.com/ethereum/go-ethereum v1.9.13 h1:rOPqjSngvs1VSYH2H+PMPiWt4VEulvNRbFgqi github.com/ethereum/go-ethereum v1.9.13/go.mod h1:qwN9d1GLyDh0N7Ab8bMGd0H9knaji2jOBm2RrMGjXls= github.com/ethereum/go-ethereum v1.9.15 h1:wrWl+QrtutRUJ9LZXdUqBoGoo2b1tOCYRDrAOQhCY3A= github.com/ethereum/go-ethereum v1.9.15/go.mod h1:slT8bPPRhXsyNTwHQxrOnjuTZ1sDXRajW11EkJ84QJ0= +github.com/ethereum/go-ethereum v1.9.18 h1:+vzvufVD7+OfQa07IJP20Z7AGZsJaw0M6JIA/WQcqy8= +github.com/ethereum/go-ethereum v1.9.18/go.mod h1:JSSTypSMTkGZtAdAChH2wP5dZEvPGh3nUTuDpH+hNrg= github.com/ethereum/go-ethereum v1.9.24 h1:6AK+ORt3EMDO+FTjzXy/AQwHMbu52J2nYHIjyQX9azQ= github.com/ethereum/go-ethereum v1.9.24/go.mod h1:JIfVb6esrqALTExdz9hRYvrP0xBDf6wCncIu1hNwHpM= github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 h1:0JZ+dUmQeA8IIVUMzysrX4/AKuQwWhV2dYQuPZdvdSQ= @@ -212,6 +228,7 @@ github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= +github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/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/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -262,6 +279,8 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -285,6 +304,8 @@ github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0 github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 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= @@ -293,11 +314,15 @@ github.com/golang/snappy v0.0.2-0.20200707131729-196ae77b8a26/go.mod h1:/XxbfmMg github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/cel-go v0.3.2/go.mod h1:DoRSdzaJzNiP1lVuWhp/RjSnHLDQr/aNPlyqSBasBqA= +github.com/google/cel-spec v0.3.0/go.mod h1:MjQm800JAGhOZXI7vatnVpmIaFTR6L8FHcKk+piiKpI= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 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/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -396,26 +421,41 @@ github.com/joeqian10/neo-gogogo v0.0.0-20200611102831-c17de5e1f0f8 h1:C+PIS6p7oQ github.com/joeqian10/neo-gogogo v0.0.0-20200611102831-c17de5e1f0f8/go.mod h1:1fVDp4U1ROZQBRIooecbGNHHJpfs3bG9528sqlZ096g= github.com/joeqian10/neo-gogogo v0.0.0-20200716075409-923bd4879b43 h1:KkErIktuwCqqZYWV8iBbD7NEsgIbyGw6xxtuylqdyu0= github.com/joeqian10/neo-gogogo v0.0.0-20200716075409-923bd4879b43/go.mod h1:1fVDp4U1ROZQBRIooecbGNHHJpfs3bG9528sqlZ096g= +github.com/joeqian10/neo-gogogo v1.1.0 h1:TjqBwFQnNCtw6LK3QMog3yHa9sTZaZmqP+zqGOZ3SZ0= +github.com/joeqian10/neo-gogogo v1.1.0/go.mod h1:1fVDp4U1ROZQBRIooecbGNHHJpfs3bG9528sqlZ096g= +github.com/joeqian10/neo3-gogogo v0.3.3 h1:QKf18gGLql19bbBrPLzl+DKyoYuYIhGHNUXNBvEMfc8= +github.com/joeqian10/neo3-gogogo v0.3.3/go.mod h1:yvYQyEha3An0uYFhzR9asMU/O9HyeYy6RApRnLGPEtM= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= 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/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= 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/kardiachain/go-kardia v1.1.1-0.20210514114009-042c640f55d4 h1:vYkCSECIwErZ8YhymhOYySiieROmbKk+3/rIsU1MUgE= +github.com/kardiachain/go-kardia v1.1.1-0.20210514114009-042c640f55d4/go.mod h1:XV2KPJf+Ib3es9iAFH5Io5fISzHpu7pk06um9bgAVKU= +github.com/kardiachain/go-kardia v1.1.1-0.20210518073513-843096e91762 h1:Jkua+KxKgB3unn8wcCfkylIn8PVcrzVGThxHcrijkbA= +github.com/kardiachain/go-kardia v1.1.1-0.20210518073513-843096e91762/go.mod h1:dIcZ5VO21q0HAjL9LiHqJ8bKMDkoE3T/4H0vy8urggs= +github.com/kardiachain/go-kardia v1.1.1-0.20210524050836-7b1961837a7a h1:KlxsfWdrLUeQ7WbwOpLKkjoqsgYkhcqhSUeQNTyJKNo= +github.com/kardiachain/go-kardia v1.1.1-0.20210524050836-7b1961837a7a/go.mod h1:dIcZ5VO21q0HAjL9LiHqJ8bKMDkoE3T/4H0vy8urggs= github.com/keybase/go-keychain v0.0.0-20190712205309-48d3d31d256d/go.mod h1:JJNrCn9otv/2QP4D7SMJBgaleKpOf66PnW6F5WGNRIc= 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/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -434,11 +474,13 @@ github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzR github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= 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.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= 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/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= @@ -452,6 +494,8 @@ github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3N github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0= github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= github.com/minio/highwayhash v1.0.0/go.mod h1:xQboMTeM9nY9v/LlAOxFctujiv5+Aq2hR5dxBpaMbdc= +github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= +github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -476,6 +520,7 @@ github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzE github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= @@ -494,6 +539,7 @@ github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5 github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/ontio/go-bip32 v0.0.0-20190520025953-d3cea6894a2b/go.mod h1:J0eVc7BEMmVVXbGv9PHoxjRSEwOwLr0qfzPk8Rdl5iw= github.com/ontio/ontology v1.10.0/go.mod h1:iok/imHJVQXi5/Yr88dcbrKBRHGdiota1ZC6qh6l6Rc= @@ -523,12 +569,15 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI 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/pebbe/zmq4 v1.0.0/go.mod h1:7N4y5R18zBiu3l0vajMUWQgZyjv464prE8RCyBcmnZM= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM= github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -556,6 +605,8 @@ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeD github.com/prometheus/client_golang v1.5.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.8.0/go.mod h1:O9VU6huf47PktckDQfMTX0Y8tY0/7TSWwj+ITvv0TnM= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -570,30 +621,41 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.14.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.6.2-0.20190402121629-4f204dcbc150/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic= +github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4= github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/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/rjeczalik/notify v0.9.2 h1:MiTWrPj55mNDHEiIX5YUSKefw/+lCQVoAFmD6oQm5w8= +github.com/rjeczalik/notify v0.9.2/go.mod h1:aErll2f0sUX9PXZnVNyeiObbmTlk5jnMoCa4QEjJeqM= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v0.0.0-20160617231935-a62a804a8a00/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.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/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y= +github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/scylladb/go-set v1.0.2/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= @@ -605,6 +667,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= @@ -636,6 +699,8 @@ github.com/spf13/viper v1.6.3 h1:pDDu1OyEDTKzpJwdq4TiuLyMsUgRa/BT5cn5O62NoHs= github.com/spf13/viper v1.6.3/go.mod h1:jUMtyi0/lB5yZH/FjyGAoH7IMNrIhlBf6pXZmbMDvzw= 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/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48 h1:ju5UTwk5Odtm4trrY+4Ca4RMj5OyXbmVeDAVad2T0Jw= +github.com/status-im/keycard-go v0.0.0-20190424133014-d95853db0f48/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= @@ -654,6 +719,8 @@ github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= @@ -711,6 +778,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/ybbus/jsonrpc v2.1.2+incompatible h1:V4mkE9qhbDQ92/MLMIhlhMSbz8jNXdagC3xBR5NDwaQ= github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM= github.com/zquestz/grab v0.0.0-20190224022517-abcee96e61b1 h1:1qKTeMTSIEvRIjvVYzgcRp0xVp0eoiRTTiHSncb5gD8= github.com/zquestz/grab v0.0.0-20190224022517-abcee96e61b1/go.mod h1:bslhAiUxakrA6z6CHmVyvkfpnxx18RJBwVyx2TluJWw= @@ -745,10 +814,15 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200406173513-056763e48d71/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o= +golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -764,6 +838,8 @@ golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKG golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -791,11 +867,16 @@ golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/ golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -804,16 +885,19 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/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-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -824,8 +908,10 @@ golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -834,10 +920,21 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3rzIsrrXfAQBWnYfn+w= golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ= golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8 h1:AvbQYmiaaaza3cW3QXRyPo5kYgpFIzOAfeAAN7m3qQ4= golang.org/x/sys v0.0.0-20200824131525-c12d262b63d8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211 h1:9UQO31fZ+0aKQOFldThf7BKPMJTiBfWycGh/u3UoO88= +golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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= @@ -864,6 +961,8 @@ golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= @@ -883,6 +982,9 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYUO2VM9mDLqo2V6CFBY84lFSZAfoi4= google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6 h1:iRN4+t0lvZX/l9gH14ARF9i58tsVa5a97k6aH95rC3Y= +google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= @@ -911,11 +1013,15 @@ google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2M google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= 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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= diff --git a/merkle/merkletree.db b/merkle/merkletree.db new file mode 100755 index 000000000..9c87f62aa Binary files /dev/null and b/merkle/merkletree.db differ diff --git a/native/service/cross_chain_manager/entrance.go b/native/service/cross_chain_manager/entrance.go index 329118c8b..ada6181cd 100644 --- a/native/service/cross_chain_manager/entrance.go +++ b/native/service/cross_chain_manager/entrance.go @@ -28,8 +28,10 @@ import ( "github.com/polynetwork/poly/native/service/cross_chain_manager/cosmos" "github.com/polynetwork/poly/native/service/cross_chain_manager/eth" "github.com/polynetwork/poly/native/service/cross_chain_manager/heco" + "github.com/polynetwork/poly/native/service/cross_chain_manager/kai" "github.com/polynetwork/poly/native/service/cross_chain_manager/msc" "github.com/polynetwork/poly/native/service/cross_chain_manager/neo" + "github.com/polynetwork/poly/native/service/cross_chain_manager/neo3" "github.com/polynetwork/poly/native/service/cross_chain_manager/okex" "github.com/polynetwork/poly/native/service/cross_chain_manager/ont" "github.com/polynetwork/poly/native/service/cross_chain_manager/quorum" @@ -66,6 +68,8 @@ func GetChainHandler(router uint64) (scom.ChainHandler, error) { return ont.NewONTHandler(), nil case utils.NEO_ROUTER: return neo.NewNEOHandler(), nil + case utils.NEO3_ROUTER: + return neo3.NewNeo3Handler(), nil case utils.COSMOS_ROUTER: return cosmos.NewCosmosHandler(), nil case utils.QUORUM_ROUTER: @@ -80,6 +84,8 @@ func GetChainHandler(router uint64) (scom.ChainHandler, error) { return msc.NewHandler(), nil case utils.OKEX_ROUTER: return okex.NewHandler(), nil + case utils.KAI_ROUTER: + return kai.NewHandler(), nil default: return nil, fmt.Errorf("not a supported router:%d", router) } diff --git a/native/service/cross_chain_manager/kai/handler.go b/native/service/cross_chain_manager/kai/handler.go new file mode 100644 index 000000000..2a47d5e3d --- /dev/null +++ b/native/service/cross_chain_manager/kai/handler.go @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package kai + +import ( + "bytes" + "encoding/hex" + "encoding/json" + "fmt" + "math/big" + + ecommon "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/light" + "github.com/ethereum/go-ethereum/rlp" + "github.com/ethereum/go-ethereum/trie" + kaiclient "github.com/kardiachain/go-kaiclient/kardia" + "github.com/kardiachain/go-kardia/types" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/common/log" + "github.com/polynetwork/poly/native" + scom "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + "github.com/polynetwork/poly/native/service/governance/side_chain_manager" + hskai "github.com/polynetwork/poly/native/service/header_sync/kai" +) + +// Handler ... +type Handler struct { +} + +// NewHandler ... +func NewHandler() *Handler { + return &Handler{} +} + +// MakeDepositProposal ... +func (h *Handler) MakeDepositProposal(service *native.NativeService) (*scom.MakeTxParam, error) { + params := new(scom.EntranceParam) + if err := params.Deserialization(common.NewZeroCopySource(service.GetInput())); err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, contract params deserialize error: %s", err) + } + info, err := hskai.GetEpochSwitchInfo(service, params.SourceChainID) + if err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, failed to get epoch switching height: %v", err) + } + if info.Height > int64(params.Height) { + return nil, fmt.Errorf("KAI MakeDepositProposal, the height %d of header is lower than epoch "+ + "switching height %d", params.Height, info.Height) + } + + if len(params.HeaderOrCrossChainMsg) == 0 { + return nil, fmt.Errorf("you must commit the header used to verify transaction's proof and get none") + } + + var myHeader kaiclient.FullHeader + if err := json.Unmarshal(params.HeaderOrCrossChainMsg, &myHeader); err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, unmarshal cosmos header failed: %v", err) + } + if myHeader.Header.Height != uint64(params.Height) { + return nil, fmt.Errorf("KAI MakeDepositProposal, "+ + "height of your header is %d not equal to %d in parameter", myHeader.Header.Height, params.Height) + } + + if err = hskai.VerifyHeader(&myHeader, info); err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, failed to verify KAI header: %v", err) + } + + sideChain, err := side_chain_manager.GetSideChain(service, params.SourceChainID) + if err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, side_chain_manager.GetSideChain error: %v", err) + } + + if !myHeader.Header.ValidatorsHash.Equal(myHeader.Header.NextValidatorsHash) && + int64(myHeader.Header.Height) > info.Height { + hskai.PutEpochSwitchInfo(service, params.SourceChainID, &hskai.EpochSwitchInfo{ + Height: int64(myHeader.Header.Height), + BlockHash: myHeader.Header.Hash().Bytes(), + NextValidatorsHash: myHeader.Header.NextValidatorsHash.Bytes(), + ChainID: info.ChainID, + }) + } + + value, err := verifyTx(myHeader.Header, service, params.Proof, params.Extra, params.SourceChainID, params.Height, sideChain) + if err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, verifyFromEthTx error: %s", err) + } + + if err := scom.CheckDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, check done transaction error:%s", err) + } + if err := scom.PutDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { + return nil, fmt.Errorf("KAI MakeDepositProposal, PutDoneTx error:%s", err) + } + + return nil, nil +} + +func verifyTx(header *types.Header, native *native.NativeService, proof, extra []byte, fromChainID uint64, height uint32, sideChain *side_chain_manager.SideChain) (param *scom.MakeTxParam, err error) { + kaiProof := new(Proof) + err = json.Unmarshal(proof, kaiProof) + if err != nil { + return nil, fmt.Errorf("verifyTx, unmarshal proof error:%s", err) + } + + if len(kaiProof.StorageProofs) != 1 { + return nil, fmt.Errorf("verifyTx, incorrect proof format") + } + + proofResult, err := verifyMerkleProof(kaiProof, header, sideChain.CCMCAddress) + if err != nil { + return nil, fmt.Errorf("verifyTx, verifyMerkleProof error:%v", err) + } + + if proofResult == nil { + return nil, fmt.Errorf("verifyTx, verifyMerkleProof failed") + } + + if !checkProofResult(proofResult, extra) { + return nil, fmt.Errorf("verifyTx, verify proof value hash failed, proof result:%x, extra:%x", proofResult, extra) + } + + data := common.NewZeroCopySource(extra) + txParam := new(scom.MakeTxParam) + if err := txParam.Deserialization(data); err != nil { + return nil, fmt.Errorf("verifyTx, deserialize merkleValue error:%s", err) + } + return txParam, nil +} + +// Proof ... +type Proof struct { + Address string `json:"address"` + Balance string `json:"balance"` + CodeHash string `json:"codeHash"` + Nonce string `json:"nonce"` + StorageHash string `json:"storageHash"` + AccountProof []string `json:"accountProof"` + StorageProofs []StorageProof `json:"storageProof"` +} + +// StorageProof ... +type StorageProof struct { + Key string `json:"key"` + Value string `json:"value"` + Proof []string `json:"proof"` +} + +// ProofAccount ... +type ProofAccount struct { + Nounce *big.Int + Balance *big.Int + Storage ecommon.Hash + Codehash ecommon.Hash +} + +func verifyMerkleProof(kaiProof *Proof, blockData *types.Header, contractAddr []byte) ([]byte, error) { + //1. prepare verify account + nodeList := new(light.NodeList) + + for _, s := range kaiProof.AccountProof { + p := scom.Replace0x(s) + nodeList.Put(nil, ecommon.Hex2Bytes(p)) + } + ns := nodeList.NodeSet() + + addr := ecommon.Hex2Bytes(scom.Replace0x(kaiProof.Address)) + if !bytes.Equal(addr, contractAddr) { + return nil, fmt.Errorf("verifyMerkleProof, contract address is error, proof address: %s, side chain address: %s", kaiProof.Address, hex.EncodeToString(contractAddr)) + } + acctKey := crypto.Keccak256(addr) + + //2. verify account proof + acctVal, err := trie.VerifyProof(ecommon.Hash(blockData.AppHash), acctKey, ns) + if err != nil { + return nil, fmt.Errorf("verifyMerkleProof, verify account proof error:%s", err) + } + + nounce := new(big.Int) + _, ok := nounce.SetString(scom.Replace0x(kaiProof.Nonce), 16) + if !ok { + return nil, fmt.Errorf("verifyMerkleProof, invalid format of nounce:%s", kaiProof.Nonce) + } + + balance := new(big.Int) + _, ok = balance.SetString(scom.Replace0x(kaiProof.Balance), 16) + if !ok { + return nil, fmt.Errorf("verifyMerkleProof, invalid format of balance:%s", kaiProof.Balance) + } + + storageHash := ecommon.HexToHash(scom.Replace0x(kaiProof.StorageHash)) + codeHash := ecommon.HexToHash(scom.Replace0x(kaiProof.CodeHash)) + + acct := &ProofAccount{ + Nounce: nounce, + Balance: balance, + Storage: storageHash, + Codehash: codeHash, + } + + acctrlp, err := rlp.EncodeToBytes(acct) + if err != nil { + return nil, err + } + + if !bytes.Equal(acctrlp, acctVal) { + return nil, fmt.Errorf("verifyMerkleProof, verify account proof failed, wanted:%v, get:%v", acctrlp, acctVal) + } + + //3.verify storage proof + nodeList = new(light.NodeList) + if len(kaiProof.StorageProofs) != 1 { + return nil, fmt.Errorf("verifyMerkleProof, invalid storage proof format") + } + + sp := kaiProof.StorageProofs[0] + storageKey := crypto.Keccak256(ecommon.HexToHash(scom.Replace0x(sp.Key)).Bytes()) + + for _, prf := range sp.Proof { + nodeList.Put(nil, ecommon.Hex2Bytes(scom.Replace0x(prf))) + } + + ns = nodeList.NodeSet() + val, err := trie.VerifyProof(storageHash, storageKey, ns) + if err != nil { + return nil, fmt.Errorf("verifyMerkleProof, verify storage proof error:%s", err) + } + + return val, nil +} + +func checkProofResult(result, value []byte) bool { + var tempBytes []byte + err := rlp.DecodeBytes(result, &tempBytes) + if err != nil { + log.Errorf("checkProofResult, rlp.DecodeBytes error:%s\n", err) + return false + } + // + var s []byte + for i := len(tempBytes); i < 32; i++ { + s = append(s, 0) + } + s = append(s, tempBytes...) + hash := crypto.Keccak256(value) + return bytes.Equal(s, hash) +} diff --git a/native/service/cross_chain_manager/kai/handler_test.go b/native/service/cross_chain_manager/kai/handler_test.go new file mode 100644 index 000000000..adeebcad8 --- /dev/null +++ b/native/service/cross_chain_manager/kai/handler_test.go @@ -0,0 +1,46 @@ +package kai + +import ( + "encoding/hex" + "fmt" + "testing" + + "github.com/polynetwork/poly/common" + cstates "github.com/polynetwork/poly/core/states" + "github.com/polynetwork/poly/core/store/leveldbstore" + "github.com/polynetwork/poly/core/store/overlaydb" + "github.com/polynetwork/poly/core/types" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/service/governance/side_chain_manager" + "github.com/polynetwork/poly/native/service/utils" + "github.com/polynetwork/poly/native/storage" +) + +func NewNative(args []byte, tx *types.Transaction, db *storage.CacheDB) *native.NativeService { + if db == nil { + store, _ := leveldbstore.NewMemLevelDBStore() + db = storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + } + ns, err := native.NewNativeService(db, tx, 0, 0, common.Uint256{0}, 0, args, false) + if err != nil { + panic(fmt.Errorf("NewNativeService error: %+v", err)) + } + + contaractAddr, _ := hex.DecodeString("48A77F43C0D7A6D6f588c4758dbA22bf6C5D95a0") + side := &side_chain_manager.SideChain{ + Name: "kai", + ChainId: 138, + BlocksToWait: 1, + Router: 1, + CCMCAddress: contaractAddr, + } + sink := common.NewZeroCopySink(nil) + _ = side.Serialization(sink) + ns.GetCacheDB().Put(utils.ConcatKey(utils.SideChainManagerContractAddress, []byte(side_chain_manager.SIDE_CHAIN), utils.GetUint64Bytes(2)), cstates.GenRawStorageItem(sink.Bytes())) + return ns +} + +func TestMakeDepositProposal(t *testing.T) { + //handler := NewHandler() + +} diff --git a/native/service/cross_chain_manager/neo/neo_handler.go b/native/service/cross_chain_manager/neo/neo_handler.go index 3f6af92a3..56b3b9fa6 100644 --- a/native/service/cross_chain_manager/neo/neo_handler.go +++ b/native/service/cross_chain_manager/neo/neo_handler.go @@ -57,10 +57,10 @@ func (this *NEOHandler) MakeDepositProposal(service *native.NativeService) (*sco } // Ensure the tx has not been processed before, and mark the tx as processed if err := scom.CheckDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { - return nil, fmt.Errorf("neo MakeDepositProposal, check done transaction error:%s", err) + return nil, fmt.Errorf("neo MakeDepositProposal, check done transaction error: %s", err) } if err = scom.PutDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { - return nil, fmt.Errorf("neo MakeDepositProposal, putDoneTx error:%s", err) + return nil, fmt.Errorf("neo MakeDepositProposal, putDoneTx error: %s", err) } return value, nil } diff --git a/native/service/cross_chain_manager/neo/neo_handler_test.go b/native/service/cross_chain_manager/neo/neo_handler_test.go index e2e9c1bfe..e04607d24 100644 --- a/native/service/cross_chain_manager/neo/neo_handler_test.go +++ b/native/service/cross_chain_manager/neo/neo_handler_test.go @@ -110,11 +110,9 @@ func Test_Neo_MakeDepositProposal(t *testing.T) { param.ChainID = 4 var err error sink := common.NewZeroCopySink(nil) - genesisHeader.Serialization(sink) + err = genesisHeader.Serialization(sink) param.GenesisHeader = sink.Bytes() - if err != nil { - t.Errorf("NeoBlockHeaderToBytes error:%v", err) - } + assert.Nil(t, err) sink = common.NewZeroCopySink(nil) param.Serialization(sink) @@ -158,5 +156,4 @@ func Test_Neo_MakeDepositProposal(t *testing.T) { _, err = neoHandler.MakeDepositProposal(native) assert.Nil(t, err) } - } diff --git a/native/service/cross_chain_manager/neo/utils.go b/native/service/cross_chain_manager/neo/utils.go index 3f905f8d7..3988fc5a3 100644 --- a/native/service/cross_chain_manager/neo/utils.go +++ b/native/service/cross_chain_manager/neo/utils.go @@ -30,16 +30,16 @@ import ( func verifyFromNeoTx(proof []byte, crosschainMsg *neo.NeoCrossChainMsg, contractAddr []byte) (*scom.MakeTxParam, error) { crossStateProofRoot, err := helper.UInt256FromString(crosschainMsg.StateRoot.StateRoot) if err != nil { - return nil, fmt.Errorf("verifyFromNeoTx, decode cross state proof root from string error:%s", err) + return nil, fmt.Errorf("verifyFromNeoTx, decode cross state proof root from string error: %s", err) } value, err := VerifyNeoCrossChainProof(proof, crossStateProofRoot.Bytes(), contractAddr) if err != nil { - return nil, fmt.Errorf("VerifyFromNeoTx, Verify Neo cross chain proof error:%v", err) + return nil, fmt.Errorf("VerifyFromNeoTx, Verify Neo cross chain proof error: %v", err) } source := common.NewZeroCopySource(value) txParam := new(scom.MakeTxParam) if err := txParam.Deserialization(source); err != nil { - return nil, fmt.Errorf("VerifyFromNeoTx, deserialize merkleValue error:%s", err) + return nil, fmt.Errorf("VerifyFromNeoTx, deserialize merkleValue error: %s", err) } return txParam, nil } @@ -47,14 +47,14 @@ func verifyFromNeoTx(proof []byte, crosschainMsg *neo.NeoCrossChainMsg, contract func VerifyNeoCrossChainProof(proof []byte, stateRoot []byte, contractAddr []byte) ([]byte, error) { scriptHash, key, proofs, err := mpt.ResolveProof(proof) if err != nil { - return nil, fmt.Errorf("VerifyNeoCrossChainProof, joeqian10/neo-gogogo/mpt.ResolveProof error:%v", err) + return nil, fmt.Errorf("VerifyNeoCrossChainProof, neo-gogogo mpt.ResolveProof error: %v", err) } if !bytes.Equal(scriptHash.Bytes(), contractAddr) { - return nil, fmt.Errorf("VerifyNeoCrossChainProof, error:scriptHash is not CCMC contract address, expected:%s, but got %s", hex.EncodeToString(common.ToArrayReverse(contractAddr)), scriptHash.String()) + return nil, fmt.Errorf("VerifyNeoCrossChainProof, error:scriptHash is not CCMC contract address, expected: %s, but got: %s", hex.EncodeToString(common.ToArrayReverse(contractAddr)), scriptHash.String()) } value, err := mpt.VerifyProof(stateRoot, scriptHash, key, proofs) if err != nil { - return nil, fmt.Errorf("VerifyNeoCrossChainProof, joeqian10/neo-gogogo/mpt.VerifyProof error:%v", err) + return nil, fmt.Errorf("VerifyNeoCrossChainProof, neo-gogogo mpt.VerifyProof error: %v", err) } return value, nil diff --git a/native/service/cross_chain_manager/neo3/neo_handler.go b/native/service/cross_chain_manager/neo3/neo_handler.go new file mode 100644 index 000000000..cb2e071aa --- /dev/null +++ b/native/service/cross_chain_manager/neo3/neo_handler.go @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package neo3 + +import ( + "fmt" + "github.com/joeqian10/neo3-gogogo/helper" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/native" + scom "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + "github.com/polynetwork/poly/native/service/governance/side_chain_manager" + "github.com/polynetwork/poly/native/service/header_sync/neo3" +) + +type Neo3Handler struct { +} + +func NewNeo3Handler() *Neo3Handler { + return &Neo3Handler{} +} + +func (this *Neo3Handler) MakeDepositProposal(service *native.NativeService) (*scom.MakeTxParam, error) { + params := new(scom.EntranceParam) + if err := params.Deserialization(common.NewZeroCopySource(service.GetInput())); err != nil { + return nil, fmt.Errorf("neo3 MakeDepositProposal, contract params deserialize error: %v", err) + } + // Deserialize neo cross chain msg and verify its signature + crossChainMsg := new(neo3.NeoCrossChainMsg) + if err := crossChainMsg.Deserialization(common.NewZeroCopySource(params.HeaderOrCrossChainMsg)); err != nil { + return nil, fmt.Errorf("neo3 MakeDepositProposal, deserialize crossChainMsg error: %v", err) + } + // Verify the validity of proof with the help of state root in verified neo cross chain msg + sideChain, err := side_chain_manager.GetSideChain(service, params.SourceChainID) + if err != nil { + return nil, fmt.Errorf("neo3 MakeDepositProposal, side_chain_manager.GetSideChain error: %v", err) + } + if err := neo3.VerifyCrossChainMsgSig(service, helper.BytesToUInt32(sideChain.ExtraInfo), crossChainMsg); err != nil { + return nil, fmt.Errorf("neo3 MakeDepositProposal, VerifyCrossChainMsg error: %v", err) + } + + // when register neo N3, convert ccmc id to []byte + // convert neo3 contract address bytes to id, it is different from other chains + // need to store int in a []byte, contract id can be get from "getcontractstate" api + // neo3 native contracts have negative ids, while custom contracts have positive ones + id := int(int32(helper.BytesToUInt32(sideChain.CCMCAddress))) + + value, err := verifyFromNeoTx(params.Proof, crossChainMsg, id) + if err != nil { + return nil, fmt.Errorf("neo3 MakeDepositProposal, VerifyFromNeoTx error: %v", err) + } + // Ensure the tx has not been processed before, and mark the tx as processed + if err := scom.CheckDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { + return nil, fmt.Errorf("neo3 MakeDepositProposal, check done transaction error:%s", err) + } + if err = scom.PutDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { + return nil, fmt.Errorf("neo3 MakeDepositProposal, putDoneTx error:%s", err) + } + return value, nil +} diff --git a/native/service/cross_chain_manager/neo3/neo_handler_test.go b/native/service/cross_chain_manager/neo3/neo_handler_test.go new file mode 100644 index 000000000..9923791b1 --- /dev/null +++ b/native/service/cross_chain_manager/neo3/neo_handler_test.go @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package neo3 + +import ( + "encoding/hex" + "github.com/joeqian10/neo3-gogogo/crypto" + "github.com/joeqian10/neo3-gogogo/helper" + tx2 "github.com/joeqian10/neo3-gogogo/tx" + "github.com/ontio/ontology-crypto/keypair" + "github.com/polynetwork/poly/account" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/core/genesis" + cstates "github.com/polynetwork/poly/core/states" + "github.com/polynetwork/poly/core/store/leveldbstore" + "github.com/polynetwork/poly/core/store/overlaydb" + "github.com/polynetwork/poly/core/types" + "github.com/polynetwork/poly/native" + scom "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + "github.com/polynetwork/poly/native/service/governance/side_chain_manager" + hscom "github.com/polynetwork/poly/native/service/header_sync/common" + "github.com/polynetwork/poly/native/service/header_sync/neo3" + "github.com/polynetwork/poly/native/service/utils" + "github.com/polynetwork/poly/native/storage" + "github.com/stretchr/testify/assert" + "log" + "testing" +) + +var ( + acct *account.Account = account.NewAccount("") + getNativeFunc = func() *native.NativeService { + store, _ := leveldbstore.NewMemLevelDBStore() + cacheDB := storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + service, _ := native.NewNativeService(cacheDB, new(types.Transaction), 0, 200, common.Uint256{}, 0, nil, false) + return service + } + getNeoHanderFunc = func() *Neo3Handler { + return NewNeo3Handler() + } + setBKers = func() { + genesis.GenesisBookkeepers = []keypair.PublicKey{acct.PublicKey} + } +) + +func init() { + setBKers() +} +func NewNative(args []byte, tx *types.Transaction, db *storage.CacheDB) *native.NativeService { + if db == nil { + store, _ := leveldbstore.NewMemLevelDBStore() + db = storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + } + ns, _ := native.NewNativeService(db, tx, 0, 0, common.Uint256{0}, 0, args, false) + return ns +} +func SetContract(ns *native.NativeService, contractAddr string) { + contaractAddr, _ := hex.DecodeString(contractAddr) + side := &side_chain_manager.SideChain{ + Name: "neo", + ChainId: 4, + BlocksToWait: 1, + Router: 4, + CCMCAddress: contaractAddr, + } + sink := common.NewZeroCopySink(nil) + _ = side.Serialization(sink) + ns.GetCacheDB().Put(utils.ConcatKey(utils.SideChainManagerContractAddress, []byte(side_chain_manager.SIDE_CHAIN), utils.GetUint64Bytes(side.ChainId)), cstates.GenRawStorageItem(sink.Bytes())) +} + +func Test_Neo_MakeDepositProposal(t *testing.T) { + var native *native.NativeService + { + prevHash, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + merkleRoot, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + nextConsensus, _ := crypto.AddressToScriptHash("NVg7LjGcUSrgxgjX3zEgqaksfMaiS8Z6e1", helper.DefaultAddressVersion) + vs, _ := crypto.Base64Decode("EQ==") + witness := tx2.Witness{ + InvocationScript: []byte{}, + VerificationScript: vs, + } + genesisHeader := &neo3.NeoBlockHeader{} + genesisHeader.SetVersion(0) + genesisHeader.SetPrevHash(prevHash) + genesisHeader.SetMerkleRoot(merkleRoot) + genesisHeader.SetTimeStamp(1468595301000) + genesisHeader.SetIndex(0) + genesisHeader.SetPrimaryIndex(0x00) + genesisHeader.SetNextConsensus(nextConsensus) + genesisHeader.SetWitnesses([]tx2.Witness{witness}) + + param := new(hscom.SyncGenesisHeaderParam) + param.ChainID = 4 + var err error + sink := common.NewZeroCopySink(nil) + err = genesisHeader.Serialization(sink) + param.GenesisHeader = sink.Bytes() + if err != nil { + t.Errorf("NeoBlockHeaderToBytes error:%v", err) + } + + sink = common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + + native = NewNative(sink.Bytes(), tx, nil) + neoHandler := neo3.NewNeo3Handler() + err = neoHandler.SyncGenesisHeader(native) + assert.NoError(t, err) + } + + { + neoCrossChainMsgBs, _ := hex.DecodeString("004b0a01000f2adbe1d4c5022f34f7c4d1e5f033ea68102e716d66d70cdd194ae6dd7ed1b415f4c0ae08b37c51bd71a78b6aa5e79408f920a3b7b93e38d781985444b93b2b01c34059d48e180101adff905300e5e2074bfd12dee1d72e6a767cc00b384633fe64bfa2119811685c5062fc2ac947da15c08953dd603be791c41666f4ae759cb9ca8440b7201eb7d39052b22826a5445f4d7da896d337ffbec6dad0c08e413d5f1ec3f79caba079d77da11bc6ed800bccb9f689f34b4e85d7b4bb0dee14cbda75c5fedc40b7a409837de5e709f7e0b3e9f730f2475f6ddd8ba61d95849f16c97a78e9980879a740d8ab98bc012619b57170496fb7c6c515ae1d58eed50e9854667028acaf8b5321030f59a5482a4e42a2e5a848608dac4e84a698e567e2860e0ca5f23fc9e818d37c21032e78261370d4d62cf4c13584ca90f46c5565117b5b97544312f2e7b7c36b9eba21026e271722c21c482f0ac74dd932e61cdc2a2dd889633a2c5d8ecef43f2769f51e2103d55bfbcd493d06ab49c09cde0cea5d9ba890d81331a2fcd6f68d329932d0398f54ae") + proofBs, _ := hex.DecodeString("25b0d4f20da68a6007d4fb7eac374b5566a5b0e229010202040000000000000000000000000c0bfd12010020f1bd34e03cf87844472bd97a245f6b4647f3da831101e8d35887b128447610cd0000205bb1e7f44a1a49702f37ec5b3c3ef254d9a55e84e30e91292e40b1a77b587c3520136df7bf0b604a15046281d14ff737f289fee06dcc21d2f5ebc3c879fe0b8f8100207f4fa0a7ca13b5712eae6df66b34c837134b1b3c206e35c8b08f58fd60eb95d9207dc275d32b07c66e4a7a85ca95812fe2bea2bc54205304db207789be9cdd9b440020ce58021310ac771901181d08fe4ea849214f5f8e8838325f88193589d06b5a6300209fc6b8cf16051f2cb0f16797064f3766ab90a0c7afe00a5ed205165a8ceb44da000020b235652da7f7892fd833b3f09656f3e74de8783896f85aa25a6315542d214d3700004a0127000d040f02000d0a06080a060000070d040f0b070e0a0c0307040b050506060a050b000e020209206fbaa1762862f38fcd56430a143632403b149491372122aed7a76252965008f85200206768e94d8cf974b35d8b20f36d4fd96a2a9ebdcb256c6cbccd67c741d8f3680500000020b532982b4fa5b52549439b9d6ab21dcdf1bdd08148573ce2cd8dbcfdc0647cd800000000000000000000000023010020584d7456e1a12be332ebe31e69970dfa18fa2bb7657c392fc63a44e01ed7f0dd92000020811d835143c81eb6d89295d33376ad7f2051fe9c12e97609373ab40983e3509d2075766bf9049fd5e20d14ffed1647f318518c125203de2dfc6473a03952cfc3e22068ea98f2f5f7d6e2c602885e57888adadd3e08e6c05043de7f1075fbfeb07f8f20c744e54af45aff995db84a5de396d73b916beed7cb54dcfadbde06e3845ada250000000000000000000000002401010020eff43eb246bba849c55908a9eca858194e43e89191555331dc2b6924621224875200002064022d7bf83e18daa3f0c521d74a430d4e9fca91edf56c484f249590378570bc20749a992c424e0da9d810b9954787b060190d631a83712f50134ac45bae43891f0000000000000000000000000000260103000200200d0c0166a089785a1f5dee523d1db836b6d30b6c226c5bd1e00493040e3b244b920000206f8cd767796594997c184b946d11a0305dc70c43bdc4ec142ec45ed1c10fd0b620409e5d22bbb60d53fb8043f823478024e7ebc89d635cd32efe27f0c301ea457e20cdf35a6da5556e432caba8db1559441a4ce2e79869340a964fda9637babf94d8209f4169310ee7c01aeacc88d3310f65cd2521d69da42a03c0ba56e1fe455e5cea0000000000000000000000003d011a000000000000000000000000000000000000000000000000000c201714f5861026fc3968ef442517da5bc15744770e2a48d55271ef40ed62aebbb1cb03c900c620dcb71d056f3cf1063bd47cd5466a0d0f480493bb963a1729f5b6119bbb2fb1002064084b8f53a425764bffd9c8d42ccef4550a6f298e92a57b339d9cbb37190751146591ea90e4cc4490f8bdd1a714f5f5d36a23711e020000000000000014a4260d6f81c436b8cbc99673eaf81e632c4e9d7d06756e6c6f636b4a14f8e41a74d1a9053acfc052df3686370452bb83c5140b24abdd39185055311aaa27082f9deb294a7255100000000000000000000000000000000000000000000000000000000000000000") + param := &scom.EntranceParam{ + SourceChainID: 4, + Height: 7006, + Proof: proofBs, + RelayerAddress: acct.Address[:], + Extra: []byte{}, + HeaderOrCrossChainMsg: neoCrossChainMsgBs, + } + + var err error + sink := common.NewZeroCopySink(nil) + param.Serialization(sink) + + sink = common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + + native = NewNative(sink.Bytes(), tx, native.GetCacheDB()) + neoHandler := NewNeo3Handler() + SetContract(native, "b0d4f20da68a6007d4fb7eac374b5566a5b0e229") + _, err = neoHandler.MakeDepositProposal(native) + assert.Nil(t, err) + } +} + +func TestNEOHandler_SetCcmcId(t *testing.T) { + // test positive int + idp := 12 + idpBytes := helper.IntToBytes(idp) + ss := helper.BytesToHex(idpBytes) + log.Println(ss) + assert.Equal(t, "0c000000", ss) + + idp2 := int(helper.BytesToUInt32(idpBytes)) + assert.Equal(t, idp, idp2) + + // test negative int + idn := -5 + idnBytes := helper.IntToBytes(idn) + log.Println(helper.BytesToHex(idnBytes)) + + idn2 := int(int32(helper.BytesToUInt32(idnBytes))) + assert.Equal(t, idn, idn2) +} diff --git a/native/service/cross_chain_manager/neo3/utils.go b/native/service/cross_chain_manager/neo3/utils.go new file mode 100644 index 000000000..71c489966 --- /dev/null +++ b/native/service/cross_chain_manager/neo3/utils.go @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ +package neo3 + +import ( + "fmt" + "github.com/joeqian10/neo3-gogogo/helper" + "github.com/joeqian10/neo3-gogogo/mpt" + "github.com/polynetwork/poly/common" + scom "github.com/polynetwork/poly/native/service/cross_chain_manager/common" + "github.com/polynetwork/poly/native/service/header_sync/neo3" +) + +func verifyFromNeoTx(proof []byte, crossChainMsg *neo3.NeoCrossChainMsg, contractId int) (*scom.MakeTxParam, error) { + crossStateProofRoot, err := helper.UInt256FromString(crossChainMsg.StateRoot.RootHash) + if err != nil { + return nil, fmt.Errorf("verifyFromNeoTx, decode cross state proof root from string error: %s", err) + } + value, err := VerifyNeoCrossChainProof(proof, crossStateProofRoot.ToByteArray(), contractId) + if err != nil { + return nil, fmt.Errorf("VerifyFromNeoTx, Verify Neo cross chain proof error: %v", err) + } + source := common.NewZeroCopySource(value) + txParam := new(scom.MakeTxParam) + if err := txParam.Deserialization(source); err != nil { + return nil, fmt.Errorf("VerifyFromNeoTx, deserialize merkleValue error: %s", err) + } + return txParam, nil +} + +func VerifyNeoCrossChainProof(proof []byte, stateRoot []byte, contractId int) ([]byte, error) { + id, key, proofs, err := mpt.ResolveProof(proof) + if err != nil { + return nil, fmt.Errorf("VerifyNeoCrossChainProof, neo3-gogogo mpt.ResolveProof error: %v", err) + } + if id != contractId { + return nil, fmt.Errorf("VerifyNeoCrossChainProof, error: id is not CCMC contract id, expected: %d, but got: %d", contractId, id) + } + root := helper.UInt256FromBytes(stateRoot) + value, err := mpt.VerifyProof(root, contractId, key, proofs) + if err != nil { + return nil, fmt.Errorf("VerifyNeoCrossChainProof, neo3-gogogo mpt.VerifyProof error: %v", err) + } + return value, nil +} diff --git a/native/service/governance/neo3_state_manager/neo3_state_manager.go b/native/service/governance/neo3_state_manager/neo3_state_manager.go new file mode 100644 index 000000000..f6247d836 --- /dev/null +++ b/native/service/governance/neo3_state_manager/neo3_state_manager.go @@ -0,0 +1,158 @@ +package neo3_state_manager + +import ( + "fmt" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/event" + "github.com/polynetwork/poly/native/service/governance/node_manager" + "github.com/polynetwork/poly/native/service/utils" +) + +const ( + //function name + GET_CURRENT_STATE_VALIDATOR = "getCurrentStateValidator" + REGISTER_STATE_VALIDATOR = "registerStateValidator" + APPROVE_REGISTER_STATE_VALIDATOR = "approveRegisterStateValidator" + REMOVE_STATE_VALIDATOR = "removeStateValidator" + APPROVE_REMOVE_STATE_VALIDATOR = "approveRemoveStateValidator" + + //key prefix + STATE_VALIDATOR = "stateValidator" + STATE_VALIDATOR_APPLY = "stateValidatorApply" + STATE_VALIDATOR_REMOVE = "stateValidatorRemove" + STATE_VALIDATOR_APPLY_ID = "stateValidatorApplyID" + STATE_VALIDATOR_REMOVE_ID = "stateValidatorRemoveID" +) + +// todo, review code + +func GetCurrentStateValidator(native *native.NativeService) ([]byte, error) { + svs, err := getStateValidators(native) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("GetCurrentStateValidator, getStateValidators error: %v", err) + } + data := SerializeStringArray(svs) + return data, nil +} + +//Register methods of node_manager contract +func RegisterStateValidatorManagerContract(native *native.NativeService) { + native.Register(GET_CURRENT_STATE_VALIDATOR, GetCurrentStateValidator) + native.Register(REGISTER_STATE_VALIDATOR, RegisterStateValidator) + native.Register(APPROVE_REGISTER_STATE_VALIDATOR, ApproveRegisterStateValidator) + native.Register(REMOVE_STATE_VALIDATOR, RemoveStateValidator) + native.Register(APPROVE_REMOVE_STATE_VALIDATOR, ApproveRemoveStateValidator) +} + +func RegisterStateValidator(native *native.NativeService) ([]byte, error) { + params := new(StateValidatorListParam) + if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return utils.BYTE_FALSE, fmt.Errorf("RegisterStateValidator, params.Deserialization error: %v", err) + } + //check witness + if err := utils.ValidateOwner(native, params.Address); err != nil { + return utils.BYTE_FALSE, fmt.Errorf("RegisterStateValidator, checkWitness: %s, error: %v", params.Address.ToBase58(), err) + } + if err := putStateValidatorApply(native, params); err != nil { + return utils.BYTE_FALSE, fmt.Errorf("RegisterStateValidator, putStateValidatorApply error: %v", err) + } + return utils.BYTE_TRUE, nil +} + +func ApproveRegisterStateValidator(native *native.NativeService) ([]byte, error) { + params := new(ApproveStateValidatorParam) + if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRegisterStateValidator, contract params deserialize error: %v", err) + } + + //check witness + err := utils.ValidateOwner(native, params.Address) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRegisterStateValidator, checkWitness error: %v", err) + } + + svListParam, err := getStateValidatorApply(native, params.ID) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRegisterStateValidator, getStateValidatorApply error: %v", err) + } + + //check consensus signs + ok, err := node_manager.CheckConsensusSigns(native, APPROVE_REGISTER_STATE_VALIDATOR, utils.GetUint64Bytes(params.ID), params.Address) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRegisterStateValidator, CheckConsensusSigns error: %v", err) + } + if !ok { + return utils.BYTE_FALSE, nil + } + + // put all the state validators in storage + err = putStateValidators(native, svListParam.StateValidators) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRegisterStateValidator, putStateValidators error: %v", err) + } + + native.GetCacheDB().Delete(utils.ConcatKey(utils.Neo3StateManagerContractAddress, []byte(STATE_VALIDATOR_APPLY), utils.GetUint64Bytes(params.ID))) + native.AddNotify( + &event.NotifyEventInfo{ + ContractAddress: utils.Neo3StateManagerContractAddress, + States: []interface{}{"ApproveRegisterStateValidator", params.ID}, + }) + return utils.BYTE_TRUE, nil +} + +func RemoveStateValidator(native *native.NativeService) ([]byte, error) { + params := new(StateValidatorListParam) + if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return utils.BYTE_FALSE, fmt.Errorf("RemoveStateValidator, contract params deserialize error: %v", err) + } + //check witness + if err := utils.ValidateOwner(native, params.Address); err != nil { + return utils.BYTE_FALSE, fmt.Errorf("RemoveStateValidator, checkWitness: %s, error: %v", params.Address.ToBase58(), err) + } + err := putStateValidatorRemove(native, params) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("RemoveStateValidator, putStateValidatorRemove error: %v", err) + } + return utils.BYTE_TRUE, nil +} + +func ApproveRemoveStateValidator(native *native.NativeService) ([]byte, error) { + params := new(ApproveStateValidatorParam) + if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRemoveStateValidator, contract params deserialize error: %v", err) + } + + //check witness + err := utils.ValidateOwner(native, params.Address) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRemoveStateValidator, checkWitness error: %v", err) + } + + svListParam, err := getStateValidatorRemove(native, params.ID) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRemoveStateValidator, getStateValidatorRemove error: %v", err) + } + + //check consensus signs + ok, err := node_manager.CheckConsensusSigns(native, APPROVE_REMOVE_STATE_VALIDATOR, utils.GetUint64Bytes(params.ID), params.Address) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRemoveStateValidator, CheckConsensusSigns error: %v", err) + } + if !ok { + return utils.BYTE_FALSE, nil + } + + // remove svs + err = removeStateValidators(native, svListParam.StateValidators) + if err != nil { + return utils.BYTE_FALSE, fmt.Errorf("ApproveRemoveStateValidator, removeStateValidators error: %v", err) + } + + native.AddNotify( + &event.NotifyEventInfo{ + ContractAddress: utils.Neo3StateManagerContractAddress, + States: []interface{}{"ApproveRemoveStateValidator", params.ID}, + }) + return utils.BYTE_TRUE, nil +} diff --git a/native/service/governance/neo3_state_manager/neo3_state_manager_test.go b/native/service/governance/neo3_state_manager/neo3_state_manager_test.go new file mode 100644 index 000000000..61fea70fb --- /dev/null +++ b/native/service/governance/neo3_state_manager/neo3_state_manager_test.go @@ -0,0 +1,302 @@ +package neo3_state_manager + +import ( + "github.com/ontio/ontology-crypto/keypair" + "github.com/polynetwork/poly/account" + "github.com/polynetwork/poly/common" + vconfig "github.com/polynetwork/poly/consensus/vbft/config" + "github.com/polynetwork/poly/core/genesis" + cstates "github.com/polynetwork/poly/core/states" + "github.com/polynetwork/poly/core/store/leveldbstore" + "github.com/polynetwork/poly/core/store/overlaydb" + "github.com/polynetwork/poly/core/types" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/service/governance/node_manager" + "github.com/polynetwork/poly/native/service/utils" + "github.com/polynetwork/poly/native/storage" + "github.com/stretchr/testify/assert" + "log" + "strconv" + "testing" +) + +var ( + acct = account.NewAccount("") + conAccts = func() []*account.Account { + accts := make([]*account.Account, 0, 7) + for i := 0; i < 7; i++ { + accts = append(accts, account.NewAccount(strconv.FormatUint(uint64(i), 10))) + } + return accts + } + getNativeFunc = func() *native.NativeService { + store, _ := + leveldbstore.NewMemLevelDBStore() + cacheDB := storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + ns, _ := native.NewNativeService(cacheDB, new(types.Transaction), 0, 200, common.Uint256{}, 0, nil, false) + return ns + } + + setBKers = func() { + genesis.GenesisBookkeepers = []keypair.PublicKey{acct.PublicKey} + } + + nativeService *native.NativeService +) + +func init() { + setBKers() +} +func putPeerMapPoolAndView(db *storage.CacheDB, conAccts []*account.Account) { + peerPoolMap := new(node_manager.PeerPoolMap) + peerPoolMap.PeerPoolMap = make(map[string]*node_manager.PeerPoolItem) + for i, conAcct := range conAccts { + pkStr := vconfig.PubkeyID(conAcct.PublicKey) + peerPoolMap.PeerPoolMap[pkStr] = &node_manager.PeerPoolItem{ + Index: uint32(i), + PeerPubkey: pkStr, + Address: conAcct.Address, + Status: node_manager.ConsensusStatus, + } + } + viewBytes := utils.GetUint32Bytes(0) + sink := common.NewZeroCopySink(nil) + peerPoolMap.Serialization(sink) + db.Put(utils.ConcatKey(utils.NodeManagerContractAddress, []byte(node_manager.PEER_POOL), viewBytes), cstates.GenRawStorageItem(sink.Bytes())) + + govView := node_manager.GovernanceView{ + 0, 10, common.UINT256_EMPTY, + } + sink = common.NewZeroCopySink(nil) + govView.Serialization(sink) + db.Put(utils.ConcatKey(utils.NodeManagerContractAddress, []byte(node_manager.GOVERNANCE_VIEW)), cstates.GenRawStorageItem(sink.Bytes())) +} + +func NewNative(args []byte, tx *types.Transaction, db *storage.CacheDB) *native.NativeService { + if db == nil { + store, _ := leveldbstore.NewMemLevelDBStore() + db = storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + } + ns, _ := native.NewNativeService(db, tx, 0, 0, common.Uint256{0}, 0, args, false) + return ns +} + +func TestRegisterStateValidator(t *testing.T) { + params := new(StateValidatorListParam) + // four state validators + params.StateValidators = []string{ + "023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", + "03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", + "02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", + "03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806", + } + params.Address = acct.Address + sink := common.NewZeroCopySink(nil) + params.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nil) + consensusAccounts := conAccts() + putPeerMapPoolAndView(nativeService.GetCacheDB(), consensusAccounts) + // register + res, err := RegisterStateValidator(nativeService) + assert.Equal(t, res, []byte{1}) + assert.Nil(t, err) + + svListParam, err := getStateValidatorApply(nativeService, 0) + assert.Nil(t, err) + assert.Equal(t, params, svListParam) + + // none consensus acct should not be able to approve register + notConAcct := account.NewAccount("x") + asvp := &ApproveStateValidatorParam{ + 0, + notConAcct.Address, + } + sink = common.NewZeroCopySink(nil) + asvp.Serialization(sink) + tx = &types.Transaction{ + SignedAddr: []common.Address{notConAcct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nativeService.GetCacheDB()) + res, err = ApproveRegisterStateValidator(nativeService) + assert.Nil(t, err) + assert.Equal(t, utils.BYTE_FALSE, res) + + for i, conAcct := range consensusAccounts { + asvp := &ApproveStateValidatorParam{ + 0, + conAcct.Address, + } + sink := common.NewZeroCopySink(nil) + asvp.Serialization(sink) + tx := &types.Transaction{ + SignedAddr: []common.Address{conAcct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nativeService.GetCacheDB()) + res, err := ApproveRegisterStateValidator(nativeService) + assert.Nil(t, err) + + if i < (2*len(consensusAccounts)+2)/3-1 { // not enough sig + assert.Equal(t, utils.BYTE_FALSE, res) + } else { + assert.Equal(t, utils.BYTE_TRUE, res) + break + } + } +} + +func TestGetCurrentStateValidator(t *testing.T) { + params := new(StateValidatorListParam) + // four state validators + params.StateValidators = []string{ + "023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", + "03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", + "02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", + "03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806", + } + params.Address = acct.Address + sink := common.NewZeroCopySink(nil) + params.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nil) + consensusAccounts := conAccts() + putPeerMapPoolAndView(nativeService.GetCacheDB(), consensusAccounts) + + contract := utils.Neo3StateManagerContractAddress + // clear storage + nativeService.GetCacheDB().Delete(utils.ConcatKey(contract, []byte(STATE_VALIDATOR))) + + // register + res, err := RegisterStateValidator(nativeService) + assert.Equal(t, res, []byte{1}) + assert.Nil(t, err) + + // approve + for i, conAcct := range consensusAccounts { + log.Println(i) + asvp := &ApproveStateValidatorParam{ + 0, + conAcct.Address, + } + sink := common.NewZeroCopySink(nil) + asvp.Serialization(sink) + tx := &types.Transaction{ + SignedAddr: []common.Address{conAcct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nativeService.GetCacheDB()) + res, err := ApproveRegisterStateValidator(nativeService) + assert.Nil(t, err) + if i < (2*len(consensusAccounts)+2)/3-1 { // not enough sig + assert.Equal(t, utils.BYTE_FALSE, res) + } else { + assert.Equal(t, utils.BYTE_TRUE, res) + break + } + //if i < (2*len(consensusAccounts)+2)/3 - 1 { // not enough sig + // ok, err := node_manager.CheckConsensusSigns(nativeService, APPROVE_REGISTER_STATE_VALIDATOR, utils.GetUint64Bytes(0), conAcct.Address) + // assert.Nil(t, err) + // assert.Equal(t, false, ok) + //} + } + // get + svs, err := getStateValidators(nativeService) + assert.Nil(t, err) + assert.Equal(t, 4, len(svs)) + + svBytes, err := GetCurrentStateValidator(nativeService) + assert.Nil(t, err) + assert.Equal(t, 269, len(svBytes)) +} + +func TestRemoveStateValidator(t *testing.T) { + params := new(StateValidatorListParam) + // four state validators + params.StateValidators = []string{ + "023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", + "03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", + "02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", + "03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806", + } + params.Address = acct.Address + sink := common.NewZeroCopySink(nil) + params.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nil) // for register + consensusAccounts := conAccts() + putPeerMapPoolAndView(nativeService.GetCacheDB(), consensusAccounts) + + // first register + res, err := RegisterStateValidator(nativeService) + assert.Equal(t, res, []byte{1}) + assert.Nil(t, err) + + // approve register + for i, conAcct := range consensusAccounts { + asvp := &ApproveStateValidatorParam{ + 0, + conAcct.Address, + } + sink := common.NewZeroCopySink(nil) + asvp.Serialization(sink) + tx := &types.Transaction{ + SignedAddr: []common.Address{conAcct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nativeService.GetCacheDB()) + res, err := ApproveRegisterStateValidator(nativeService) + assert.Nil(t, err) + + if i < (2*len(consensusAccounts)+2)/3-1 { // not enough sig + assert.Equal(t, utils.BYTE_FALSE, res) + } else { + assert.Equal(t, utils.BYTE_TRUE, res) + break + } + } + + // confirm state validators in storage + svs, err := getStateValidators(nativeService) + assert.Nil(t, err) + assert.Equal(t, 4, len(svs)) + + // remove + nativeService = NewNative(sink.Bytes(), tx, nativeService.GetCacheDB()) // for remove + res, err = RemoveStateValidator(nativeService) + assert.Equal(t, res, []byte{1}) + assert.Nil(t, err) + + svRaw1, err := getStateValidatorRemove(nativeService, 0) + assert.Nil(t, err) + assert.Equal(t, params, svRaw1) + + // approve remove + for i, conAcct := range consensusAccounts { + asvp := &ApproveStateValidatorParam{ + 0, + conAcct.Address, + } + sink := common.NewZeroCopySink(nil) + asvp.Serialization(sink) + tx := &types.Transaction{ + SignedAddr: []common.Address{conAcct.Address}, + } + nativeService = NewNative(sink.Bytes(), tx, nativeService.GetCacheDB()) + res, err := ApproveRemoveStateValidator(nativeService) + assert.Nil(t, err) + + if i < (2*len(consensusAccounts)+2)/3-1 { // not enough sig + assert.Equal(t, utils.BYTE_FALSE, res) + } else { + assert.Equal(t, utils.BYTE_TRUE, res) + break + } + } +} diff --git a/native/service/governance/neo3_state_manager/param.go b/native/service/governance/neo3_state_manager/param.go new file mode 100644 index 000000000..177606e73 --- /dev/null +++ b/native/service/governance/neo3_state_manager/param.go @@ -0,0 +1,75 @@ +package neo3_state_manager + +import ( + "fmt" + "github.com/polynetwork/poly/common" +) + +type StateValidatorListParam struct { + StateValidators []string // public key strings in encoded format, each is 33 bytes in []byte + Address common.Address // for check witness? +} + +func (this *StateValidatorListParam) Serialization(sink *common.ZeroCopySink) { + sink.WriteVarUint(uint64(len(this.StateValidators))) + for _, v := range this.StateValidators { + sink.WriteString(v) + } + sink.WriteVarBytes(this.Address[:]) +} + +func (this *StateValidatorListParam) Deserialization(source *common.ZeroCopySource) error { + n, eof := source.NextVarUint() + if eof { + return fmt.Errorf("source.NextVarUint, deserialize StateValidators length error") + } + stateValidators := make([]string, 0, n) + for i := 0; uint64(i) < n; i++ { + ss, eof := source.NextString() + if eof { + return fmt.Errorf("source.NextString, deserialize stateValidator error") + } + stateValidators = append(stateValidators, ss) + } + + address, eof := source.NextVarBytes() + if eof { + return fmt.Errorf("source.NextVarBytes, deserialize address error") + } + addr, err := common.AddressParseFromBytes(address) + if err != nil { + return fmt.Errorf("common.AddressParseFromBytes, deserialize address error: %s", err) + } + this.StateValidators = stateValidators + this.Address = addr + return nil +} + +type ApproveStateValidatorParam struct { + ID uint64 // StateValidatorApproveID + Address common.Address // for check witness? +} + +func (this *ApproveStateValidatorParam) Serialization(sink *common.ZeroCopySink) { + sink.WriteVarUint(this.ID) + sink.WriteVarBytes(this.Address[:]) +} + +func (this *ApproveStateValidatorParam) Deserialization(source *common.ZeroCopySource) error { + ID, eof := source.NextVarUint() + if eof { + return fmt.Errorf("source.NextVarUint, deserialize ID error") + } + + address, eof := source.NextVarBytes() + if eof { + return fmt.Errorf("source.NextVarBytes, deserialize address error") + } + addr, err := common.AddressParseFromBytes(address) + if err != nil { + return fmt.Errorf("common.AddressParseFromBytes, deserialize address error: %s", err) + } + this.ID = ID + this.Address = addr + return nil +} diff --git a/native/service/governance/neo3_state_manager/param_test.go b/native/service/governance/neo3_state_manager/param_test.go new file mode 100644 index 000000000..cd3b504a3 --- /dev/null +++ b/native/service/governance/neo3_state_manager/param_test.go @@ -0,0 +1,25 @@ +package neo3_state_manager + +import ( + "github.com/polynetwork/poly/common" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestStateValidatorListParam_Serialization(t *testing.T) { + params := new(StateValidatorListParam) + params.StateValidators = []string{ + "023e9b32ea89b94d066e649b124fd50e396ee91369e8e2a6ae1b11c170d022256d", + "03009b7540e10f2562e5fd8fac9eaec25166a58b26e412348ff5a86927bfac22a2", + "02ba2c70f5996f357a43198705859fae2cfea13e1172962800772b3d588a9d4abd", + "03408dcd416396f64783ac587ea1e1593c57d9fea880c8a6a1920e92a259477806", + } + sink := common.NewZeroCopySink(nil) + params.Serialization(sink) + + source := common.NewZeroCopySource(sink.Bytes()) + var p StateValidatorListParam + err := p.Deserialization(source) + assert.Nil(t, err) + assert.Equal(t, 4, len(p.StateValidators)) +} diff --git a/native/service/governance/neo3_state_manager/utils.go b/native/service/governance/neo3_state_manager/utils.go new file mode 100644 index 000000000..c1e130435 --- /dev/null +++ b/native/service/governance/neo3_state_manager/utils.go @@ -0,0 +1,247 @@ +package neo3_state_manager + +import ( + "fmt" + "github.com/polynetwork/poly/common" + cstates "github.com/polynetwork/poly/core/states" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/event" + "github.com/polynetwork/poly/native/service/utils" +) + +func SerializeStringArray(data []string) []byte { + sink := common.NewZeroCopySink(nil) + // serialize + sink.WriteVarUint(uint64(len(data))) + for _, v := range data { + sink.WriteString(v) + } + return sink.Bytes() +} + +func DeserializeStringArray(data []byte) ([]string, error) { + source := common.NewZeroCopySource(data) + n, eof := source.NextVarUint() + if eof { + return nil, fmt.Errorf("source.NextVarUint error") + } + result := make([]string, 0, n) + for i := 0; uint64(i) < n; i++ { + ss, eof := source.NextString() + if eof { + return nil, fmt.Errorf("source.NextString error") + } + result = append(result, ss) + } + return result, nil +} + +func getStateValidators(native *native.NativeService) ([]string, error) { + contract := utils.Neo3StateManagerContractAddress + svStore, err := native.GetCacheDB().Get(utils.ConcatKey(contract, []byte(STATE_VALIDATOR))) + if err != nil { + return nil, fmt.Errorf("getStateValidator, get stateValidatorListParamStore error: %v", err) + } + if svStore == nil { + return []string{}, nil + } + svBytes, err := cstates.GetValueFromRawStorageItem(svStore) + if err != nil { + return nil, fmt.Errorf("getStateValidator, deserialize from raw storage item error: %v", err) + } + svs, err := DeserializeStringArray(svBytes) + if err != nil { + return nil, fmt.Errorf("getStateValidator, convert to UInt160 array error: %v", err) + } + return svs, nil +} + +func putStateValidators(native *native.NativeService, stateValidators []string) error { + contract := utils.Neo3StateManagerContractAddress + // get current stored value + oldSVs, err := getStateValidators(native) + if err != nil { + return fmt.Errorf("putStateValidator, get old state validators error: %v", err) + } + // max capacity = len(oldSVs)+len(stateValidators) + newSVs := make([]string, 0, len(oldSVs)+len(stateValidators)) + newSVs = append(newSVs, oldSVs...) + // filter duplicate svs + for _, sv := range stateValidators { + isInOld := false + for _, oldSv := range oldSVs{ + if sv == oldSv { + isInOld = true + break + } + } + if !isInOld { + newSVs = append(newSVs, sv) + } + } + // convert back to []byte + data := SerializeStringArray(newSVs) + native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(STATE_VALIDATOR)), cstates.GenRawStorageItem(data)) + return nil +} + +func removeStateValidators(native *native.NativeService, stateValidators []string) error { + contract := utils.Neo3StateManagerContractAddress + // get current stored value + oldSVs, err := getStateValidators(native) + if err != nil { + return fmt.Errorf("removeStateValidator, get old state validators error: %v", err) + } + // remove in the slice + for _, sv := range stateValidators { + for i, oldSv := range oldSVs{ + if sv == oldSv { + oldSVs = append(oldSVs[:i], oldSVs[i+1:]...) + break + } + } + } + // if no sv left, delete the storage, else put remaining back + if len(oldSVs) == 0 { + native.GetCacheDB().Delete(utils.ConcatKey(contract, []byte(STATE_VALIDATOR))) + return nil + } + // convert back to []byte + data := SerializeStringArray(oldSVs) + native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(STATE_VALIDATOR)), cstates.GenRawStorageItem(data)) + return nil +} + +func getStateValidatorApply(native *native.NativeService, applyID uint64) (*StateValidatorListParam, error) { + contract := utils.Neo3StateManagerContractAddress + svListParamStore, err := native.GetCacheDB().Get(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_APPLY), utils.GetUint64Bytes(applyID))) + if err != nil { + return nil, fmt.Errorf("getStateValidatorApply, get stateValidatorListParamStore error: %v", err) + } + if svListParamStore == nil { + return nil, nil + } + svListParam := new(StateValidatorListParam) + svListParamBytes, err := cstates.GetValueFromRawStorageItem(svListParamStore) + if err != nil { + return nil, fmt.Errorf("getStateValidatorApply, deserialize from raw storage item error: %v", err) + } + err = svListParam.Deserialization(common.NewZeroCopySource(svListParamBytes)) + if err != nil { + + } + return svListParam, nil +} + +func putStateValidatorApply(native *native.NativeService, stateValidatorListParam *StateValidatorListParam) error { + contract := utils.Neo3StateManagerContractAddress + applyID, err := getStateValidatorApplyID(native) + if err != nil { + return fmt.Errorf("putStateValidatorApply, getStateValidatorApplyID error: %v", err) + } + newApplyID := applyID + 1 + err = putStateValidatorApplyID(native, newApplyID) + if err != nil { + return fmt.Errorf("putStateValidatorApply, putStateValidatorApplyID error: %v", err) + } + sink := common.NewZeroCopySink(nil) + stateValidatorListParam.Serialization(sink) + native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_APPLY), utils.GetUint64Bytes(applyID)), cstates.GenRawStorageItem(sink.Bytes())) + native.AddNotify( + &event.NotifyEventInfo{ + ContractAddress: contract, + States: []interface{}{"putStateValidatorApply", applyID}, + }) + return nil +} + +func getStateValidatorApplyID(native *native.NativeService) (uint64, error) { + contract := utils.Neo3StateManagerContractAddress + applyIDStore, err := native.GetCacheDB().Get(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_APPLY_ID))) + if err != nil { + return 0, fmt.Errorf("getStateValidatorApplyID, get applyIDStore error: %v", err) + } + var applyID uint64 = 0 + if applyIDStore != nil { + applyIDBytes, err := cstates.GetValueFromRawStorageItem(applyIDStore) + if err != nil { + return 0, fmt.Errorf("getStateValidatorApplyID, deserialize from raw storage item error: %v", err) + } + applyID = utils.GetBytesUint64(applyIDBytes) + } + return applyID, nil +} + +func putStateValidatorApplyID(native *native.NativeService, applyID uint64) error { + contract := utils.Neo3StateManagerContractAddress + applyIDByte := utils.GetUint64Bytes(applyID) + native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_APPLY_ID)), cstates.GenRawStorageItem(applyIDByte)) + return nil +} + +func getStateValidatorRemove(native *native.NativeService, removeID uint64) (*StateValidatorListParam, error) { + contract := utils.Neo3StateManagerContractAddress + svListParamStore, err := native.GetCacheDB().Get(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_REMOVE), utils.GetUint64Bytes(removeID))) + if err != nil { + return nil, fmt.Errorf("getStateValidatorRemove, get stateValidatorListParamStore error: %v", err) + } + if svListParamStore == nil { + return nil, nil + } + svListParam := new(StateValidatorListParam) + svListParamBytes, err := cstates.GetValueFromRawStorageItem(svListParamStore) + if err != nil { + return nil, fmt.Errorf("getStateValidatorRemove, deserialize from raw storage item error: %v", err) + } + err = svListParam.Deserialization(common.NewZeroCopySource(svListParamBytes)) + if err != nil { + return nil, fmt.Errorf("getStateValidatorRemove, svListParam.Deserialization error: %v", err) + } + return svListParam, nil +} + +func putStateValidatorRemove(native *native.NativeService, svListParam *StateValidatorListParam) error { + contract := utils.Neo3StateManagerContractAddress + removeID, err := getStateValidatorRemoveID(native) + if err != nil { + return fmt.Errorf("putStateValidatorRemove, getStateValidatorRemoveID error: %v", err) + } + newRemoveID := removeID + 1 + err = putStateValidatorRemoveID(native, newRemoveID) + if err != nil { + return fmt.Errorf("putStateValidatorRemove, putStateValidatorRemoveID error: %v", err) + } + sink := common.NewZeroCopySink(nil) + svListParam.Serialization(sink) + native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_REMOVE), utils.GetUint64Bytes(removeID)), cstates.GenRawStorageItem(sink.Bytes())) + native.AddNotify( + &event.NotifyEventInfo{ + ContractAddress: contract, + States: []interface{}{"putStateValidatorRemove", removeID}, + }) + return nil +} + +func getStateValidatorRemoveID(native *native.NativeService) (uint64, error) { + contract := utils.Neo3StateManagerContractAddress + removeIDStore, err := native.GetCacheDB().Get(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_REMOVE_ID))) + if err != nil { + return 0, fmt.Errorf("getStateValidatorRemoveID, get removeIDStore error: %v", err) + } + var removeID uint64 = 0 + if removeIDStore != nil { + removeIDBytes, err := cstates.GetValueFromRawStorageItem(removeIDStore) + if err != nil { + return 0, fmt.Errorf("getStateValidatorRemoveID, deserialize from raw storage item error: %v", err) + } + removeID = utils.GetBytesUint64(removeIDBytes) + } + return removeID, nil +} + +func putStateValidatorRemoveID(native *native.NativeService, removeID uint64) error { + contract := utils.Neo3StateManagerContractAddress + removeIDBytes := utils.GetUint64Bytes(removeID) + native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(STATE_VALIDATOR_REMOVE_ID)), cstates.GenRawStorageItem(removeIDBytes)) + return nil +} diff --git a/native/service/header_sync/entrance.go b/native/service/header_sync/entrance.go index ef360c187..25fae091c 100644 --- a/native/service/header_sync/entrance.go +++ b/native/service/header_sync/entrance.go @@ -19,8 +19,11 @@ package header_sync import ( "fmt" + "github.com/polynetwork/poly/native/service/header_sync/neo" + "github.com/polynetwork/poly/native/service/header_sync/neo3" "github.com/polynetwork/poly/native/service/header_sync/heco" + "github.com/polynetwork/poly/native/service/header_sync/kai" "github.com/polynetwork/poly/native/service/header_sync/msc" "github.com/polynetwork/poly/native/service/header_sync/okex" @@ -32,7 +35,6 @@ import ( hscommon "github.com/polynetwork/poly/native/service/header_sync/common" "github.com/polynetwork/poly/native/service/header_sync/cosmos" "github.com/polynetwork/poly/native/service/header_sync/eth" - "github.com/polynetwork/poly/native/service/header_sync/neo" "github.com/polynetwork/poly/native/service/header_sync/ont" "github.com/polynetwork/poly/native/service/header_sync/quorum" "github.com/polynetwork/poly/native/service/header_sync/zilliqa" @@ -62,6 +64,8 @@ func GetChainHandler(router uint64) (hscommon.HeaderSyncHandler, error) { return ont.NewONTHandler(), nil case utils.NEO_ROUTER: return neo.NewNEOHandler(), nil + case utils.NEO3_ROUTER: + return neo3.NewNeo3Handler(), nil case utils.COSMOS_ROUTER: return cosmos.NewCosmosHandler(), nil case utils.QUORUM_ROUTER: @@ -76,6 +80,8 @@ func GetChainHandler(router uint64) (hscommon.HeaderSyncHandler, error) { return msc.NewHandler(), nil case utils.OKEX_ROUTER: return okex.NewHandler(), nil + case utils.KAI_ROUTER: + return kai.NewHandler(), nil default: return nil, fmt.Errorf("not a supported router:%d", router) } diff --git a/native/service/header_sync/kai/header_sync.go b/native/service/header_sync/kai/header_sync.go new file mode 100644 index 000000000..c7d00d404 --- /dev/null +++ b/native/service/header_sync/kai/header_sync.go @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ +package kai + +import ( + "encoding/json" + "fmt" + "strconv" + + kaiclient "github.com/kardiachain/go-kaiclient/kardia" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/common/log" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/service/governance/node_manager" + hscommon "github.com/polynetwork/poly/native/service/header_sync/common" + "github.com/polynetwork/poly/native/service/utils" +) + +// Handler ... +type Handler struct { +} + +func NewHandler() *Handler { + return &Handler{} +} + +func (h *Handler) SyncGenesisHeader(native *native.NativeService) error { + param := new(hscommon.SyncGenesisHeaderParam) + if err := param.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return fmt.Errorf("Handler SyncGenesisHeader, contract params deserialize error: %v", err) + } + // Get current epoch operator + operatorAddress, err := node_manager.GetCurConOperator(native) + if err != nil { + return fmt.Errorf("Handler SyncGenesisHeader, get current consensus operator address error: %v", err) + } + //check witness + err = utils.ValidateOwner(native, operatorAddress) + if err != nil { + return fmt.Errorf("Handler SyncGenesisHeader, checkWitness error: %v", err) + } + // get genesis header from input parameters + var header kaiclient.FullHeader + if err := json.Unmarshal(param.GenesisHeader, &header); err != nil { + return fmt.Errorf("Handler SyncGenesisHeader, Unmarshal error: %v", err) + } + + // check if has genesis header + info, err := GetEpochSwitchInfo(native, param.ChainID) + if err == nil && info != nil { + return fmt.Errorf("Handler SyncGenesisHeader, genesis header had been initialized") + } + PutEpochSwitchInfo(native, param.ChainID, &EpochSwitchInfo{ + Height: int64(header.Header.Height), + NextValidatorsHash: header.Header.NextValidatorsHash.Bytes(), + ChainID: strconv.Itoa(int(param.ChainID)), + BlockHash: header.Header.Hash().Bytes(), + }) + return nil +} + +// SyncBlockHeader ... +func (h *Handler) SyncBlockHeader(native *native.NativeService) error { + params := new(hscommon.SyncBlockHeaderParam) + if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return fmt.Errorf("SyncBlockHeader, contract params deserialize error: %v", err) + } + cnt := 0 + info, err := GetEpochSwitchInfo(native, params.ChainID) + if err != nil { + return fmt.Errorf("SyncBlockHeader, get epoch switching height failed: %v", err) + } + for _, v := range params.Headers { + var myHeader kaiclient.FullHeader + if err := json.Unmarshal(v, &myHeader); err != nil { + return fmt.Errorf("SyncBlockHeader failed to unmarshal header: %v", err) + } + + if myHeader.Header.NextValidatorsHash.Equal(myHeader.Header.ValidatorsHash) { + continue + } + if info.Height >= int64(myHeader.Header.Height) { + log.Debugf("SyncBlockHeader, height %d is lower or equal than epoch switching height %d", + myHeader.Header.Height, info.Height) + continue + } + if err = VerifyHeader(&myHeader, info); err != nil { + return fmt.Errorf("SyncBlockHeader, failed to verify header: %v", err) + } + info.NextValidatorsHash = myHeader.Header.NextValidatorsHash.Bytes() + info.Height = int64(myHeader.Header.Height) + info.BlockHash = myHeader.Header.Hash().Bytes() + cnt++ + } + if cnt == 0 { + return fmt.Errorf("no header you commited is useful") + } + PutEpochSwitchInfo(native, params.ChainID, info) + return nil +} + +func (this *Handler) SyncCrossChainMsg(native *native.NativeService) error { + return nil +} diff --git a/native/service/header_sync/kai/header_sync_test.go b/native/service/header_sync/kai/header_sync_test.go new file mode 100644 index 000000000..82894bd84 --- /dev/null +++ b/native/service/header_sync/kai/header_sync_test.go @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ +package kai + +import ( + "context" + "encoding/json" + "strings" + "testing" + + kaiclient "github.com/kardiachain/go-kaiclient/kardia" + "github.com/kardiachain/go-kardia/lib/bytes" + "github.com/ontio/ontology-crypto/keypair" + "github.com/polynetwork/poly/account" + "github.com/polynetwork/poly/common" + vconfig "github.com/polynetwork/poly/consensus/vbft/config" + "github.com/polynetwork/poly/core/genesis" + "github.com/polynetwork/poly/core/states" + "github.com/polynetwork/poly/core/store/leveldbstore" + "github.com/polynetwork/poly/core/store/overlaydb" + "github.com/polynetwork/poly/core/types" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/service/governance/node_manager" + scom "github.com/polynetwork/poly/native/service/header_sync/common" + "github.com/polynetwork/poly/native/service/utils" + "github.com/polynetwork/poly/native/storage" + "gotest.tools/assert" +) + +var ( + acct *account.Account = account.NewAccount("") + setBKers = func() { + genesis.GenesisBookkeepers = []keypair.PublicKey{acct.PublicKey} + } + tool kaiclient.Node +) + +func newKaiClient() kaiclient.Node { + url := "https://dev-6.kardiachain.io" + node, err := kaiclient.NewNode(url, nil) + if err != nil { + panic(err) + } + return node +} + +func init() { + setBKers() + tool = newKaiClient() +} + +func NewNative(args []byte, tx *types.Transaction, db *storage.CacheDB) (*native.NativeService, error) { + if db == nil { + store, _ := leveldbstore.NewMemLevelDBStore() + db = storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + sink := common.NewZeroCopySink(nil) + view := &node_manager.GovernanceView{ + TxHash: common.UINT256_EMPTY, + Height: 0, + View: 0, + } + view.Serialization(sink) + db.Put(utils.ConcatKey(utils.NodeManagerContractAddress, []byte(node_manager.GOVERNANCE_VIEW)), states.GenRawStorageItem(sink.Bytes())) + + peerPoolMap := &node_manager.PeerPoolMap{ + PeerPoolMap: map[string]*node_manager.PeerPoolItem{ + vconfig.PubkeyID(acct.PublicKey): { + Address: acct.Address, + Status: node_manager.ConsensusStatus, + PeerPubkey: vconfig.PubkeyID(acct.PublicKey), + Index: 0, + }, + }, + } + sink.Reset() + peerPoolMap.Serialization(sink) + db.Put(utils.ConcatKey(utils.NodeManagerContractAddress, + []byte(node_manager.PEER_POOL), utils.GetUint32Bytes(0)), states.GenRawStorageItem(sink.Bytes())) + + } + return native.NewNativeService(db, tx, 0, 0, common.Uint256{0}, 0, args, false) +} + +const ( + SUCCESS = iota + GENESIS_PARAM_ERROR + GENESIS_INITIALIZED + SYNCBLOCK_PARAM_ERROR + SYNCBLOCK_ORPHAN + DIFFICULTY_ERROR + NONCE_ERROR + OPERATOR_ERROR + UNKNOWN +) + +func typeOfError(e error) int { + if e == nil { + return SUCCESS + } + errDesc := e.Error() + if strings.Contains(errDesc, "genesis had been initialized") { + return GENESIS_INITIALIZED + } else if strings.Contains(errDesc, "deserialize GenesisHeader err") { + return GENESIS_PARAM_ERROR + // } else if strings.Contains(errDesc, "SyncBlockHeader, deserialize header err:") { + // return SYNCBLOCK_PARAM_ERROR + // } else if strings.Contains(errDesc, "SyncBlockHeader, get the parent block failed. Error:") { + // return SYNCBLOCK_ORPHAN + // } else if strings.Contains(errDesc, "SyncBlockHeader, invalid difficulty:") { + // return DIFFICULTY_ERROR + // } else if strings.Contains(errDesc, "SyncBlockHeader, verify header error:") { + // return NONCE_ERROR + } else if strings.Contains(errDesc, "SyncGenesisHeader, checkWitness error:") { + return OPERATOR_ERROR + } + return UNKNOWN +} + +const ChainID = 138 + +func getGenesisHeaderByHeight(t *testing.T, epochHeight uint64) *kaiclient.FullHeader { + h, err := tool.FullHeaderByNumber(context.Background(), epochHeight) + assert.NilError(t, err) + return h +} + +func getGenesisHeader(t *testing.T) *kaiclient.FullHeader { + return getGenesisHeaderByHeight(t, 5) +} + +func TestSyncGenesisHeader(t *testing.T) { + + genesisHeader := getGenesisHeader(t) + genesisHeaderBytes, err := json.Marshal(genesisHeader) + assert.NilError(t, err) + + param := new(scom.SyncGenesisHeaderParam) + param.ChainID = ChainID + param.GenesisHeader = genesisHeaderBytes + sink := common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + + native, err := NewNative(sink.Bytes(), tx, nil) + assert.NilError(t, err) + handler := NewHandler() + err = handler.SyncGenesisHeader(native) + assert.NilError(t, err) + + epochInfo, err := GetEpochSwitchInfo(native, 138) + assert.NilError(t, err) + assert.Equal(t, epochInfo.Height, int64(5)) + assert.Equal(t, epochInfo.NextValidatorsHash.String(), bytes.HexBytes(genesisHeader.Header.NextValidatorsHash.Bytes()).String()) + assert.Equal(t, epochInfo.ChainID, "138") + assert.Equal(t, epochInfo.BlockHash.String(), bytes.HexBytes(genesisHeader.Header.Hash().Bytes()).String()) +} + +func syncGenesisBlockHeader(t *testing.T) *native.NativeService { + genesisHeader := getGenesisHeader(t) + genesisHeaderBytes, err := json.Marshal(genesisHeader) + assert.NilError(t, err) + + param := new(scom.SyncGenesisHeaderParam) + param.ChainID = ChainID + param.GenesisHeader = genesisHeaderBytes + sink := common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + + native, err := NewNative(sink.Bytes(), tx, nil) + assert.NilError(t, err) + handler := NewHandler() + err = handler.SyncGenesisHeader(native) + assert.NilError(t, err) + return native +} + +func TestSyncBlockHeader(t *testing.T) { + native := syncGenesisBlockHeader(t) + + param := new(scom.SyncBlockHeaderParam) + param.ChainID = ChainID + param.Address = acct.Address + + h1 := getGenesisHeaderByHeight(t, 6) + hb1, err := json.Marshal(h1) + assert.NilError(t, err) + + h2 := getGenesisHeaderByHeight(t, 7) + hb2, err := json.Marshal(h2) + assert.NilError(t, err) + + param.Headers = append(param.Headers, hb1) + param.Headers = append(param.Headers, hb2) + + sink := common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + + native, err = NewNative(sink.Bytes(), tx, native.GetCacheDB()) + assert.NilError(t, err) + handler := NewHandler() + _ = handler.SyncBlockHeader(native) +} + +func TestVerifyHeader(t *testing.T) { + native := syncGenesisBlockHeader(t) + epochInfo, err := GetEpochSwitchInfo(native, 138) + assert.NilError(t, err) + h6 := getGenesisHeaderByHeight(t, 6) + err = VerifyHeader(h6, epochInfo) + assert.NilError(t, err) +} diff --git a/native/service/header_sync/kai/state.go b/native/service/header_sync/kai/state.go new file mode 100644 index 000000000..907447b46 --- /dev/null +++ b/native/service/header_sync/kai/state.go @@ -0,0 +1,53 @@ +package kai + +import ( + "fmt" + + "github.com/kardiachain/go-kardia/lib/bytes" + "github.com/polynetwork/poly/common" +) + +type EpochSwitchInfo struct { + // The height where validators set changed last time. Poly only accept + // header and proof signed by new validators. That means the header + // can not be lower than this height. + Height int64 + + // Hash of the block at `Height`. Poly don't save the whole header. + // So we can identify the content of this block by `BlockHash`. + BlockHash bytes.HexBytes + + // The hash of new validators set which used to verify validators set + // committed with proof. + NextValidatorsHash bytes.HexBytes + + ChainID string +} + +func (info *EpochSwitchInfo) Serialization(sink *common.ZeroCopySink) { + sink.WriteInt64(info.Height) + sink.WriteVarBytes(info.BlockHash) + sink.WriteVarBytes(info.NextValidatorsHash) + sink.WriteString(info.ChainID) +} + +func (info *EpochSwitchInfo) Deserialization(source *common.ZeroCopySource) error { + var eof bool + info.Height, eof = source.NextInt64() + if eof { + return fmt.Errorf("deserialize height of EpochSwitchInfo failed") + } + info.BlockHash, eof = source.NextVarBytes() + if eof { + return fmt.Errorf("deserialize BlockHash of EpochSwitchInfo failed") + } + info.NextValidatorsHash, eof = source.NextVarBytes() + if eof { + return fmt.Errorf("deserialize NextValidatorsHash of EpochSwitchInfo failed") + } + info.ChainID, eof = source.NextString() + if eof { + return fmt.Errorf("deserialize ChainID of EpochSwitchInfo failed") + } + return nil +} diff --git a/native/service/header_sync/kai/utils.go b/native/service/header_sync/kai/utils.go new file mode 100644 index 000000000..de28b4e6d --- /dev/null +++ b/native/service/header_sync/kai/utils.go @@ -0,0 +1,70 @@ +package kai + +import ( + "bytes" + "fmt" + + kaiclient "github.com/kardiachain/go-kaiclient/kardia" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/common/config" + cstates "github.com/polynetwork/poly/core/states" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/event" + hscommon "github.com/polynetwork/poly/native/service/header_sync/common" + "github.com/polynetwork/poly/native/service/utils" +) + +func VerifyHeader(myHeader *kaiclient.FullHeader, info *EpochSwitchInfo) error { + valset := myHeader.ValidatorSet + // now verify this header + if !bytes.Equal(info.NextValidatorsHash, valset.Hash().Bytes()) { + return fmt.Errorf("VerifyHeader, block validator is not right, next validator hash: %s, "+ + "validator set hash: %s", info.NextValidatorsHash.String(), valset.Hash().Hex()) + } + if !myHeader.Header.ValidatorsHash.Equal(valset.Hash()) { + return fmt.Errorf("VerifyHeader, block validator is not right!, header validator hash: %s, "+ + "validator set hash: %s", myHeader.Header.ValidatorsHash.String(), valset.Hash().Hex()) + } + if err := valset.VerifyCommit("", myHeader.Header.LastBlockID, myHeader.Header.Height-1, myHeader.Commit); err != nil { + return err + } + return nil +} + +func GetEpochSwitchInfo(service *native.NativeService, chainId uint64) (*EpochSwitchInfo, error) { + val, err := service.GetCacheDB().Get( + utils.ConcatKey(utils.HeaderSyncContractAddress, []byte(hscommon.EPOCH_SWITCH), utils.GetUint64Bytes(chainId))) + if err != nil { + return nil, fmt.Errorf("failed to get epoch switching height: %v", err) + } + raw, err := cstates.GetValueFromRawStorageItem(val) + if err != nil { + return nil, fmt.Errorf("deserialize bytes from raw storage item err: %v", err) + } + info := &EpochSwitchInfo{} + if err = info.Deserialization(common.NewZeroCopySource(raw)); err != nil { + return nil, fmt.Errorf("failed to deserialize EpochSwitchInfo: %v", err) + } + return info, nil +} + +func PutEpochSwitchInfo(service *native.NativeService, chainId uint64, info *EpochSwitchInfo) { + sink := common.NewZeroCopySink(nil) + info.Serialization(sink) + service.GetCacheDB().Put( + utils.ConcatKey(utils.HeaderSyncContractAddress, []byte(hscommon.EPOCH_SWITCH), utils.GetUint64Bytes(chainId)), + cstates.GenRawStorageItem(sink.Bytes())) + notifyEpochSwitchInfo(service, chainId, info) +} + +func notifyEpochSwitchInfo(native *native.NativeService, chainID uint64, info *EpochSwitchInfo) { + if !config.DefConfig.Common.EnableEventLog { + return + } + native.AddNotify( + &event.NotifyEventInfo{ + ContractAddress: utils.HeaderSyncContractAddress, + States: []interface{}{chainID, info.BlockHash.String(), info.Height, + info.NextValidatorsHash.String(), info.ChainID, native.GetHeight()}, + }) +} diff --git a/native/service/header_sync/neo/header_sync_test.go b/native/service/header_sync/neo/header_sync_test.go index cc5d0a3d8..6ef011366 100644 --- a/native/service/header_sync/neo/header_sync_test.go +++ b/native/service/header_sync/neo/header_sync_test.go @@ -228,5 +228,4 @@ func TestSyncBlockHeader(t *testing.T) { err := neoHandler.SyncBlockHeader(native) assert.NoError(t, err) } - } diff --git a/native/service/header_sync/neo/states.go b/native/service/header_sync/neo/states.go index 2370a1fc3..349d276ad 100644 --- a/native/service/header_sync/neo/states.go +++ b/native/service/header_sync/neo/states.go @@ -56,7 +56,7 @@ func (this *NeoConsensus) Deserialization(source *common.ZeroCopySource) error { var err error if this.NextConsensus, err = helper.UInt160FromBytes(nextConsensusBs); err != nil { - return fmt.Errorf("NeoConsensus.Deserialization, NextConsensus UInt160FromBytes error:%s", err) + return fmt.Errorf("NeoConsensus.Deserialization, NextConsensus UInt160FromBytes error: %s", err) } return nil } @@ -70,7 +70,7 @@ func (this *NeoBlockHeader) Deserialization(source *common.ZeroCopySource) error br := io.NewBinaryReaderFromBuf(source.Bytes()) this.BlockHeader.Deserialize(br) if br.Err != nil { - return fmt.Errorf("joeqian10/neo-gogogo/block.BlockHeader Deserialize error:%s", br.Err) + return fmt.Errorf("joeqian10/neo-gogogo/block.BlockHeader Deserialize error: %s", br.Err) } return nil } @@ -79,7 +79,7 @@ func (this *NeoBlockHeader) Serialization(sink *common.ZeroCopySink) error { bw := io.NewBufBinaryWriter() this.Serialize(bw.BinaryWriter) if bw.Err != nil { - return fmt.Errorf("joeqian10/neo-gogogo/block.BlockHeader Serialize error:%s", bw.Err) + return fmt.Errorf("joeqian10/neo-gogogo/block.BlockHeader Serialize error: %s", bw.Err) } sink.WriteBytes(bw.Bytes()) return nil @@ -89,7 +89,7 @@ func (this *NeoBlockHeader) GetMessage() ([]byte, error) { buf := io.NewBufBinaryWriter() this.SerializeUnsigned(buf.BinaryWriter) if buf.Err != nil { - return nil, fmt.Errorf("GetHashData of NeoBlockHeader joeqian10/neo-gogogo/block.BlockHeader SerializeUnsigned error:%s", buf.Err) + return nil, fmt.Errorf("GetHashData of NeoBlockHeader neo-gogogo block.BlockHeader SerializeUnsigned error: %s", buf.Err) } return buf.Bytes(), nil } @@ -103,7 +103,7 @@ func (this *NeoCrossChainMsg) Deserialization(source *common.ZeroCopySource) err br := io.NewBinaryReaderFromBuf(source.Bytes()) this.Deserialize(br) if br.Err != nil { - return fmt.Errorf("joeqian10/neo-gogogo/mpt.StateRoot Deserialize error:%s", br.Err) + return fmt.Errorf("neo-gogogo mpt.StateRoot Deserialize error: %s", br.Err) } return nil } @@ -112,7 +112,7 @@ func (this *NeoCrossChainMsg) Serialization(sink *common.ZeroCopySink) error { bw := io.NewBufBinaryWriter() this.Serialize(bw.BinaryWriter) if bw.Err != nil { - return fmt.Errorf("joeqian10/neo-gogogo/mpt.StateRoot Serialize error:%s", bw.Err) + return fmt.Errorf("neo-gogogo mpt.StateRoot Serialize error: %s", bw.Err) } sink.WriteBytes(bw.Bytes()) return nil @@ -121,14 +121,14 @@ func (this *NeoCrossChainMsg) Serialization(sink *common.ZeroCopySink) error { func (this *NeoCrossChainMsg) GetScriptHash() (helper.UInt160, error) { verificationScriptBs, err := hex.DecodeString(this.Witness.VerificationScript) if err != nil { - return helper.UInt160{}, fmt.Errorf("NeoCrossChainMsg.Witness.VerificationScript decode to bytes error:%s", err) + return helper.UInt160{}, fmt.Errorf("NeoCrossChainMsg.Witness.VerificationScript decode to bytes error: %s", err) } if len(verificationScriptBs) == 0 { return helper.UInt160{}, fmt.Errorf("NeoCrossChainMsg.Witness.VerificationScript length is 0 ") } scriptHash, err := helper.UInt160FromBytes(crypto.Hash160(verificationScriptBs)) if err != nil { - return helper.UInt160{}, fmt.Errorf("joeqian10/neo-gogogo/tx.Witness GetScriptHash error:%s", err) + return helper.UInt160{}, fmt.Errorf("neo-gogogo tx.Witness GetScriptHash error: %s", err) } return scriptHash, nil } @@ -137,7 +137,7 @@ func (this *NeoCrossChainMsg) GetMessage() ([]byte, error) { buf := io.NewBufBinaryWriter() this.SerializeUnsigned(buf.BinaryWriter) if buf.Err != nil { - return nil, fmt.Errorf("GetHashData of NeoBlockHeader joeqian10/neo-gogogo/mpt.StateRoot SerializeUnsigned error:%s", buf.Err) + return nil, fmt.Errorf("GetHashData of NeoBlockHeader neo-gogogo mpt.StateRoot SerializeUnsigned error: %s", buf.Err) } return buf.Bytes(), nil } diff --git a/native/service/header_sync/neo/states_test.go b/native/service/header_sync/neo/states_test.go index cb6321a45..9223ac7a9 100644 --- a/native/service/header_sync/neo/states_test.go +++ b/native/service/header_sync/neo/states_test.go @@ -66,10 +66,11 @@ func Test_NeoBlockHeader_Serialization(t *testing.T) { } paramSerialize.BlockHeader = genesisHeader sink := common.NewZeroCopySink(nil) - paramSerialize.Serialization(sink) + err := paramSerialize.Serialization(sink) + assert.Nil(t, err) paramDeserialize := new(NeoBlockHeader) - err := paramDeserialize.Deserialization(common.NewZeroCopySource(sink.Bytes())) + err = paramDeserialize.Deserialization(common.NewZeroCopySource(sink.Bytes())) assert.Nil(t, err) assert.Equal(t, paramDeserialize, paramSerialize) } @@ -92,10 +93,11 @@ func Test_NeoCrossChainMsg_Serialization(t *testing.T) { } sink := common.NewZeroCopySink(nil) - paramSerialize.Serialization(sink) + err := paramSerialize.Serialization(sink) + assert.Nil(t, err) paramDeserialize := new(NeoCrossChainMsg) - err := paramDeserialize.Deserialization(common.NewZeroCopySource(sink.Bytes())) + err = paramDeserialize.Deserialization(common.NewZeroCopySource(sink.Bytes())) assert.Nil(t, err) assert.Equal(t, paramDeserialize, paramSerialize) } diff --git a/native/service/header_sync/neo/utils.go b/native/service/header_sync/neo/utils.go index 43be21294..11507b64e 100644 --- a/native/service/header_sync/neo/utils.go +++ b/native/service/header_sync/neo/utils.go @@ -33,10 +33,10 @@ import ( func verifyHeader(native *native.NativeService, chainID uint64, header *NeoBlockHeader) error { neoConsensus, err := getConsensusValByChainId(native, chainID) if err != nil { - return fmt.Errorf("verifyHeader, get Consensus error:%s", err) + return fmt.Errorf("verifyHeader, get Consensus error: %s", err) } if neoConsensus.NextConsensus != header.Witness.GetScriptHash() { - return fmt.Errorf("verifyHeader, invalid script hash in header error, expected:%s, got:%s", neoConsensus.NextConsensus.String(), header.Witness.GetScriptHash().String()) + return fmt.Errorf("verifyHeader, invalid script hash in header error, expected: %s, got: %s", neoConsensus.NextConsensus.String(), header.Witness.GetScriptHash().String()) } msg, err := header.GetMessage() @@ -44,7 +44,7 @@ func verifyHeader(native *native.NativeService, chainID uint64, header *NeoBlock return fmt.Errorf("verifyHeader, unable to get hash data of header") } if verified := tx.VerifyMultiSignatureWitness(msg, header.Witness); !verified { - return fmt.Errorf("verifyHeader, VerifyMultiSignatureWitness error:%s, height:%d", err, header.Index) + return fmt.Errorf("verifyHeader, VerifyMultiSignatureWitness error: %s, height: %d", err, header.Index) } return nil } @@ -52,14 +52,14 @@ func verifyHeader(native *native.NativeService, chainID uint64, header *NeoBlock func VerifyCrossChainMsgSig(native *native.NativeService, chainID uint64, crossChainMsg *NeoCrossChainMsg) error { neoConsensus, err := getConsensusValByChainId(native, chainID) if err != nil { - return fmt.Errorf("verifyCrossChainMsg, get ConsensusPeer error:%v", err) + return fmt.Errorf("verifyCrossChainMsg, get ConsensusPeer error: %v", err) } crossChainMsgConsensus, err := crossChainMsg.GetScriptHash() if err != nil { - return fmt.Errorf("verifyCrossChainMsg, getScripthash error:%v", err) + return fmt.Errorf("verifyCrossChainMsg, getScripthash error: %v", err) } if neoConsensus.NextConsensus != crossChainMsgConsensus { - return fmt.Errorf("verifyCrossChainMsg, invalid script hash in NeoCrossChainMsg error, expected:%s, got:%s", neoConsensus.NextConsensus.String(), crossChainMsgConsensus.String()) + return fmt.Errorf("verifyCrossChainMsg, invalid script hash in NeoCrossChainMsg error, expected: %s, got: %s", neoConsensus.NextConsensus.String(), crossChainMsgConsensus.String()) } msg, err := crossChainMsg.GetMessage() if err != nil { @@ -72,7 +72,7 @@ func VerifyCrossChainMsgSig(native *native.NativeService, chainID uint64, crossC VerificationScript: verScript, } if verified := tx.VerifyMultiSignatureWitness(msg, witness); !verified { - return fmt.Errorf("verifyCrossChainMsg, VerifyMultiSignatureWitness error:%s, height:%d", "verified failed", crossChainMsg.Index) + return fmt.Errorf("verifyCrossChainMsg, VerifyMultiSignatureWitness error: %s, height: %d", "verification failed", crossChainMsg.Index) } return nil } @@ -89,7 +89,7 @@ func getConsensusValByChainId(native *native.NativeService, chainID uint64) (*Ne } neoConsensusBytes, err := cstates.GetValueFromRawStorageItem(neoConsensusStore) if err != nil { - return nil, fmt.Errorf("getConsensusPeerByHeight, deserialize from raw storage item err:%v", err) + return nil, fmt.Errorf("getConsensusPeerByHeight, deserialize from raw storage item err: %v", err) } neoConsensus := new(NeoConsensus) if err := neoConsensus.Deserialization(common.NewZeroCopySource(neoConsensusBytes)); err != nil { diff --git a/native/service/header_sync/neo3/header_sync.go b/native/service/header_sync/neo3/header_sync.go new file mode 100644 index 000000000..739a03d1b --- /dev/null +++ b/native/service/header_sync/neo3/header_sync.go @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package neo3 + +import ( + "fmt" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/service/governance/node_manager" + hscommon "github.com/polynetwork/poly/native/service/header_sync/common" + + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/native/service/utils" +) + +type Neo3Handler struct { +} + +func NewNeo3Handler() *Neo3Handler { + return &Neo3Handler{} +} + +func (this *Neo3Handler) SyncGenesisHeader(native *native.NativeService) error { + params := new(hscommon.SyncGenesisHeaderParam) + if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return fmt.Errorf("Neo3Handler SyncGenesisHeader, contract params deserialize error: %v", err) + } + // Get current epoch operator + operatorAddress, err := node_manager.GetCurConOperator(native) + if err != nil { + return fmt.Errorf("Neo3Handler SyncGenesisHeader, get current consensus operator address error: %v", err) + } + //check witness + err = utils.ValidateOwner(native, operatorAddress) + if err != nil { + return fmt.Errorf("Neo3Handler SyncGenesisHeader, checkWitness error: %v", err) + } + // Deserialize neo block header + + header := new(NeoBlockHeader) + if err := header.Deserialization(common.NewZeroCopySource(params.GenesisHeader)); err != nil { + return fmt.Errorf("Neo3Handler SyncGenesisHeader, deserialize header err: %v", err) + } + + if neoConsensus, _ := getConsensusValByChainId(native, params.ChainID); neoConsensus == nil { + // Put NeoConsensus.NextConsensus into storage + if err = putConsensusValByChainId(native, &NeoConsensus{ + ChainID: params.ChainID, + Height: header.GetIndex(), + NextConsensus: header.GetNextConsensus(), + }); err != nil { + return fmt.Errorf("Neo3Handler SyncGenesisHeader, update ConsensusPeer error: %v", err) + } + } + return nil +} + +func (this *Neo3Handler) SyncBlockHeader(native *native.NativeService) error { + params := new(hscommon.SyncBlockHeaderParam) + if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { + return fmt.Errorf("Neo3Handler SyncBlockHeader, contract params deserialize error: %v", err) + } + neoConsensus, err := getConsensusValByChainId(native, params.ChainID) + if err != nil { + return fmt.Errorf("Neo3Handler SyncBlockHeader, the consensus validator has not been initialized, chainId: %d", params.ChainID) + } + var newNeoConsensus *NeoConsensus + for _, v := range params.Headers { + header := new(NeoBlockHeader) + if err := header.Deserialization(common.NewZeroCopySource(v)); err != nil { + return fmt.Errorf("Neo3Handler SyncBlockHeader, NeoBlockHeaderFromBytes error: %v", err) + } + if !header.GetNextConsensus().Equals(neoConsensus.NextConsensus) && header.GetIndex() > neoConsensus.Height { + if err = verifyHeader(native, params.ChainID, header); err != nil { + return fmt.Errorf("Neo3Handler SyncBlockHeader, verifyHeader error: %v", err) + } + newNeoConsensus = &NeoConsensus{ + ChainID: neoConsensus.ChainID, + Height: header.GetIndex(), + NextConsensus: header.GetNextConsensus(), + } + } + } + if newNeoConsensus != nil { + if err = putConsensusValByChainId(native, newNeoConsensus); err != nil { + return fmt.Errorf("Neo3Handler SyncBlockHeader, update ConsensusPeer error: %v", err) + } + } + return nil +} + +func (this *Neo3Handler) SyncCrossChainMsg(native *native.NativeService) error { + return nil +} diff --git a/native/service/header_sync/neo3/header_sync_test.go b/native/service/header_sync/neo3/header_sync_test.go new file mode 100644 index 000000000..7f89611b8 --- /dev/null +++ b/native/service/header_sync/neo3/header_sync_test.go @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package neo3 + +import ( + "github.com/joeqian10/neo3-gogogo/block" + "github.com/joeqian10/neo3-gogogo/crypto" + "github.com/joeqian10/neo3-gogogo/helper" + tx2 "github.com/joeqian10/neo3-gogogo/tx" + "github.com/ontio/ontology-crypto/keypair" + "github.com/polynetwork/poly/account" + "github.com/polynetwork/poly/common" + "github.com/polynetwork/poly/core/genesis" + "github.com/polynetwork/poly/core/store/leveldbstore" + "github.com/polynetwork/poly/core/store/overlaydb" + "github.com/polynetwork/poly/core/types" + "github.com/polynetwork/poly/native" + scom "github.com/polynetwork/poly/native/service/header_sync/common" + "github.com/polynetwork/poly/native/storage" + "github.com/stretchr/testify/assert" + "testing" +) + +var ( + //neoAcct = func() *wallet.Account { + // acct, _ := wallet.NewAccount() + // return acct + //}() + acct *account.Account = account.NewAccount("") + getNativeFunc = func() *native.NativeService { + store, _ := leveldbstore.NewMemLevelDBStore() + cacheDB := storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + service, _ := native.NewNativeService(cacheDB, new(types.Transaction), 0, 200, common.Uint256{}, 0, nil, false) + return service + } + getNeoHanderFunc = func() *Neo3Handler { + return NewNeo3Handler() + } + setBKers = func() { + genesis.GenesisBookkeepers = []keypair.PublicKey{acct.PublicKey} + } +) + +func init() { + setBKers() +} + +func NewNative(args []byte, tx *types.Transaction, db *storage.CacheDB) *native.NativeService { + if db == nil { + store, _ := leveldbstore.NewMemLevelDBStore() + db = storage.NewCacheDB(overlaydb.NewOverlayDB(store)) + } + ns, _ := native.NewNativeService(db, tx, 0, 0, common.Uint256{0}, 0, args, false) + return ns +} + +func TestSyncGenesisHeader(t *testing.T) { + prevHash, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + merkleRoot, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + nextConsensus, _ := crypto.AddressToScriptHash("NVg7LjGcUSrgxgjX3zEgqaksfMaiS8Z6e1", helper.DefaultAddressVersion) + vs, _ := crypto.Base64Decode("EQ==") + witness := tx2.Witness{ + InvocationScript: []byte{}, + VerificationScript: vs, + } + genesisHeader := &NeoBlockHeader{Header: block.NewBlockHeader()} + genesisHeader.SetVersion(0) + genesisHeader.SetPrevHash(prevHash) + genesisHeader.SetMerkleRoot(merkleRoot) + genesisHeader.SetTimeStamp(1468595301000) + genesisHeader.SetIndex(0) + genesisHeader.SetPrimaryIndex(0x00) + genesisHeader.SetNextConsensus(nextConsensus) + genesisHeader.SetWitnesses([]tx2.Witness{witness}) + + param := new(scom.SyncGenesisHeaderParam) + param.ChainID = 4 + sink := common.NewZeroCopySink(nil) + err := genesisHeader.Serialization(sink) + param.GenesisHeader = sink.Bytes() + assert.Nil(t, err) + + sink = common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + //cdb := new(storage.CacheDB) + //cdb.Put() + native := NewNative(sink.Bytes(), tx, nil) + neoHandler := NewNeo3Handler() + err = neoHandler.SyncGenesisHeader(native) + assert.NoError(t, err) +} + +func TestSyncBlockHeader(t *testing.T) { + prevHash, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + merkleRoot, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + nextConsensus, _ := crypto.AddressToScriptHash("NVg7LjGcUSrgxgjX3zEgqaksfMaiS8Z6e1", helper.DefaultAddressVersion) + is := []byte{} + vs, _ := crypto.Base64Decode("EQ==") + witness := tx2.Witness{ + InvocationScript: is, + VerificationScript: vs, + } + genesisHeader := &NeoBlockHeader{Header: block.NewBlockHeader()} + genesisHeader.SetVersion(0) + genesisHeader.SetPrevHash(prevHash) + genesisHeader.SetMerkleRoot(merkleRoot) + genesisHeader.SetTimeStamp(1468595301000) + genesisHeader.SetIndex(0) + genesisHeader.SetPrimaryIndex(0x00) + genesisHeader.SetNextConsensus(nextConsensus) + genesisHeader.SetWitnesses([]tx2.Witness{witness}) + sink := common.NewZeroCopySink(nil) + if err := genesisHeader.Serialization(sink); err != nil { + t.Errorf("NeoBlockHeaderToBytes error:%v", err) + } + neoGenesisHeaderbs := sink.Bytes() + // block 100 + prevHash, _ = helper.UInt256FromString("0xcee650e843a8f8cf78f7c62a2bc2108375df93bfa9a912de64bea2d8948fec31") + merkleRoot, _ = helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + nextConsensus, _ = crypto.AddressToScriptHash("NYmMriQPYAiNxHC7tziV4ABJku5Yqe79N4", helper.DefaultAddressVersion) + is, _ = crypto.Base64Decode("DEAF2siXzBq5rCzpaNvAxTPuebSgsn3XX7bKMvuf1RzQx1QqJDLBn/XxMyCzAOnsolp67X8eLZ8xuc4bovqSMf4lDECxfs8iV5/5yLs2hVW0tB1d1n7R1J3HEoJ8vNCJr/xrqt3bJRoOFL+eObBmjyo+ZSk5M6GrGH+UqpglZqr0upu8DEAX9lh0LKdbFTOg5GfZ8gP9UdGURu/xbM288BKFUBXhTH1p/2Y4hqZzJoXes+DdlRCwWzhToCMa468OnmTHkxDoDEB4etR6RX+B69qB5cv7QjihqnTowYWzU3Zhec+yz+2wgETkD0aD4uUafiSGpCK7xNB7aknDbFgMJXWSK7cM+c3NDEDw4z4PxskKUfJ1cmXKXxhtdzo/05iEi6c/n2rfZHPLd/YA0aBPQuWf3QSWizQYsmsYyA2uriKR2PA7asqYYB60") + vs, _ = crypto.Base64Decode("FQwhAwCbdUDhDyVi5f2PrJ6uwlFmpYsm5BI0j/WoaSe/rCKiDCEDAgXpzvrqWh38WAryDI1aokaLsBSPGl5GBfxiLIDmBLoMIQIUuvDO6jpm8X5+HoOeol/YvtbNgua7bmglAYkGX0T/AQwhAj6bMuqJuU0GbmSbEk/VDjlu6RNp6OKmrhsRwXDQIiVtDCEDQI3NQWOW9keDrFh+oeFZPFfZ/qiAyKahkg6SollHeAYMIQKng0vpsy4pgdFXy1u9OstCz9EepcOxAiTXpE6YxZEPGwwhAroscPWZbzV6QxmHBYWfriz+oT4RcpYoAHcrPViKnUq9F0F7zmyl") + witness = tx2.Witness{ + InvocationScript: is, + VerificationScript: vs, + } + neoHeader100 := &NeoBlockHeader{Header: block.NewBlockHeader()} + neoHeader100.SetVersion(0) + neoHeader100.SetPrevHash(prevHash) + neoHeader100.SetMerkleRoot(merkleRoot) + neoHeader100.SetTimeStamp(1616577294488) + neoHeader100.SetIndex(100) + neoHeader100.SetPrimaryIndex(0x00) + neoHeader100.SetNextConsensus(nextConsensus) + neoHeader100.SetWitnesses([]tx2.Witness{witness}) + sink = common.NewZeroCopySink(nil) + if err := neoHeader100.Serialization(sink); err != nil { + t.Errorf("NeoBlockHeaderToBytes error:%v", err) + } + neoHeader100bs := sink.Bytes() + + // block 200 + prevHash, _ = helper.UInt256FromString("0xe22cd5bb35d832e59554dc2d4165a48bed56b2d7f9df379639078cca35ecc770") + merkleRoot, _ = helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + nextConsensus, _ = crypto.AddressToScriptHash("NYmMriQPYAiNxHC7tziV4ABJku5Yqe79N4", helper.DefaultAddressVersion) + is, _ = crypto.Base64Decode("DEBGAk7oudrv67j+GFWetgK8W0Hu6m/15ceMxaq3sl6aKfjTQckmQfqzzGgzJ/rrdWMCyCsjYkgc14MdFvI/GnopDEBj9dRQtcKyu9K2qOyvqqkUoqK/9A32kdj0LbXpYPw+WDrz0DlvjNQF8dc2EuvmwTrYuQ5fUTrHvaPXKTmOPl3IDEAKtZf8AaZmY+onQejV8jqkEN5DGKKWthYGpVza5jueTvx4Hi1B5Uh7k6jW5Z6Y7mUVGuIUAGLbeULsp/MAQiyjDEBibp/Gy0rg5h1Hm3TokJi12KfYSMizn973+rkMDjKiWW1ySq6Sif3BEqlHi1prbuFPYSQf7xiJgs3+P0aFXfPzDEBdqKNocAkjWPBbxrHCHq0DRJoXBgmrXA9BSmytymp/pdU4xt2Y/Gxb/GBBXOAorOumjZ46DxWwnqfVpJ9adHMj") + vs, _ = crypto.Base64Decode("FQwhAwCbdUDhDyVi5f2PrJ6uwlFmpYsm5BI0j/WoaSe/rCKiDCEDAgXpzvrqWh38WAryDI1aokaLsBSPGl5GBfxiLIDmBLoMIQIUuvDO6jpm8X5+HoOeol/YvtbNgua7bmglAYkGX0T/AQwhAj6bMuqJuU0GbmSbEk/VDjlu6RNp6OKmrhsRwXDQIiVtDCEDQI3NQWOW9keDrFh+oeFZPFfZ/qiAyKahkg6SollHeAYMIQKng0vpsy4pgdFXy1u9OstCz9EepcOxAiTXpE6YxZEPGwwhAroscPWZbzV6QxmHBYWfriz+oT4RcpYoAHcrPViKnUq9F0F7zmyl") + witness = tx2.Witness{ + InvocationScript: is, + VerificationScript: vs, + } + neoHeader200 := &NeoBlockHeader{Header: block.NewBlockHeader()} + neoHeader200.SetVersion(0) + neoHeader200.SetPrevHash(prevHash) + neoHeader200.SetMerkleRoot(merkleRoot) + neoHeader200.SetTimeStamp(1616578903762) + neoHeader200.SetIndex(200) + neoHeader200.SetPrimaryIndex(0x00) + neoHeader200.SetNextConsensus(nextConsensus) + neoHeader200.SetWitnesses([]tx2.Witness{witness}) + sink = common.NewZeroCopySink(nil) + if err := neoHeader200.Serialization(sink); err != nil { + t.Errorf("NeoBlockHeaderToBytes error:%v", err) + } + neoHeader200bs := sink.Bytes() + + neoHandler := NewNeo3Handler() + var native *native.NativeService + { + param := new(scom.SyncGenesisHeaderParam) + param.ChainID = 4 + param.GenesisHeader = neoGenesisHeaderbs + sink := common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + + native = NewNative(sink.Bytes(), tx, nil) + err := neoHandler.SyncGenesisHeader(native) + assert.NoError(t, err) + } + + { + param := new(scom.SyncBlockHeaderParam) + param.ChainID = 4 + param.Address = acct.Address + param.Headers = append(param.Headers, neoHeader100bs) + param.Headers = append(param.Headers, neoHeader200bs) + sink := common.NewZeroCopySink(nil) + param.Serialization(sink) + + tx := &types.Transaction{ + SignedAddr: []common.Address{acct.Address}, + } + + native = NewNative(sink.Bytes(), tx, native.GetCacheDB()) + err := neoHandler.SyncBlockHeader(native) + assert.NoError(t, err) + } +} diff --git a/native/service/header_sync/neo3/states.go b/native/service/header_sync/neo3/states.go new file mode 100644 index 000000000..d606f4a9e --- /dev/null +++ b/native/service/header_sync/neo3/states.go @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package neo3 + +import ( + "fmt" + "github.com/joeqian10/neo3-gogogo/block" + "github.com/joeqian10/neo3-gogogo/crypto" + "github.com/joeqian10/neo3-gogogo/helper" + "github.com/joeqian10/neo3-gogogo/io" + "github.com/joeqian10/neo3-gogogo/mpt" + "github.com/polynetwork/poly/common" +) + +type NeoConsensus struct { + ChainID uint64 + Height uint32 + NextConsensus *helper.UInt160 +} + +func (this *NeoConsensus) Serialization(sink *common.ZeroCopySink) { + sink.WriteUint64(this.ChainID) + sink.WriteUint32(this.Height) + sink.WriteVarBytes(this.NextConsensus.ToByteArray()) +} + +func (this *NeoConsensus) Deserialization(source *common.ZeroCopySource) error { + var eof bool + if this.ChainID, eof = source.NextUint64(); eof { + return fmt.Errorf("NeoConsensus.Deserialization, ChainID NextUint64 error") + } + if this.Height, eof = source.NextUint32(); eof { + return fmt.Errorf("NeoConsensus.Deserialization, Height NextUint32 error") + } + + nextConsensusBs, eof := source.NextVarBytes() + if eof { + return fmt.Errorf("NeoConsensus.Deserialization, NextConsensus NextVarBytes error") + } + + this.NextConsensus = helper.UInt160FromBytes(nextConsensusBs); + return nil +} + +type NeoBlockHeader struct { + *block.Header +} + +func (this *NeoBlockHeader) Deserialization(source *common.ZeroCopySource) error { + this.Header = block.NewBlockHeader() + br := io.NewBinaryReaderFromBuf(source.Bytes()) + this.Header.Deserialize(br) + if br.Err != nil { + return fmt.Errorf("neo3-gogogo Header Deserialize error: %s", br.Err) + } + return nil +} + +func (this *NeoBlockHeader) Serialization(sink *common.ZeroCopySink) error { + bw := io.NewBufBinaryWriter() + this.Serialize(bw.BinaryWriter) + if bw.Err != nil { + return fmt.Errorf("neo3-gogogo Header Serialize error: %s", bw.Err) + } + sink.WriteBytes(bw.Bytes()) + return nil +} + +func (this *NeoBlockHeader) GetMessage() ([]byte, error) { + buf := io.NewBufBinaryWriter() + this.SerializeUnsigned(buf.BinaryWriter) + if buf.Err != nil { + return nil, fmt.Errorf("neo3-gogogo Header SerializeUnsigned error: %s", buf.Err) + } + return buf.Bytes(), nil +} + +type NeoCrossChainMsg struct { + *mpt.StateRoot +} + +func (this *NeoCrossChainMsg) Deserialization(source *common.ZeroCopySource) error { + this.StateRoot = new(mpt.StateRoot) + br := io.NewBinaryReaderFromBuf(source.Bytes()) + this.Deserialize(br) + if br.Err != nil { + return fmt.Errorf("neo3-gogogo mpt.StateRoot Deserialize error: %s", br.Err) + } + return nil +} + +func (this *NeoCrossChainMsg) Serialization(sink *common.ZeroCopySink) error { + bw := io.NewBufBinaryWriter() + this.Serialize(bw.BinaryWriter) + if bw.Err != nil { + return fmt.Errorf("neo3-gogogo mpt.StateRoot Serialize error: %s", bw.Err) + } + sink.WriteBytes(bw.Bytes()) + return nil +} + +func (this *NeoCrossChainMsg) GetScriptHash() (*helper.UInt160, error) { + if len(this.Witnesses) == 0 { + return nil, fmt.Errorf("NeoCrossChainMsg.Witness incorrect length") + } + verificationScriptBs, err := crypto.Base64Decode(this.Witnesses[0].Verification) // base64 + if err != nil { + return nil, fmt.Errorf("NeoCrossChainMsg.Witness.Verification decode error: %s", err) + } + if len(verificationScriptBs) == 0 { + return nil, fmt.Errorf("NeoCrossChainMsg.Witness.VerificationScript is empty") + } + scriptHash := helper.UInt160FromBytes(crypto.Hash160(verificationScriptBs)) + return scriptHash, nil +} + +func (this *NeoCrossChainMsg) GetMessage(magic uint32) ([]byte, error) { + buff2 := io.NewBufBinaryWriter() + this.SerializeUnsigned(buff2.BinaryWriter) + if buff2.Err != nil { + return nil, fmt.Errorf("neo3-gogogo mpt.StateRoot SerializeUnsigned error: %s", buff2.Err) + } + hash := helper.UInt256FromBytes(crypto.Sha256(buff2.Bytes())) + + buf := io.NewBufBinaryWriter() + buf.BinaryWriter.WriteLE(magic) + buf.BinaryWriter.WriteLE(hash) + if buf.Err != nil { + return nil, fmt.Errorf("write hash error: %s", buf.Err) + } + return buf.Bytes(), nil +} diff --git a/native/service/header_sync/neo3/states_test.go b/native/service/header_sync/neo3/states_test.go new file mode 100644 index 000000000..37953712e --- /dev/null +++ b/native/service/header_sync/neo3/states_test.go @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package neo3 + +import ( + "github.com/joeqian10/neo3-gogogo/block" + "github.com/joeqian10/neo3-gogogo/crypto" + "github.com/joeqian10/neo3-gogogo/rpc/models" + "log" + "testing" + + "github.com/joeqian10/neo3-gogogo/helper" + "github.com/joeqian10/neo3-gogogo/mpt" + tx2 "github.com/joeqian10/neo3-gogogo/tx" + "github.com/polynetwork/poly/common" + "github.com/stretchr/testify/assert" +) + +func Test_NeoConsensus_Serialization(t *testing.T) { + nextConsensus, _ := crypto.AddressToScriptHash("NYmMriQPYAiNxHC7tziV4ABJku5Yqe79N4", helper.DefaultAddressVersion) + paramSerialize := &NeoConsensus{ + ChainID: 4, + Height: 100, + NextConsensus: nextConsensus, + } + sink := common.NewZeroCopySink(nil) + paramSerialize.Serialization(sink) + + paramDeserialize := new(NeoConsensus) + err := paramDeserialize.Deserialization(common.NewZeroCopySource(sink.Bytes())) + assert.Nil(t, err) + assert.Equal(t, paramDeserialize, paramSerialize) +} + +func Test_NeoBlockHeader_Serialization(t *testing.T) { + prevHash, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + merkleRoot, _ := helper.UInt256FromString("0x0000000000000000000000000000000000000000000000000000000000000000") + nextConsensus, _ := crypto.AddressToScriptHash("NVg7LjGcUSrgxgjX3zEgqaksfMaiS8Z6e1", helper.DefaultAddressVersion) + //vs, _ := crypto.Base64Decode("EQ==") + witness := tx2.Witness{ + InvocationScript: []byte{}, + VerificationScript: []byte{}, + } + genesisHeader := block.NewBlockHeader() + genesisHeader.SetVersion(0) + genesisHeader.SetPrevHash(prevHash) + genesisHeader.SetMerkleRoot(merkleRoot) + genesisHeader.SetTimeStamp(1468595301000) + genesisHeader.SetIndex(0) + genesisHeader.SetPrimaryIndex(0x00) + genesisHeader.SetNextConsensus(nextConsensus) + genesisHeader.SetWitnesses([]tx2.Witness{witness}) + paramSerialize := new(NeoBlockHeader) + paramSerialize.Header = genesisHeader + sink := common.NewZeroCopySink(nil) + err := paramSerialize.Serialization(sink) + assert.Nil(t, err) + + log.Println(helper.BytesToHex(sink.Bytes())) + + paramDeserialize := new(NeoBlockHeader) + err = paramDeserialize.Deserialization(common.NewZeroCopySource(sink.Bytes())) + assert.Nil(t, err) + assert.Equal(t, paramDeserialize, paramSerialize) +} + +func Test_NeoCrossChainMsg_Serialization(t *testing.T) { + paramSerialize := &NeoCrossChainMsg{ + StateRoot: &mpt.StateRoot{ + Version: 0, + Index: 1000, + RootHash: "0x53360e02b03f548c6fc2f74f760d82a6749df6a844fd117ad7b62504390c8f8c", + Witness: models.RpcWitness { + Invocation: "DEBnIRHFS8tG/6pw4cqZQbOQZri6rboaQPUJTCVS2ZD/HwOZG2m9IG3NJ8E/gTV++o7G1r35l+p5aQcAbqwoP1wTDECeyQcx2M1DP/irLP7sQy/tNRyina2rdK6ATV/QY+Ib4tJ3sYpXaiPx4iGo+AgqUeTRDmD8anfUNtYzjYgos6x9DEDS+medyKx59813WgtCusxLIK0tx50H36tbMGmTUQxR5nHzrpG8nzQ8HKNKRNMgQNBoT4U3pcHMpwJY9bXUge4R", + Verification: "EwwhAnIujtkuXxpCUIyfti3TyTtoOhUd/wjLU4lwdHzBhsu6DCECkeyvwoMh29AA30IiQMankxndS3LESLsUGkLoTzfm/doMIQOyS9DtdzAVHs/Ne1yheExdO8NYTw1NkKyi1i4gd5tG1wwhA/sZ1ZOuaNWI9PnKa/3WYbE9xjnVVYWhVYYXFD38xLJWFEF7zmyl", + }, + }, + } + + sink := common.NewZeroCopySink(nil) + err := paramSerialize.Serialization(sink) + assert.Nil(t, err) + + paramDeserialize := new(NeoCrossChainMsg) + err = paramDeserialize.Deserialization(common.NewZeroCopySource(sink.Bytes())) + assert.Nil(t, err) + assert.Equal(t, paramDeserialize, paramSerialize) +} diff --git a/native/service/header_sync/neo3/utils.go b/native/service/header_sync/neo3/utils.go new file mode 100644 index 000000000..c9c3231b7 --- /dev/null +++ b/native/service/header_sync/neo3/utils.go @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2020 The poly network Authors + * This file is part of The poly network library. + * + * The poly network is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The poly network is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * You should have received a copy of the GNU Lesser General Public License + * along with The poly network . If not, see . + */ + +package neo3 + +import ( + "fmt" + "github.com/joeqian10/neo3-gogogo/crypto" + "github.com/joeqian10/neo3-gogogo/sc" + "github.com/joeqian10/neo3-gogogo/tx" + "github.com/polynetwork/poly/common" + cstates "github.com/polynetwork/poly/core/states" + "github.com/polynetwork/poly/native" + "github.com/polynetwork/poly/native/service/governance/neo3_state_manager" + hscommon "github.com/polynetwork/poly/native/service/header_sync/common" + "github.com/polynetwork/poly/native/service/utils" +) + +//verify header of any height +//find key height and get neoconsensus first, then check the witness +func verifyHeader(native *native.NativeService, chainID uint64, header *NeoBlockHeader) error { + neoConsensus, err := getConsensusValByChainId(native, chainID) + if err != nil { + return fmt.Errorf("verifyHeader, get Consensus error: %s", err) + } + if neoConsensus.NextConsensus != header.Witness.GetScriptHash() { + return fmt.Errorf("verifyHeader, invalid script hash in header error, expected: %s, got: %s", neoConsensus.NextConsensus.String(), header.Witness.GetScriptHash().String()) + } + + msg, err := header.GetMessage() + if err != nil { + return fmt.Errorf("verifyHeader, unable to get hash data of header") + } + if verified := tx.VerifyMultiSignatureWitness(msg, header.Witness); !verified { + return fmt.Errorf("verifyHeader, VerifyMultiSignatureWitness error: %s, height: %d", err, header.GetIndex()) + } + return nil +} + +func VerifyCrossChainMsgSig(native *native.NativeService, magic uint32, crossChainMsg *NeoCrossChainMsg) error { + // get neo3 state validator from native contract + svListBytes, err := neo3_state_manager.GetCurrentStateValidator(native) + if err != nil { + return fmt.Errorf("verifyCrossChainMsg, neo3_state_manager.GetCurrentStateValidator error: %v", err) + } + svStrings, err := neo3_state_manager.DeserializeStringArray(svListBytes) + if err != nil { + return fmt.Errorf("verifyCrossChainMsg, neo3_state_manager.DeserializeStringArray error: %v", err) + } + pubKeys := make([]crypto.ECPoint, len(svStrings), len(svStrings)) + for i, v := range svStrings { + pubKey, err := crypto.NewECPointFromString(v) + if err != nil { + return fmt.Errorf("verifyCrossChainMsg, crypto.NewECPointFromString error: %v", err) + } + pubKeys[i] = *pubKey + } + n := len(pubKeys) + m := n - (n-1)/3 + msc, err := sc.CreateMultiSigContract(m, pubKeys) // sort public keys inside + if err != nil { + return fmt.Errorf("verifyCrossChainMsg, sc.CreateMultiSigContract error: %v", err) + } + expected := msc.GetScriptHash() + got, err := crossChainMsg.GetScriptHash() + if err != nil { + return fmt.Errorf("verifyCrossChainMsg, getScripthash error: %v", err) + } + // compare state validator + if !expected.Equals(got) { + return fmt.Errorf("verifyCrossChainMsg, invalid script hash in NeoCrossChainMsg error, expected: %s, got: %s", expected.String(), got.String()) + } + msg, err := crossChainMsg.GetMessage(magic) + if err != nil { + return fmt.Errorf("verifyCrossChainMsg, unable to get unsigned message of neo crossChainMsg") + } + if len(crossChainMsg.Witnesses) == 0 { + return fmt.Errorf("verifyCrossChainMsg, incorrect witness length") + } + invScript, err := crypto.Base64Decode(crossChainMsg.Witnesses[0].Invocation) + if err != nil { + return fmt.Errorf("crypto.Base64Decode, decode invocation script error: %v", err) + } + verScript, err := crypto.Base64Decode(crossChainMsg.Witnesses[0].Verification) + if err != nil { + return fmt.Errorf("crypto.Base64Decode, decode verification script error: %v", err) + } + witness := &tx.Witness{ + InvocationScript: invScript, + VerificationScript: verScript, + } + v1 := tx.VerifyMultiSignatureWitness(msg, witness) + v2 := tx.VerifySignatureWitness(msg, witness) + if !v1 && !v2 { + return fmt.Errorf("verifyCrossChainMsg, verify witness failed, height: %d", crossChainMsg.Index) + } + return nil +} + +func getConsensusValByChainId(native *native.NativeService, chainID uint64) (*NeoConsensus, error) { + contract := utils.HeaderSyncContractAddress + chainIDBytes := utils.GetUint64Bytes(chainID) + neoConsensusStore, err := native.GetCacheDB().Get(utils.ConcatKey(contract, []byte(hscommon.CONSENSUS_PEER), chainIDBytes)) + if err != nil { + return nil, fmt.Errorf("getNextConsensusByHeight, get nextConsensusStore error: %v", err) + } + if neoConsensusStore == nil { + return nil, fmt.Errorf("getNextConsensusByHeight, can not find any record") + } + neoConsensusBytes, err := cstates.GetValueFromRawStorageItem(neoConsensusStore) + if err != nil { + return nil, fmt.Errorf("getConsensusPeerByHeight, deserialize from raw storage item err: %v", err) + } + neoConsensus := new(NeoConsensus) + if err := neoConsensus.Deserialization(common.NewZeroCopySource(neoConsensusBytes)); err != nil { + return nil, fmt.Errorf("getConsensusPeerByHeight, deserialize consensusPeer error: %v", err) + } + return neoConsensus, nil +} + +func putConsensusValByChainId(native *native.NativeService, neoConsensus *NeoConsensus) error { + contract := utils.HeaderSyncContractAddress + sink := common.NewZeroCopySink(nil) + neoConsensus.Serialization(sink) + chainIDBytes := utils.GetUint64Bytes(neoConsensus.ChainID) + native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(hscommon.CONSENSUS_PEER), chainIDBytes), cstates.GenRawStorageItem(sink.Bytes())) + return nil +} diff --git a/native/service/init.go b/native/service/init.go index 486414a18..5a55238ef 100644 --- a/native/service/init.go +++ b/native/service/init.go @@ -21,6 +21,7 @@ import ( "github.com/polynetwork/poly/common/config" "github.com/polynetwork/poly/native" "github.com/polynetwork/poly/native/service/cross_chain_manager" + "github.com/polynetwork/poly/native/service/governance/neo3_state_manager" "github.com/polynetwork/poly/native/service/governance/node_manager" "github.com/polynetwork/poly/native/service/governance/relayer_manager" "github.com/polynetwork/poly/native/service/governance/side_chain_manager" @@ -34,6 +35,7 @@ func init() { native.Contracts[utils.CrossChainManagerContractAddress] = cross_chain_manager.RegisterCrossChainManagerContract native.Contracts[utils.NodeManagerContractAddress] = node_manager.RegisterNodeManagerContract native.Contracts[utils.RelayerManagerContractAddress] = relayer_manager.RegisterRelayerManagerContract + native.Contracts[utils.Neo3StateManagerContractAddress] = neo3_state_manager.RegisterStateValidatorManagerContract config.EXTRA_INFO_HEIGHT_FORK_CHECK = true } diff --git a/native/service/utils/params.go b/native/service/utils/params.go index 605234a8b..962503ea9 100644 --- a/native/service/utils/params.go +++ b/native/service/utils/params.go @@ -37,6 +37,7 @@ var ( SideChainManagerContractAddress, _ = common.AddressParseFromBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}) NodeManagerContractAddress, _ = common.AddressParseFromBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}) RelayerManagerContractAddress, _ = common.AddressParseFromBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06}) + Neo3StateManagerContractAddress, _ = common.AddressParseFromBytes([]byte{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07}) BTC_ROUTER = uint64(1) ETH_ROUTER = uint64(2) @@ -48,5 +49,7 @@ var ( QUORUM_ROUTER = uint64(8) ZILLIQA_ROUTER = uint64(9) MSC_ROUTER = uint64(10) + NEO3_ROUTER = uint64(11) OKEX_ROUTER = uint64(12) + KAI_ROUTER = uint64(13) )