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)
)