feat(*): add governance module
1.Add governance built-in contract; 2.Add governance related tests.
This commit is contained in:
parent
917186f216
commit
2902f16647
|
@ -18,7 +18,12 @@ func GetChainStatus(cbs *ChainBrokerService) (*pb.Response, error) {
|
|||
}
|
||||
|
||||
func GetValidators(cbs *ChainBrokerService) (*pb.Response, error) {
|
||||
addresses := cbs.genesis.Addresses
|
||||
admins := cbs.genesis.Admins
|
||||
addresses := make([]string, 0)
|
||||
for _, admin := range admins {
|
||||
addresses = append(addresses, admin.Address)
|
||||
}
|
||||
|
||||
v, err := json.Marshal(addresses)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -61,9 +61,20 @@ solo = false
|
|||
type = "serial" # opensource version only supports serial type, commercial version supports serial and parallel types
|
||||
|
||||
[genesis]
|
||||
addresses = [
|
||||
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
|
||||
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
]
|
||||
[[genesis.admins]]
|
||||
address = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
weight = 1
|
||||
[genesis.strategy]
|
||||
AppchainMgr = "SimpleMajority"
|
||||
RuleMgr = "SimpleMajority"
|
||||
NodeMgr = "SimpleMajority"
|
||||
ServiceMgr = "SimpleMajority"
|
13
go.mod
13
go.mod
|
@ -4,16 +4,18 @@ require (
|
|||
github.com/Rican7/retry v0.1.0
|
||||
github.com/aristanetworks/goarista v0.0.0-20200310212843-2da4c1f5881b // indirect
|
||||
github.com/cbergoon/merkletree v0.2.0
|
||||
github.com/cheynewallace/tabby v1.1.1
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20190529165535-67e0ed34491a
|
||||
github.com/coreos/etcd v3.3.18+incompatible
|
||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
|
||||
github.com/ethereum/go-ethereum v1.9.18
|
||||
github.com/fatih/color v1.7.0
|
||||
github.com/gobuffalo/envy v1.9.0 // indirect
|
||||
github.com/gobuffalo/packd v1.0.0
|
||||
github.com/gobuffalo/packr v1.30.1
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/mock v1.4.4
|
||||
github.com/golang/mock v1.5.0
|
||||
github.com/google/btree v1.0.0
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||
|
@ -27,13 +29,13 @@ require (
|
|||
github.com/lestrrat-go/strftime v1.0.3 // indirect
|
||||
github.com/libp2p/go-libp2p-core v0.5.6
|
||||
github.com/magiconair/properties v1.8.4
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210318102029-494ee3060b0c
|
||||
github.com/meshplus/bitxhub-kit v1.1.2-0.20210112075018-319e668d6359
|
||||
github.com/meshplus/bitxhub-model v1.1.2-0.20210120083349-c7a006b03fcb
|
||||
github.com/meshplus/bitxhub-model v1.1.2-0.20210309053945-afaea82e9fe1
|
||||
github.com/meshplus/go-libp2p-cert v0.0.0-20210125063330-7c25fd5b7a49
|
||||
github.com/meshplus/go-lightp2p v0.0.0-20210120082108-df5a536a6192
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/multiformats/go-multiaddr v0.2.2
|
||||
github.com/multiformats/go-multiaddr v0.3.0
|
||||
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6
|
||||
github.com/pelletier/go-toml v1.2.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
|
@ -48,7 +50,7 @@ require (
|
|||
github.com/stretchr/testify v1.6.0
|
||||
github.com/sykesm/zap-logfmt v0.0.4 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d
|
||||
github.com/tidwall/gjson v1.3.5
|
||||
github.com/tidwall/gjson v1.6.8
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5
|
||||
github.com/urfave/cli v1.22.1
|
||||
github.com/wasmerio/go-ext-wasm v0.3.1
|
||||
|
@ -57,7 +59,6 @@ require (
|
|||
go.uber.org/atomic v1.7.0
|
||||
go.uber.org/multierr v1.6.0 // indirect
|
||||
go.uber.org/zap v1.16.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 // indirect
|
||||
google.golang.org/genproto v0.0.0-20201119123407-9b1e624d6bc4 // indirect
|
||||
google.golang.org/grpc v1.33.2
|
||||
)
|
||||
|
|
43
go.sum
43
go.sum
|
@ -91,6 +91,8 @@ 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.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheynewallace/tabby v1.1.1 h1:JvUR8waht4Y0S3JF17G6Vhyt+FRhnqVCkk8l4YrOU54=
|
||||
github.com/cheynewallace/tabby v1.1.1/go.mod h1:Pba/6cUL8uYqvOc9RkyvFbHGrQ9wShyrn6/S/1OYVys=
|
||||
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/common-nighthawk/go-figure v0.0.0-20190529165535-67e0ed34491a h1:kTv7wPomOuRf17BKQKO5Y6GrKsYC52XHrjf26H6FdQU=
|
||||
|
@ -208,8 +210,8 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb
|
|||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
|
||||
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||
github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g=
|
||||
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
|
||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
|
@ -313,6 +315,8 @@ github.com/ipfs/go-cid v0.0.3/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUP
|
|||
github.com/ipfs/go-cid v0.0.4/go.mod h1:4LLaPOQwmk5z9LBgQnpkivrx8BJjUyGwTXCd5Xfj6+M=
|
||||
github.com/ipfs/go-cid v0.0.5 h1:o0Ix8e/ql7Zb5UVUJEUfjsWCIY8t48++9lR8qi6oiJU=
|
||||
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
|
||||
github.com/ipfs/go-cid v0.0.7 h1:ysQJVJA3fNDF1qigJbsSQOdjhVLsOEoPdh0+R97k3jY=
|
||||
github.com/ipfs/go-cid v0.0.7/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
|
||||
github.com/ipfs/go-datastore v0.0.1/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
|
||||
github.com/ipfs/go-datastore v0.1.0/go.mod h1:d4KVXhMt913cLBEI/PXAy6ko+W7e9AhyAKBGh803qeE=
|
||||
github.com/ipfs/go-datastore v0.1.1/go.mod h1:w38XXW9kVFNp57Zj5knbKWM2T+KOZCGDRVNdgPHtbHw=
|
||||
|
@ -592,6 +596,8 @@ github.com/libp2p/go-yamux v1.3.3/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZ
|
|||
github.com/libp2p/go-yamux v1.3.5/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
||||
github.com/libp2p/go-yamux v1.3.6 h1:O5qcBXRcfqecvQ/My9NqDNHB3/5t58yuJYqthcKhhgE=
|
||||
github.com/libp2p/go-yamux v1.3.6/go.mod h1:FGTiPvoV/3DVdgWpX+tM0OW3tsM+W5bSE3gZwqQTcow=
|
||||
github.com/looplab/fsm v0.2.0 h1:M8hf5EF4AYLcT1FNKVUX8nu7D0xfp291iGeuigSxfrw=
|
||||
github.com/looplab/fsm v0.2.0/go.mod h1:p+IElwgCnAByqr2DWMuNbPjgMwqcHvTRZZn3dvKEke0=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
|
@ -617,8 +623,8 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/
|
|||
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956 h1:f1CXhJSLo/JuTXLjv5PRtvLvzq7mxzD58Aet27k5QlU=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210126064930-8245c5b45956/go.mod h1:MHf0waxqnW4Qwfpq66jqvJP+FritN5OTs/8wlQcNlJY=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210318102029-494ee3060b0c h1:78bm/wsSv0IORdGw6xdoeFVsILn/hwG6vk4eAg3rgLE=
|
||||
github.com/meshplus/bitxhub-core v0.1.0-rc1.0.20210318102029-494ee3060b0c/go.mod h1:G19Wrz1u66UmwaES/iLM19jmlv3APAZ5qfYOlNnIIZw=
|
||||
github.com/meshplus/bitxhub-kit v1.1.1 h1:vkPO88oA3+Kpc0N8lIgfj/U52KBuI+633hPbMYt1xm8=
|
||||
github.com/meshplus/bitxhub-kit v1.1.1/go.mod h1:r4l4iqn0RPJreb/OmoYKfjCjQJrXpZX++6Qc31VG/1k=
|
||||
github.com/meshplus/bitxhub-kit v1.1.2-0.20201021105954-468d0a9d7957/go.mod h1:r4l4iqn0RPJreb/OmoYKfjCjQJrXpZX++6Qc31VG/1k=
|
||||
|
@ -628,8 +634,8 @@ github.com/meshplus/bitxhub-kit v1.1.2-0.20201203072410-8a0383a6870d/go.mod h1:K
|
|||
github.com/meshplus/bitxhub-kit v1.1.2-0.20210112075018-319e668d6359 h1:GdgS14bnCF4b/a5zhQi2wlu92pHc9cfl6A1HcbO7zmE=
|
||||
github.com/meshplus/bitxhub-kit v1.1.2-0.20210112075018-319e668d6359/go.mod h1:KR7ZlXhII9n0Bu8viaZTScvXCYn0MCQnYlsTvHPp0XA=
|
||||
github.com/meshplus/bitxhub-model v1.1.2-0.20201021152621-0b3c17c54b23/go.mod h1:4qWBZx5wv7WZzUqiuBsbkQqQ2Ju8aOFpsoNpBBNy8Us=
|
||||
github.com/meshplus/bitxhub-model v1.1.2-0.20210120083349-c7a006b03fcb h1:PxGQL22OVxozkvEgVvxHol9WDqCZlhyvnd0Bu0HBX1Y=
|
||||
github.com/meshplus/bitxhub-model v1.1.2-0.20210120083349-c7a006b03fcb/go.mod h1:x3H+TL24wcByzHegenLfs+5PQkQGNsk8eCm31QJMa+Q=
|
||||
github.com/meshplus/bitxhub-model v1.1.2-0.20210309053945-afaea82e9fe1 h1:ziae0L0cbCMKp66OYzjZuU1WtNoB2TgfFhNIVWOTod4=
|
||||
github.com/meshplus/bitxhub-model v1.1.2-0.20210309053945-afaea82e9fe1/go.mod h1:x3H+TL24wcByzHegenLfs+5PQkQGNsk8eCm31QJMa+Q=
|
||||
github.com/meshplus/go-libp2p-cert v0.0.0-20210120021632-1578cf63e06a h1:eg1BDjSOsz3cdH49kPE8c2XnIFlLTPEMJLqpofV/OEY=
|
||||
github.com/meshplus/go-libp2p-cert v0.0.0-20210120021632-1578cf63e06a/go.mod h1:rS4AYMqKypLn2IPEnHICP//V2v16SZo4CWUbwMdihl0=
|
||||
github.com/meshplus/go-libp2p-cert v0.0.0-20210125063330-7c25fd5b7a49 h1:F8dpLJZW6FxqinAQcZKTkoymZgxnqlNvTebNqWVMEYI=
|
||||
|
@ -671,6 +677,8 @@ github.com/mr-tron/base58 v1.1.3 h1:v+sk57XuaCKGXpWtVBX8YJzO7hMGx4Aajh4TQbdEFdc=
|
|||
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/multiformats/go-base32 v0.0.3 h1:tw5+NhuwaOjJCC5Pp82QuXbrmLzWg7uxlMFp8Nq/kkI=
|
||||
github.com/multiformats/go-base32 v0.0.3/go.mod h1:pLiuGC8y0QR3Ue4Zug5UzK9LjgbkL8NSQj0zQ5Nz/AA=
|
||||
github.com/multiformats/go-base36 v0.1.0 h1:JR6TyF7JjGd3m6FbLU2cOxhC0Li8z8dLNGQ89tUg4F4=
|
||||
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
|
||||
github.com/multiformats/go-multiaddr v0.0.1/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
github.com/multiformats/go-multiaddr v0.0.2/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
github.com/multiformats/go-multiaddr v0.0.4/go.mod h1:xKVEak1K9cS1VdmPZW3LSIb6lgmoS58qz/pzqmAxV44=
|
||||
|
@ -680,6 +688,8 @@ github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y9
|
|||
github.com/multiformats/go-multiaddr v0.2.1/go.mod h1:s/Apk6IyxfvMjDafnhJgJ3/46z7tZ04iMk5wP4QMGGE=
|
||||
github.com/multiformats/go-multiaddr v0.2.2 h1:XZLDTszBIJe6m0zF6ITBrEcZR73OPUhCBBS9rYAuUzI=
|
||||
github.com/multiformats/go-multiaddr v0.2.2/go.mod h1:NtfXiOtHvghW9KojvtySjH5y0u0xW5UouOmQQrn6a3Y=
|
||||
github.com/multiformats/go-multiaddr v0.3.0 h1:z1Old9IYcUyMEtSbvwCOJ1jcrmJdU0LYH8aFBvZKzcQ=
|
||||
github.com/multiformats/go-multiaddr v0.3.0/go.mod h1:dF9kph9wfJ+3VLAaeBqo9Of8x4fJxp6ggJGteB8HQTI=
|
||||
github.com/multiformats/go-multiaddr-dns v0.0.1/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
|
||||
github.com/multiformats/go-multiaddr-dns v0.0.2/go.mod h1:9kWcqw/Pj6FwxAwW38n/9403szc57zJPs45fmnznu3Q=
|
||||
github.com/multiformats/go-multiaddr-dns v0.2.0 h1:YWJoIDwLePniH7OU5hBnDZV6SWuvJqJ0YtN6pLeH9zA=
|
||||
|
@ -698,6 +708,8 @@ github.com/multiformats/go-multiaddr-net v0.1.5/go.mod h1:ilNnaM9HbmVFqsb/qcNysj
|
|||
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
|
||||
github.com/multiformats/go-multibase v0.0.2 h1:2pAgScmS1g9XjH7EtAfNhTuyrWYEWcxy0G5Wo85hWDA=
|
||||
github.com/multiformats/go-multibase v0.0.2/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
|
||||
github.com/multiformats/go-multibase v0.0.3 h1:l/B6bJDQjvQ5G52jw4QGSYeOTZoAwIO77RblWplfIqk=
|
||||
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
|
||||
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
|
||||
github.com/multiformats/go-multihash v0.0.5/go.mod h1:lt/HCbqlQwlPBz7lv0sQCdtfcMtlJvakRUn/0Ual8po=
|
||||
github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||
|
@ -705,6 +717,8 @@ github.com/multiformats/go-multihash v0.0.9/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa
|
|||
github.com/multiformats/go-multihash v0.0.10/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
|
||||
github.com/multiformats/go-multihash v0.0.13 h1:06x+mk/zj1FoMsgNejLpy6QTvJqlSt/BhLEy87zidlc=
|
||||
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
|
||||
github.com/multiformats/go-multihash v0.0.14 h1:QoBceQYQQtNUuf6s7wHxnE2c8bhbMqhfGzNI032se/I=
|
||||
github.com/multiformats/go-multihash v0.0.14/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
|
||||
github.com/multiformats/go-multistream v0.1.0/go.mod h1:fJTiDfXJVmItycydCnNx4+wSzZ5NwG2FEVAI30fiovg=
|
||||
github.com/multiformats/go-multistream v0.1.1 h1:JlAdpIFhBhGRLxe9W6Om0w++Gd6KMWoFPZL/dEnm9nI=
|
||||
github.com/multiformats/go-multistream v0.1.1/go.mod h1:KmHZ40hzVxiaiwlj3MEbYgK9JFk2/9UktWZAF54Du38=
|
||||
|
@ -712,6 +726,8 @@ github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS
|
|||
github.com/multiformats/go-varint v0.0.2/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/multiformats/go-varint v0.0.5 h1:XVZwSo04Cs3j/jS0uAEPpT3JY6DzMcVLLoWOSnCxOjg=
|
||||
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/multiformats/go-varint v0.0.6 h1:gk85QWKxh3TazbLxED/NlDVv8+q+ReFJk7Y2W/KhfNY=
|
||||
github.com/multiformats/go-varint v0.0.6/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
|
||||
|
@ -884,12 +900,12 @@ github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto
|
|||
github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ=
|
||||
github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
|
||||
github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
|
||||
github.com/tidwall/gjson v1.3.5 h1:2oW9FBNu8qt9jy5URgrzsVx/T/KSn3qn/smJQ0crlDQ=
|
||||
github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
|
||||
github.com/tidwall/match v1.0.1 h1:PnKP62LPNxHKTwvHHZZzdOAOCtsJTjo6dZLCwpKm5xc=
|
||||
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tidwall/gjson v1.6.8 h1:CTmXMClGYPAmln7652e69B7OLXfTi5ABcPPwjIWUv7w=
|
||||
github.com/tidwall/gjson v1.6.8/go.mod h1:zeFuBCIqD4sN/gmqBzZ4j7Jd6UcA2Fc56x7QFsv+8fI=
|
||||
github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE=
|
||||
github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU=
|
||||
github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
|
@ -1080,9 +1096,8 @@ golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package contracts
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
|
@ -15,15 +16,69 @@ type AppchainManager struct {
|
|||
appchainMgr.AppchainManager
|
||||
}
|
||||
|
||||
type RegisterResult struct {
|
||||
ChainID string `json:"chain_id"`
|
||||
ProposalID string `json:"proposal_id"`
|
||||
}
|
||||
|
||||
func (am *AppchainManager) Manager(des string, proposalResult string, extra []byte) *boltvm.Response {
|
||||
am.AppchainManager.Persister = am.Stub
|
||||
chain := &appchainMgr.Appchain{}
|
||||
if err := json.Unmarshal(extra, chain); err != nil {
|
||||
return boltvm.Error("unmarshal json error:" + err.Error())
|
||||
}
|
||||
|
||||
ok, err := am.AppchainManager.ChangeStatus(chain.ID, proposalResult)
|
||||
if !ok {
|
||||
return boltvm.Error(string(err))
|
||||
}
|
||||
|
||||
if proposalResult == string(APPOVED) {
|
||||
switch des {
|
||||
case appchainMgr.EventRegister:
|
||||
return am.CrossInvoke(constant.InterchainContractAddr.String(), "Register", pb.String(chain.ID))
|
||||
case appchainMgr.EventUpdate:
|
||||
return responseWrapper(am.AppchainManager.UpdateAppchain(chain.ID, chain.Validators, chain.ConsensusType, chain.ChainType, chain.Name, chain.Desc, chain.Version, chain.PublicKey))
|
||||
}
|
||||
}
|
||||
|
||||
return boltvm.Success(nil)
|
||||
}
|
||||
|
||||
// Register appchain managers registers appchain info caller is the appchain
|
||||
// manager address return appchain id and error
|
||||
func (am *AppchainManager) Register(validators string, consensusType int32, chainType, name, desc, version, pubkey string) *boltvm.Response {
|
||||
am.AppchainManager.Persister = am.Stub
|
||||
res := am.CrossInvoke(constant.InterchainContractAddr.String(), "Register")
|
||||
ok, idData := am.AppchainManager.Register(am.Caller(), validators, consensusType, chainType, name, desc, version, pubkey)
|
||||
if ok {
|
||||
return boltvm.Error("appchain has registered, chain id: " + string(idData))
|
||||
}
|
||||
|
||||
ok, data := am.AppchainManager.GetAppchain(string(idData))
|
||||
if !ok {
|
||||
return boltvm.Error("get appchain error: " + string(data))
|
||||
}
|
||||
|
||||
res := am.CrossInvoke(constant.GovernanceContractAddr.String(), "SubmitProposal",
|
||||
pb.String(am.Caller()),
|
||||
pb.String(appchainMgr.EventRegister),
|
||||
pb.String(string(AppchainMgr)),
|
||||
pb.Bytes(data),
|
||||
)
|
||||
|
||||
if !res.Ok {
|
||||
return res
|
||||
}
|
||||
return responseWrapper(am.AppchainManager.Register(am.Caller(), validators, consensusType, chainType, name, desc, version, pubkey))
|
||||
|
||||
res1 := RegisterResult{
|
||||
ChainID: am.Caller(),
|
||||
ProposalID: string(res.Result),
|
||||
}
|
||||
resData, err := json.Marshal(res1)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(resData)
|
||||
}
|
||||
|
||||
// UpdateAppchain updates approved appchain
|
||||
|
@ -32,16 +87,10 @@ func (am *AppchainManager) UpdateAppchain(validators string, consensusType int32
|
|||
return responseWrapper(am.AppchainManager.UpdateAppchain(am.Caller(), validators, consensusType, chainType, name, desc, version, pubkey))
|
||||
}
|
||||
|
||||
//FetchAuditRecords fetches audit records by appchain id
|
||||
func (am *AppchainManager) FetchAuditRecords(id string) *boltvm.Response {
|
||||
am.AppchainManager.Persister = am.Stub
|
||||
return responseWrapper(am.AppchainManager.FetchAuditRecords(id))
|
||||
}
|
||||
|
||||
// CountApprovedAppchains counts all approved appchains
|
||||
func (am *AppchainManager) CountApprovedAppchains() *boltvm.Response {
|
||||
func (am *AppchainManager) CountAvailableAppchains() *boltvm.Response {
|
||||
am.AppchainManager.Persister = am.Stub
|
||||
return responseWrapper(am.AppchainManager.CountApprovedAppchains())
|
||||
return responseWrapper(am.AppchainManager.CountAvailableAppchains())
|
||||
}
|
||||
|
||||
// CountAppchains counts all appchains including approved, rejected or registered
|
||||
|
@ -74,15 +123,6 @@ func (am *AppchainManager) GetPubKeyByChainID(id string) *boltvm.Response {
|
|||
return responseWrapper(am.AppchainManager.GetPubKeyByChainID(id))
|
||||
}
|
||||
|
||||
// Audit bitxhub manager audit appchain register info
|
||||
func (am *AppchainManager) Audit(proposer string, isApproved int32, desc string) *boltvm.Response {
|
||||
am.AppchainManager.Persister = am.Stub
|
||||
if res := am.IsAdmin(); !res.Ok {
|
||||
return res
|
||||
}
|
||||
return responseWrapper(am.AppchainManager.Audit(proposer, isApproved, desc))
|
||||
}
|
||||
|
||||
func (am *AppchainManager) DeleteAppchain(cid string) *boltvm.Response {
|
||||
am.AppchainManager.Persister = am.Stub
|
||||
if res := am.IsAdmin(); !res.Ok {
|
||||
|
|
|
@ -4,23 +4,24 @@ import (
|
|||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
appchainMgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
||||
"github.com/meshplus/bitxhub-core/boltvm"
|
||||
"github.com/meshplus/bitxhub-core/boltvm/mock_stub"
|
||||
"github.com/meshplus/bitxhub-core/validator"
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-kit/log"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
"github.com/meshplus/bitxhub-model/constant"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/meshplus/bitxhub/internal/repo"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var caller = "0x3f9d18f7c3a6e5e4c0b877fe3e688ab08840b997"
|
||||
|
@ -74,7 +75,7 @@ func TestAppchainManager_Appchains(t *testing.T) {
|
|||
addr := types.NewAddress([]byte{byte(i)}).String()
|
||||
|
||||
chain := &appchainMgr.Appchain{
|
||||
Status: appchainMgr.APPROVED,
|
||||
Status: appchainMgr.AppchainAvailable,
|
||||
ID: addr,
|
||||
Name: "appchain" + addr,
|
||||
Validators: "",
|
||||
|
@ -93,9 +94,7 @@ func TestAppchainManager_Appchains(t *testing.T) {
|
|||
}
|
||||
|
||||
logger := log.NewWithModule("contracts")
|
||||
registerResponse := &boltvm.Response{
|
||||
Ok: true,
|
||||
}
|
||||
|
||||
am := &AppchainManager{
|
||||
Stub: mockStub,
|
||||
}
|
||||
|
@ -104,7 +103,8 @@ func TestAppchainManager_Appchains(t *testing.T) {
|
|||
mockStub.EXPECT().Logger().Return(logger).AnyTimes()
|
||||
|
||||
// test for register
|
||||
mockStub.EXPECT().CrossInvoke(constant.InterchainContractAddr.String(), "Register").Return(registerResponse)
|
||||
mockStub.EXPECT().Get(gomock.Any()).Return(true, chainsData[0]).AnyTimes()
|
||||
mockStub.EXPECT().CrossInvoke(constant.GovernanceContractAddr.String(), "SubmitProposal", gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Success(nil))
|
||||
mockStub.EXPECT().Has(AppchainKey(caller)).Return(false).MaxTimes(3)
|
||||
am.Register(chains[0].Validators, chains[0].ConsensusType, chains[0].ChainType,
|
||||
chains[0].Name, chains[0].Desc, chains[0].Version, chains[0].PublicKey)
|
||||
|
@ -133,31 +133,102 @@ func TestAppchainManager_Appchains(t *testing.T) {
|
|||
assert.Equal(t, "2", string(res.Result))
|
||||
|
||||
// test GetAppchain
|
||||
mockStub.EXPECT().Get(AppchainKey(caller)).Return(true, chainsData[0])
|
||||
|
||||
res = am.GetAppchain(caller)
|
||||
assert.Equal(t, true, res.Ok)
|
||||
assert.Equal(t, chainsData[0], res.Result)
|
||||
}
|
||||
|
||||
func TestAudit(t *testing.T) {
|
||||
am, mockStub, _, _ := prepare(t)
|
||||
func TestAppchainManager_Register(t *testing.T) {
|
||||
am, mockStub, chains, chainsData := prepare(t)
|
||||
|
||||
logger := log.NewWithModule("contracts")
|
||||
// test for DeleteAppchain
|
||||
|
||||
mockStub.EXPECT().Caller().Return(caller).AnyTimes()
|
||||
mockStub.EXPECT().Get(gomock.Any()).Return(true, chainsData[0]).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(gomock.Any(), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
chain := ret.(*appchainMgr.Appchain)
|
||||
chain.ID = chains[0].ID
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).Return().AnyTimes()
|
||||
mockStub.EXPECT().Logger().Return(logger).AnyTimes()
|
||||
mockStub.EXPECT().CrossInvoke(constant.GovernanceContractAddr.String(), "SubmitProposal", gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Success(nil))
|
||||
mockStub.EXPECT().Has(AppchainKey(caller)).Return(false).Times(1)
|
||||
mockStub.EXPECT().Has(AppchainKey(caller)).Return(true).AnyTimes()
|
||||
res := am.Register(chains[0].Validators, chains[0].ConsensusType, chains[0].ChainType,
|
||||
chains[0].Name, chains[0].Desc, chains[0].Version, chains[0].PublicKey)
|
||||
assert.True(t, res.Ok)
|
||||
|
||||
// test for audit
|
||||
approveRes := &boltvm.Response{
|
||||
Ok: true,
|
||||
Result: []byte("true"),
|
||||
// test for repeated register
|
||||
am.Register(chains[0].Validators, chains[0].ConsensusType, chains[0].ChainType,
|
||||
chains[0].Name, chains[0].Desc, chains[0].Version, chains[0].PublicKey)
|
||||
assert.True(t, res.Ok)
|
||||
}
|
||||
|
||||
func TestAppchainManager_Manager(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
am := &AppchainManager{
|
||||
Stub: mockStub,
|
||||
}
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "IsAdmin", gomock.Any()).Return(approveRes)
|
||||
mockStub.EXPECT().GetObject(gomock.Any(), gomock.Any()).Return(true).AnyTimes()
|
||||
|
||||
res := am.Audit(caller, appchainMgr.APPROVED, "approve test chain")
|
||||
assert.Equal(t, true, res.Ok)
|
||||
chain := &appchainMgr.Appchain{
|
||||
Status: appchainMgr.AppchainUpdating,
|
||||
ID: "addr",
|
||||
Name: "appchain A",
|
||||
Validators: "",
|
||||
ConsensusType: int32(1),
|
||||
ChainType: "fabric",
|
||||
Desc: "",
|
||||
Version: "",
|
||||
PublicKey: "11111",
|
||||
}
|
||||
data, err := json.Marshal(chain)
|
||||
assert.Nil(t, err)
|
||||
|
||||
chain1 := &appchainMgr.Appchain{
|
||||
Status: appchainMgr.AppchainUpdating,
|
||||
ID: "addr1",
|
||||
Name: "appchain A",
|
||||
Validators: "",
|
||||
ConsensusType: int32(1),
|
||||
ChainType: "fabric",
|
||||
Desc: "",
|
||||
Version: "",
|
||||
PublicKey: "11111",
|
||||
}
|
||||
data1, err := json.Marshal(chain1)
|
||||
assert.Nil(t, err)
|
||||
|
||||
mockStub.EXPECT().Get(AppchainKey("addr")).Return(true, data).AnyTimes()
|
||||
mockStub.EXPECT().Get(AppchainKey("addr1")).Return(false, nil).AnyTimes()
|
||||
mockStub.EXPECT().Has(AppchainKey("addr")).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().Has(AppchainKey("addr1")).Return(false).AnyTimes()
|
||||
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).Return().AnyTimes()
|
||||
mockStub.EXPECT().GetObject(gomock.Any(), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
chain := ret.(*appchainMgr.Appchain)
|
||||
chain.Status = appchainMgr.AppchainAvailable
|
||||
assert.Equal(t, key, AppchainKey("addr"))
|
||||
return true
|
||||
})
|
||||
|
||||
res := am.Manager(appchainMgr.EventUpdate, string(APPOVED), data1)
|
||||
assert.False(t, res.Ok)
|
||||
res = am.Manager(appchainMgr.EventUpdate, string(REJECTED), data1)
|
||||
assert.False(t, res.Ok)
|
||||
res = am.Manager(appchainMgr.EventUpdate, string(APPOVED), data)
|
||||
assert.True(t, res.Ok)
|
||||
res = am.Manager(appchainMgr.EventUpdate, string(REJECTED), data)
|
||||
assert.True(t, res.Ok)
|
||||
|
||||
mockStub.EXPECT().CrossInvoke(constant.InterchainContractAddr.String(), "Register", gomock.Any()).Return(boltvm.Error("")).Times(1)
|
||||
mockStub.EXPECT().CrossInvoke(constant.InterchainContractAddr.String(), "Register", gomock.Any()).Return(boltvm.Success(nil)).AnyTimes()
|
||||
res = am.Manager(appchainMgr.EventRegister, string(APPOVED), data)
|
||||
assert.False(t, res.Ok)
|
||||
res = am.Manager(appchainMgr.EventRegister, string(APPOVED), data)
|
||||
assert.True(t, res.Ok)
|
||||
}
|
||||
|
||||
func TestUpdateChain(t *testing.T) {
|
||||
|
@ -165,26 +236,20 @@ func TestUpdateChain(t *testing.T) {
|
|||
logger := log.NewWithModule("contracts")
|
||||
// test for DeleteAppchain
|
||||
mockStub.EXPECT().Caller().Return(caller).AnyTimes()
|
||||
mockStub.EXPECT().Has(AppchainKey(caller)).Return(true)
|
||||
mockStub.EXPECT().Has(AppchainKey(caller)).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).Return().AnyTimes()
|
||||
mockStub.EXPECT().Logger().Return(logger).AnyTimes()
|
||||
// test UpdateAppchain without register
|
||||
mockStub.EXPECT().GetObject(AppchainKey(caller), gomock.Any()).Return(true)
|
||||
res := am.UpdateAppchain(chains[0].Validators, chains[0].ConsensusType, chains[0].ChainType,
|
||||
chains[0].Name, chains[0].Desc, chains[0].Version, chains[0].PublicKey)
|
||||
|
||||
assert.Equal(t, false, res.Ok)
|
||||
// TODO: test UpdateAppchain without register (false)
|
||||
// test UpdateAppchain with register
|
||||
mockStub.EXPECT().Has(AppchainKey(caller)).Return(true)
|
||||
mockStub.EXPECT().GetObject(gomock.Any(), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
chain := ret.(*appchainMgr.Appchain)
|
||||
chain.Status = appchainMgr.APPROVED
|
||||
chain.Status = appchainMgr.AppchainAvailable
|
||||
chain.PublicKey = chains[0].PublicKey
|
||||
assert.Equal(t, key, AppchainKey(caller))
|
||||
return true
|
||||
})
|
||||
res = am.UpdateAppchain(chains[0].Validators, chains[0].ConsensusType, chains[0].ChainType,
|
||||
res := am.UpdateAppchain(chains[0].Validators, chains[0].ConsensusType, chains[0].ChainType,
|
||||
chains[0].Name, chains[0].Desc, chains[0].Version, chains[0].PublicKey)
|
||||
assert.Equal(t, true, res.Ok)
|
||||
}
|
||||
|
@ -199,7 +264,7 @@ func TestCountApprovedAppchains(t *testing.T) {
|
|||
mockStub.EXPECT().Logger().Return(logger).AnyTimes()
|
||||
// test for CountApprovedAppchains
|
||||
mockStub.EXPECT().Query(appchainMgr.PREFIX).Return(true, chainsData)
|
||||
res := am.CountApprovedAppchains()
|
||||
res := am.CountAvailableAppchains()
|
||||
assert.Equal(t, true, res.Ok)
|
||||
assert.Equal(t, "2", string(res.Result))
|
||||
}
|
||||
|
@ -219,7 +284,6 @@ func TestDeleteAppchain(t *testing.T) {
|
|||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "IsAdmin", gomock.Any()).Return(approveRes)
|
||||
mockStub.EXPECT().CrossInvoke(constant.InterchainContractAddr.String(), "DeleteInterchain",
|
||||
gomock.Any()).Return(approveRes)
|
||||
mockStub.EXPECT().GetObject(AppchainKey(caller), gomock.Any()).Return(true)
|
||||
mockStub.EXPECT().Delete(AppchainKey(caller)).Return()
|
||||
|
||||
res := am.DeleteAppchain(caller)
|
||||
|
@ -233,7 +297,7 @@ func TestGetPubKeyByChainID(t *testing.T) {
|
|||
mockStub.EXPECT().GetObject(gomock.Any(), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
chain := ret.(*appchainMgr.Appchain)
|
||||
chain.Status = appchainMgr.APPROVED
|
||||
chain.Status = appchainMgr.AppchainAvailable
|
||||
chain.PublicKey = chains[0].PublicKey
|
||||
assert.Equal(t, key, AppchainKey(caller))
|
||||
fmt.Printf("chain is %v", chain)
|
||||
|
@ -247,6 +311,9 @@ func TestGetPubKeyByChainID(t *testing.T) {
|
|||
func prepare(t *testing.T) (*AppchainManager, *mock_stub.MockStub, []*appchainMgr.Appchain, [][]byte) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
am := &AppchainManager{
|
||||
Stub: mockStub,
|
||||
}
|
||||
|
||||
var chains []*appchainMgr.Appchain
|
||||
var chainsData [][]byte
|
||||
|
@ -254,7 +321,7 @@ func prepare(t *testing.T) (*AppchainManager, *mock_stub.MockStub, []*appchainMg
|
|||
addr := types.NewAddress([]byte{byte(i)}).String()
|
||||
|
||||
chain := &appchainMgr.Appchain{
|
||||
Status: appchainMgr.APPROVED,
|
||||
Status: appchainMgr.AppchainAvailable,
|
||||
ID: addr,
|
||||
Name: "appchain" + addr,
|
||||
Validators: "",
|
||||
|
@ -272,9 +339,6 @@ func prepare(t *testing.T) (*AppchainManager, *mock_stub.MockStub, []*appchainMg
|
|||
chains = append(chains, chain)
|
||||
}
|
||||
|
||||
am := &AppchainManager{
|
||||
Stub: mockStub,
|
||||
}
|
||||
return am, mockStub, chains, chainsData
|
||||
}
|
||||
|
||||
|
@ -283,7 +347,7 @@ func TestInterchainManager_Register(t *testing.T) {
|
|||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
addr := types.NewAddress([]byte{0}).String()
|
||||
mockStub.EXPECT().Caller().Return(addr).AnyTimes()
|
||||
//mockStub.EXPECT().Caller().Return(addr).AnyTimes()
|
||||
mockStub.EXPECT().Set(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
o1 := mockStub.EXPECT().Get(appchainMgr.PREFIX+addr).Return(false, nil)
|
||||
|
||||
|
@ -313,7 +377,7 @@ func TestInterchainManager_Register(t *testing.T) {
|
|||
|
||||
im := &InterchainManager{mockStub}
|
||||
|
||||
res := im.Register()
|
||||
res := im.Register(addr)
|
||||
assert.Equal(t, true, res.Ok)
|
||||
|
||||
ic := &pb.Interchain{}
|
||||
|
@ -324,11 +388,11 @@ func TestInterchainManager_Register(t *testing.T) {
|
|||
assert.Equal(t, 0, len(ic.ReceiptCounter))
|
||||
assert.Equal(t, 0, len(ic.SourceReceiptCounter))
|
||||
|
||||
res = im.Register()
|
||||
res = im.Register(addr)
|
||||
assert.Equal(t, true, res.Ok)
|
||||
assert.Equal(t, data0, res.Result)
|
||||
|
||||
res = im.Register()
|
||||
res = im.Register(addr)
|
||||
assert.Equal(t, true, res.Ok)
|
||||
assert.Equal(t, data1, res.Result)
|
||||
}
|
||||
|
@ -585,19 +649,17 @@ func TestInterchainManager_HandleIBTPs(t *testing.T) {
|
|||
|
||||
mockStub.EXPECT().Set(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
f1 := mockStub.EXPECT().Get(appchainMgr.PREFIX+caller).Return(false, nil)
|
||||
|
||||
data0, err := interchain.Marshal()
|
||||
assert.Nil(t, err)
|
||||
|
||||
f2 := mockStub.EXPECT().Get(appchainMgr.PREFIX+caller).Return(true, data0).AnyTimes()
|
||||
mockStub.EXPECT().Get(appchainMgr.PREFIX+caller).Return(true, data0).AnyTimes()
|
||||
mockStub.EXPECT().Get(appchainMgr.PREFIX+to).Return(true, data0).AnyTimes()
|
||||
mockStub.EXPECT().CrossInvoke(gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Success(nil)).AnyTimes()
|
||||
mockStub.EXPECT().AddObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
mockStub.EXPECT().GetTxIndex().Return(uint64(1)).AnyTimes()
|
||||
mockStub.EXPECT().PostInterchainEvent(gomock.Any()).AnyTimes()
|
||||
mockStub.EXPECT().GetTxHash().Return(&types.Hash{}).AnyTimes()
|
||||
gomock.InOrder(f1, f2)
|
||||
|
||||
im := &InterchainManager{mockStub}
|
||||
|
||||
|
@ -649,7 +711,7 @@ func TestInterchainManager_HandleUnionIBTP(t *testing.T) {
|
|||
assert.Nil(t, err)
|
||||
|
||||
relayChain := &appchainMgr.Appchain{
|
||||
Status: appchainMgr.APPROVED,
|
||||
Status: appchainMgr.AppchainAvailable,
|
||||
ID: from,
|
||||
Name: "appchain" + from,
|
||||
Validators: "",
|
||||
|
@ -802,10 +864,15 @@ func TestRole_GetRole(t *testing.T) {
|
|||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
addrs := []string{types.NewAddress([]byte{0}).String(), types.NewAddress([]byte{1}).String()}
|
||||
admins := []*repo.Admin{
|
||||
&repo.Admin{
|
||||
Address: "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
Weight: 1,
|
||||
},
|
||||
}
|
||||
|
||||
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, addrs).AnyTimes()
|
||||
mockStub.EXPECT().Caller().Return(types.NewAddress([]byte{0}).String())
|
||||
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, admins).AnyTimes()
|
||||
mockStub.EXPECT().Caller().Return(admins[0].Address)
|
||||
|
||||
im := &Role{mockStub}
|
||||
|
||||
|
@ -831,13 +898,18 @@ func TestRole_IsAdmin(t *testing.T) {
|
|||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
addrs := []string{types.NewAddress([]byte{0}).String(), types.NewAddress([]byte{1}).String()}
|
||||
admins := []*repo.Admin{
|
||||
&repo.Admin{
|
||||
Address: "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
Weight: 1,
|
||||
},
|
||||
}
|
||||
|
||||
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, addrs).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, admins).AnyTimes()
|
||||
|
||||
im := &Role{mockStub}
|
||||
|
||||
res := im.IsAdmin(addrs[0])
|
||||
res := im.IsAdmin(admins[0].Address)
|
||||
assert.True(t, res.Ok)
|
||||
assert.Equal(t, "true", string(res.Result))
|
||||
|
||||
|
@ -850,21 +922,30 @@ func TestRole_GetAdminRoles(t *testing.T) {
|
|||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
addrs := []string{types.NewAddress([]byte{0}).String(), types.NewAddress([]byte{1}).String()}
|
||||
admins := []*repo.Admin{
|
||||
&repo.Admin{
|
||||
Address: "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
Weight: 1,
|
||||
},
|
||||
&repo.Admin{
|
||||
Address: "0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
Weight: 1,
|
||||
},
|
||||
}
|
||||
|
||||
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, addrs).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, admins).AnyTimes()
|
||||
|
||||
im := &Role{mockStub}
|
||||
|
||||
res := im.GetAdminRoles()
|
||||
assert.True(t, res.Ok)
|
||||
|
||||
var admins []string
|
||||
err := json.Unmarshal(res.Result, &admins)
|
||||
var as []*repo.Admin
|
||||
err := json.Unmarshal(res.Result, &as)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, len(addrs), len(admins))
|
||||
for i, addr := range addrs {
|
||||
assert.Equal(t, addr, admins[i])
|
||||
assert.Equal(t, len(admins), len(as))
|
||||
for i, admin := range admins {
|
||||
assert.Equal(t, admin.Address, as[i].Address)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -873,7 +954,7 @@ func TestRole_SetAdminRoles(t *testing.T) {
|
|||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
addrs := []string{types.NewAddress([]byte{0}).String(), types.NewAddress([]byte{1}).String()}
|
||||
mockStub.EXPECT().SetObject(adminRolesKey, addrs).AnyTimes()
|
||||
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
|
||||
im := &Role{mockStub}
|
||||
|
||||
|
@ -884,6 +965,31 @@ func TestRole_SetAdminRoles(t *testing.T) {
|
|||
assert.True(t, res.Ok)
|
||||
}
|
||||
|
||||
func TestRole_GetRoleWeight(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
admins := []*repo.Admin{
|
||||
&repo.Admin{
|
||||
Address: "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
Weight: 1,
|
||||
},
|
||||
}
|
||||
|
||||
mockStub.EXPECT().GetObject(adminRolesKey, gomock.Any()).SetArg(1, admins).AnyTimes()
|
||||
|
||||
im := &Role{mockStub}
|
||||
|
||||
res := im.GetRoleWeight(admins[0].Address)
|
||||
assert.True(t, res.Ok)
|
||||
w, err := strconv.Atoi(string(res.Result))
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, admins[0].Weight, uint64(w))
|
||||
|
||||
res = im.GetRoleWeight("")
|
||||
assert.False(t, res.Ok)
|
||||
}
|
||||
|
||||
func TestRuleManager_RegisterRule(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
@ -1420,3 +1526,467 @@ func TestInterRelayBroker_InvokeInterRelayContract(t *testing.T) {
|
|||
res = interRelayBroker.GetOutMessage("123", 1)
|
||||
require.True(t, res.Ok)
|
||||
}
|
||||
|
||||
func TestGovernance_SubmitProposal(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
g := Governance{mockStub}
|
||||
|
||||
idExistent := "idExistent-1"
|
||||
addrApproved := "addrApproved"
|
||||
addrAganisted := "addrAganisted"
|
||||
approveBallot := Ballot{
|
||||
VoterAddr: addrApproved,
|
||||
Approve: BallotApprove,
|
||||
Num: 1,
|
||||
Reason: "",
|
||||
}
|
||||
againstBallot := Ballot{
|
||||
VoterAddr: addrAganisted,
|
||||
Approve: BallotReject,
|
||||
Num: 1,
|
||||
Reason: "",
|
||||
}
|
||||
proposalExistent := &Proposal{
|
||||
Id: idExistent,
|
||||
Des: "des",
|
||||
Typ: AppchainMgr,
|
||||
Status: PROPOSED,
|
||||
BallotMap: map[string]Ballot{addrApproved: approveBallot, addrAganisted: againstBallot},
|
||||
ApproveNum: 1,
|
||||
AgainstNum: 1,
|
||||
}
|
||||
pData, err := json.Marshal(proposalExistent)
|
||||
assert.Nil(t, err)
|
||||
pDatas := make([][]byte, 0)
|
||||
pDatas = append(pDatas, pData)
|
||||
|
||||
admins := []*repo.Admin{
|
||||
&repo.Admin{
|
||||
Address: "addr1",
|
||||
Weight: 1,
|
||||
},
|
||||
&repo.Admin{
|
||||
Address: "addr2",
|
||||
Weight: 1,
|
||||
},
|
||||
&repo.Admin{
|
||||
Address: "addr3",
|
||||
Weight: 1,
|
||||
},
|
||||
&repo.Admin{
|
||||
Address: "addr4",
|
||||
Weight: 1,
|
||||
},
|
||||
}
|
||||
adminsData, err := json.Marshal(admins)
|
||||
assert.Nil(t, err)
|
||||
adminsErrorData := make([]byte, 0)
|
||||
|
||||
mockStub.EXPECT().Query(gomock.Any()).Return(true, pDatas).AnyTimes()
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetAdminRoles").Return(boltvm.Error("")).Times(1)
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetAdminRoles").Return(boltvm.Success(adminsErrorData)).Times(2)
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetAdminRoles").Return(boltvm.Success(adminsData)).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(gomock.Any(), gomock.Any()).Return(false).AnyTimes()
|
||||
mockStub.EXPECT().AddObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
|
||||
res := g.SubmitProposal("", "des", string(AppchainMgr), []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// GetAdminRoles error
|
||||
res = g.SubmitProposal(idExistent, "des", string(AppchainMgr), []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// GetAdminRoles unmarshal error
|
||||
res = g.SubmitProposal(idExistent, "des", string(AppchainMgr), []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.SubmitProposal(idExistent, "des", "", []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.SubmitProposal(idExistent, "des", string(AppchainMgr), []byte{})
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
|
||||
}
|
||||
func TestGovernance_Proposal(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
g := Governance{mockStub}
|
||||
|
||||
idExistent := "idExistent-1"
|
||||
idNonexistent := "idNonexistent-2"
|
||||
idClosed := "idClosed-3"
|
||||
idNotReachThreshold := "idNotReachThreshold-4"
|
||||
idSuperMajorityApprove := "idSuperMajorityApprove-5"
|
||||
idSuperMajorityAgainst := "idSuperMajorityAgainst-6"
|
||||
idUnupportedType := "idUnsupportedType-7"
|
||||
addrApproved := "addrApproved"
|
||||
addrAganisted := "addrAganisted"
|
||||
addrNotVoted := "addrNotVoted"
|
||||
addrNotVoted1 := "addrNotVoted1"
|
||||
addrNotVoted2 := "addrNotVoted2"
|
||||
addrNotVoted3 := "addrNotVoted3"
|
||||
addrNotVoted4 := "addrNotVoted4"
|
||||
addrNotVoted5 := "addrNotVoted5"
|
||||
addrNotVoted6 := "addrNotVoted6"
|
||||
|
||||
approveBallot := Ballot{
|
||||
VoterAddr: addrApproved,
|
||||
Approve: BallotApprove,
|
||||
Num: 1,
|
||||
Reason: "",
|
||||
}
|
||||
againstBallot := Ballot{
|
||||
VoterAddr: addrAganisted,
|
||||
Approve: BallotReject,
|
||||
Num: 1,
|
||||
Reason: "",
|
||||
}
|
||||
proposalExistent := Proposal{
|
||||
Id: idExistent,
|
||||
Des: "des",
|
||||
Typ: AppchainMgr,
|
||||
Status: PROPOSED,
|
||||
BallotMap: map[string]Ballot{addrApproved: approveBallot, addrAganisted: againstBallot},
|
||||
ApproveNum: 1,
|
||||
AgainstNum: 1,
|
||||
ElectorateNum: 4,
|
||||
ThresholdNum: 3,
|
||||
}
|
||||
|
||||
pData, err := json.Marshal(proposalExistent)
|
||||
assert.Nil(t, err)
|
||||
pDatas := make([][]byte, 0)
|
||||
pDatas = append(pDatas, pData)
|
||||
|
||||
admins := []*repo.Admin{
|
||||
&repo.Admin{
|
||||
Address: "addr1",
|
||||
Weight: 1,
|
||||
},
|
||||
&repo.Admin{
|
||||
Address: "addr2",
|
||||
Weight: 1,
|
||||
},
|
||||
&repo.Admin{
|
||||
Address: "addr3",
|
||||
Weight: 1,
|
||||
},
|
||||
&repo.Admin{
|
||||
Address: "addr4",
|
||||
Weight: 1,
|
||||
},
|
||||
}
|
||||
adminsData, err := json.Marshal(admins)
|
||||
assert.Nil(t, err)
|
||||
|
||||
mockStub.EXPECT().Has(ProposalKey(idExistent)).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().Has(ProposalKey(idNonexistent)).Return(false).AnyTimes()
|
||||
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
mockStub.EXPECT().AddObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(ProposalKey(idExistent), gomock.Any()).SetArg(1, proposalExistent).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(ProposalKey(idClosed), gomock.Any()).Do(
|
||||
func(id string, ret interface{}) bool {
|
||||
pro := ret.(*Proposal)
|
||||
pro.Id = idClosed
|
||||
pro.Des = proposalExistent.Des
|
||||
pro.Typ = proposalExistent.Typ
|
||||
pro.Status = APPOVED
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(ProposalKey(idNonexistent), gomock.Any()).Return(false).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(ProposalKey(idNotReachThreshold), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
pro := ret.(*Proposal)
|
||||
pro.Id = idNotReachThreshold
|
||||
pro.Des = proposalExistent.Des
|
||||
pro.Typ = RuleMgr
|
||||
pro.Status = proposalExistent.Status
|
||||
pro.BallotMap = proposalExistent.BallotMap
|
||||
pro.ApproveNum = proposalExistent.ApproveNum
|
||||
pro.AgainstNum = proposalExistent.AgainstNum
|
||||
pro.ElectorateNum = 4
|
||||
pro.ThresholdNum = 4
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(ProposalKey(idSuperMajorityApprove), gomock.Any()).Do(
|
||||
func(id string, ret interface{}) bool {
|
||||
pro := ret.(*Proposal)
|
||||
pro.Id = idSuperMajorityApprove
|
||||
pro.Des = proposalExistent.Des
|
||||
pro.Typ = NodeMgr
|
||||
pro.Status = proposalExistent.Status
|
||||
pro.BallotMap = proposalExistent.BallotMap
|
||||
pro.ApproveNum = proposalExistent.ApproveNum
|
||||
pro.AgainstNum = proposalExistent.AgainstNum
|
||||
pro.ElectorateNum = proposalExistent.ElectorateNum
|
||||
pro.ThresholdNum = proposalExistent.ThresholdNum
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(ProposalKey(idSuperMajorityAgainst), gomock.Any()).Do(
|
||||
func(id string, ret interface{}) bool {
|
||||
pro := ret.(*Proposal)
|
||||
pro.Id = idSuperMajorityAgainst
|
||||
pro.Des = proposalExistent.Des
|
||||
pro.Typ = NodeMgr
|
||||
pro.Status = proposalExistent.Status
|
||||
pro.BallotMap = proposalExistent.BallotMap
|
||||
pro.ApproveNum = proposalExistent.ApproveNum
|
||||
pro.AgainstNum = proposalExistent.AgainstNum
|
||||
pro.ElectorateNum = proposalExistent.ElectorateNum
|
||||
pro.ThresholdNum = proposalExistent.ThresholdNum
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(ProposalKey(idUnupportedType), gomock.Any()).Do(
|
||||
func(id string, ret interface{}) bool {
|
||||
pro := ret.(*Proposal)
|
||||
pro.Id = idUnupportedType
|
||||
pro.Des = proposalExistent.Des
|
||||
pro.Typ = ServiceMgr
|
||||
pro.Status = proposalExistent.Status
|
||||
pro.BallotMap = proposalExistent.BallotMap
|
||||
pro.ApproveNum = proposalExistent.ApproveNum
|
||||
pro.AgainstNum = proposalExistent.AgainstNum
|
||||
pro.ElectorateNum = proposalExistent.ElectorateNum
|
||||
pro.ThresholdNum = proposalExistent.ThresholdNum
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(string(AppchainMgr), gomock.Any()).Return(false).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(string(RuleMgr), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
proStrategy := ret.(*ProposalStrategy)
|
||||
proStrategy.Typ = SimpleMajority
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(string(NodeMgr), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
proStrategy := ret.(*ProposalStrategy)
|
||||
proStrategy.Typ = SuperMajorityApprove
|
||||
return true
|
||||
}).Return(true).Times(1)
|
||||
mockStub.EXPECT().GetObject(string(NodeMgr), gomock.Any()).Do(
|
||||
func(key string, ret interface{}) bool {
|
||||
proStrategy := ret.(*ProposalStrategy)
|
||||
proStrategy.Typ = SuperMajorityAgainst
|
||||
return true
|
||||
}).Return(true).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(string(ServiceMgr), gomock.Any()).Return(false).AnyTimes()
|
||||
mockStub.EXPECT().Query(gomock.Any()).Return(true, pDatas).AnyTimes()
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetRoleWeight", gomock.Any()).Return(boltvm.Error("get role weight")).Times(1)
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetRoleWeight", gomock.Any()).Return(boltvm.Success([]byte(""))).Times(1)
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetRoleWeight", gomock.Any()).Return(boltvm.Success([]byte(strconv.Itoa(1)))).AnyTimes()
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetAdminRoles").Return(boltvm.Error("")).Times(1)
|
||||
mockStub.EXPECT().CrossInvoke(constant.RoleContractAddr.String(), "GetAdminRoles").Return(boltvm.Success(adminsData)).AnyTimes()
|
||||
mockStub.EXPECT().CrossInvoke(constant.AppchainMgrContractAddr.String(), "Manager", gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Error("")).Times(1)
|
||||
mockStub.EXPECT().CrossInvoke(constant.AppchainMgrContractAddr.String(), "Manager", gomock.Any(), gomock.Any(), gomock.Any()).Return(boltvm.Success(nil)).AnyTimes()
|
||||
|
||||
res := g.ModifyProposal(idExistent, "des", string(AppchainMgr), []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.ModifyProposal(idExistent, "des", string(AppchainMgr), []byte{})
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.ModifyProposal(idNonexistent, "des", string(AppchainMgr), []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.ModifyProposal("", "des", string(AppchainMgr), []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.ModifyProposal(idExistent, "des", "", []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetProposal(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetProposal(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetProposalsByFrom("idExistent")
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetProposalsByTyp("")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetProposalsByTyp(string(AppchainMgr))
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetProposalsByStatus("")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetProposalsByStatus(string((PROPOSED)))
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetDes(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetDes(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetTyp(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetTyp(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetStatus(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetStatus(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetApprove(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetApprove(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetAgainst(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetAgainst(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetVotedNum(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetVotedNum(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetVoted(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetVoted(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetApproveNum(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetApproveNum(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetAgainstNum(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetAgainstNum(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetElectorateNum(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetElectorateNum(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetThresholdNum(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetThresholdNum(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
var v = &Ballot{}
|
||||
res = g.GetBallot(addrApproved, idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetBallot(addrNotVoted, idExistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetBallot(addrApproved, idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
err = json.Unmarshal(res.Result, v)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, BallotApprove, v.Approve)
|
||||
assert.Equal(t, uint64(1), v.Num)
|
||||
res = g.GetBallot(addrAganisted, idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
err = json.Unmarshal(res.Result, v)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, BallotReject, v.Approve)
|
||||
assert.Equal(t, uint64(1), v.Num)
|
||||
|
||||
res = g.GetUnvote(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetUnvote(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetUnvoteNum(idNonexistent)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetUnvoteNum(idExistent)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
mockStub.EXPECT().Caller().Return(addrApproved).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrApproved).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted1).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted2).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted3).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted4).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted5).Times(1)
|
||||
mockStub.EXPECT().Caller().Return(addrNotVoted6).Times(1)
|
||||
|
||||
// nonexistent error
|
||||
res = g.Vote(idNonexistent, BallotApprove, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// closed error
|
||||
res = g.Vote(idClosed, BallotApprove, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// has voted error
|
||||
res = g.Vote(idExistent, BallotApprove, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
// get weight error
|
||||
res = g.Vote(idExistent, BallotApprove, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// get weight parse int error
|
||||
res = g.Vote(idExistent, BallotApprove, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
// not reach threshold (approve:1)
|
||||
res = g.Vote(idNotReachThreshold, BallotApprove, "")
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
// SuperMajorityApprove (reject:1)
|
||||
res = g.Vote(idSuperMajorityApprove, BallotReject, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// SuperMajorityAgainst (approve:2)
|
||||
res = g.Vote(idSuperMajorityAgainst, BallotApprove, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// UnupportedType (reject:2)
|
||||
res = g.Vote(idUnupportedType, BallotReject, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// Manager error (approve:3)
|
||||
res = g.Vote(idExistent, BallotApprove, "")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
// reject (reject:3)
|
||||
res = g.Vote(idExistent, BallotReject, "")
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
// approve (approve:4)
|
||||
res = g.Vote(idExistent, BallotReject, "")
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
}
|
||||
|
||||
func TestGovernance_ProposalStrategy(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockStub := mock_stub.NewMockStub(mockCtl)
|
||||
|
||||
g := Governance{mockStub}
|
||||
ps := &ProposalStrategy{
|
||||
Typ: SimpleMajority,
|
||||
ParticipateThreshold: 0.5,
|
||||
}
|
||||
psData, err := json.Marshal(ps)
|
||||
assert.Nil(t, err)
|
||||
|
||||
psError := &ProposalStrategy{
|
||||
Typ: SimpleMajority,
|
||||
ParticipateThreshold: 1.5,
|
||||
}
|
||||
psErrorData, err := json.Marshal(psError)
|
||||
assert.Nil(t, err)
|
||||
|
||||
mockStub.EXPECT().SetObject(gomock.Any(), gomock.Any()).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(string(RuleMgr), gomock.Any()).Return(false).AnyTimes()
|
||||
mockStub.EXPECT().GetObject(string(AppchainMgr), gomock.Any()).Return(true).AnyTimes()
|
||||
|
||||
res := g.NewProposalStrategy(string(SimpleMajority), 0.5, []byte{})
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.NewProposalStrategy("", 0.5, []byte{})
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.SetProposalStrategy(string(AppchainMgr), psData)
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.SetProposalStrategy("", psData)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.SetProposalStrategy(string(AppchainMgr), psErrorData)
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetProposalStrategy(string(AppchainMgr))
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetProposalStrategy("")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetProposalStrategy(string(RuleMgr))
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
|
||||
res = g.GetProposalStrategyType(string(AppchainMgr))
|
||||
assert.True(t, res.Ok, string(res.Result))
|
||||
res = g.GetProposalStrategyType("")
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
res = g.GetProposalStrategyType(string(RuleMgr))
|
||||
assert.False(t, res.Ok, string(res.Result))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,729 @@
|
|||
package contracts
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/meshplus/bitxhub-core/boltvm"
|
||||
"github.com/meshplus/bitxhub-model/constant"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/meshplus/bitxhub/internal/repo"
|
||||
)
|
||||
|
||||
type Governance struct {
|
||||
boltvm.Stub
|
||||
}
|
||||
|
||||
type ProposalType string
|
||||
type ProposalStatus string
|
||||
|
||||
const (
|
||||
PROPOSAL_PREFIX = "proposal-"
|
||||
|
||||
AppchainMgr ProposalType = "AppchainMgr"
|
||||
RuleMgr ProposalType = "RuleMgr"
|
||||
NodeMgr ProposalType = "NodeMgr"
|
||||
ServiceMgr ProposalType = "ServiceMgr"
|
||||
|
||||
PROPOSED ProposalStatus = "proposed"
|
||||
APPOVED ProposalStatus = "approve"
|
||||
REJECTED ProposalStatus = "reject"
|
||||
|
||||
BallotApprove = "approve"
|
||||
BallotReject = "reject"
|
||||
)
|
||||
|
||||
type Ballot struct {
|
||||
VoterAddr string `json:"voter_addr"`
|
||||
Approve string `json:"approve"`
|
||||
Num uint64 `json:"num"`
|
||||
Reason string `json:"reason"`
|
||||
}
|
||||
|
||||
func (g *Governance) GetBallot(voterAddr, proposalId string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(proposalId), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
ballot, ok := p.BallotMap[voterAddr]
|
||||
if !ok {
|
||||
return boltvm.Error("administrator of the address has not voted")
|
||||
}
|
||||
|
||||
bData, err := json.Marshal(ballot)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(bData)
|
||||
}
|
||||
|
||||
type Proposal struct {
|
||||
Id string `json:"id"`
|
||||
Des string `json:"des"`
|
||||
Typ ProposalType `json:"typ"`
|
||||
Status ProposalStatus `json:"status"`
|
||||
// ballot information: voter address -> ballot
|
||||
BallotMap map[string]Ballot `json:"ballot_map"`
|
||||
ApproveNum uint64 `json:"approve_num"`
|
||||
AgainstNum uint64 `json:"against_num"`
|
||||
ElectorateNum uint64 `json:"electorate_num"`
|
||||
ThresholdNum uint64 `json:"threshold_num"`
|
||||
Extra []byte `json:"extra"`
|
||||
}
|
||||
|
||||
func (g *Governance) SubmitProposal(from, des string, typ string, extra []byte) *boltvm.Response {
|
||||
ret, err := g.getProposalsByFrom(from)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
en, err := g.getElectorateNum()
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
tn, err := g.getThresholdNum(en, ProposalType(typ))
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
p := &Proposal{
|
||||
Id: from + "-" + strconv.Itoa(len(ret)),
|
||||
Des: des,
|
||||
Typ: ProposalType(typ),
|
||||
Status: PROPOSED,
|
||||
BallotMap: make(map[string]Ballot, 0),
|
||||
ApproveNum: 0,
|
||||
AgainstNum: 0,
|
||||
ElectorateNum: en,
|
||||
ThresholdNum: tn,
|
||||
Extra: extra,
|
||||
}
|
||||
if err := checkProposalInfo(p); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
g.AddObject(ProposalKey(p.Id), *p)
|
||||
|
||||
return boltvm.Success([]byte(p.Id))
|
||||
}
|
||||
|
||||
func (g *Governance) getElectorateNum() (uint64, error) {
|
||||
res := g.CrossInvoke(constant.RoleContractAddr.String(), "GetAdminRoles")
|
||||
if !res.Ok {
|
||||
return 0, fmt.Errorf(string(res.Result))
|
||||
}
|
||||
|
||||
var admins []*repo.Admin
|
||||
if err := json.Unmarshal(res.Result, &admins); err != nil {
|
||||
return 0, fmt.Errorf(err.Error())
|
||||
}
|
||||
|
||||
electorateNum := uint64(0)
|
||||
for _, admin := range admins {
|
||||
electorateNum = electorateNum + admin.Weight
|
||||
}
|
||||
return electorateNum, nil
|
||||
}
|
||||
|
||||
func (g *Governance) getThresholdNum(electorateNum uint64, proposalTyp ProposalType) (uint64, error) {
|
||||
if err := checkProposalType(proposalTyp); err != nil {
|
||||
return 0, fmt.Errorf(err.Error())
|
||||
}
|
||||
ps := ProposalStrategy{}
|
||||
if !g.GetObject(string(proposalTyp), &ps) {
|
||||
// SimpleMajority is used by default
|
||||
ps.Typ = SimpleMajority
|
||||
ps.ParticipateThreshold = 0.75
|
||||
g.AddObject(string(proposalTyp), ps)
|
||||
}
|
||||
|
||||
return uint64(math.Ceil(float64(electorateNum) * ps.ParticipateThreshold)), nil
|
||||
}
|
||||
|
||||
// ModifyProposal modify a proposal
|
||||
func (g *Governance) ModifyProposal(id, des string, typ string, extra []byte) *boltvm.Response {
|
||||
en, err := g.getElectorateNum()
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
tn, err := g.getThresholdNum(en, ProposalType(typ))
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
p := &Proposal{
|
||||
Id: id,
|
||||
Des: des,
|
||||
Typ: ProposalType(typ),
|
||||
Status: PROPOSED,
|
||||
BallotMap: make(map[string]Ballot, 0),
|
||||
ApproveNum: 0,
|
||||
AgainstNum: 0,
|
||||
ElectorateNum: en,
|
||||
ThresholdNum: tn,
|
||||
Extra: extra,
|
||||
}
|
||||
|
||||
if err := checkProposalInfo(p); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
if !g.Has(ProposalKey(p.Id)) {
|
||||
return boltvm.Error(fmt.Sprintf("proposal does not exists"))
|
||||
}
|
||||
|
||||
g.SetObject(ProposalKey(p.Id), *p)
|
||||
return boltvm.Success(nil)
|
||||
}
|
||||
|
||||
// GetProposal query proposal by id
|
||||
func (g *Governance) GetProposal(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
pData, err := json.Marshal(p)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(pData)
|
||||
}
|
||||
|
||||
// Query proposals by proposal type, returning a list of proposal for that type
|
||||
func (g *Governance) GetProposalsByFrom(from string) *boltvm.Response {
|
||||
ret, err := g.getProposalsByFrom(from)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
retData, err := json.Marshal(ret)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(retData)
|
||||
}
|
||||
|
||||
func (g *Governance) getProposalsByFrom(from string) ([]Proposal, error) {
|
||||
ok, datas := g.Query(PROPOSAL_PREFIX)
|
||||
if !ok {
|
||||
return make([]Proposal, 0), nil
|
||||
}
|
||||
|
||||
ret := make([]Proposal, 0)
|
||||
for _, d := range datas {
|
||||
p := Proposal{}
|
||||
if err := json.Unmarshal(d, &p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if from == p.Id[0:strings.Index(p.Id, "-")] {
|
||||
ret = append(ret, p)
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Query proposals by proposal type, returning a list of proposal for that type
|
||||
func (g *Governance) GetProposalsByTyp(typ string) *boltvm.Response {
|
||||
if err := checkProposalType(ProposalType(typ)); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
ret := make([]Proposal, 0)
|
||||
|
||||
ok, datas := g.Query(PROPOSAL_PREFIX)
|
||||
if ok {
|
||||
for _, d := range datas {
|
||||
p := Proposal{}
|
||||
if err := json.Unmarshal(d, &p); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
if ProposalType(typ) == p.Typ {
|
||||
ret = append(ret, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retData, err := json.Marshal(ret)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(retData)
|
||||
}
|
||||
|
||||
// Query proposals based on proposal status, returning a list of proposal for that status
|
||||
func (g *Governance) GetProposalsByStatus(status string) *boltvm.Response {
|
||||
if err := checkProposalStauts(ProposalStatus(status)); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
ret := make([]Proposal, 0)
|
||||
|
||||
ok, datas := g.Query(PROPOSAL_PREFIX)
|
||||
if ok {
|
||||
for _, d := range datas {
|
||||
p := Proposal{}
|
||||
if err := json.Unmarshal(d, &p); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
if ProposalStatus(status) == p.Status {
|
||||
ret = append(ret, p)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
retData, err := json.Marshal(ret)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(retData)
|
||||
}
|
||||
|
||||
// Get proposal description information
|
||||
func (g *Governance) GetDes(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(p.Des))
|
||||
}
|
||||
|
||||
// Get Proposal Type
|
||||
func (g *Governance) GetTyp(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(p.Typ))
|
||||
}
|
||||
|
||||
// Get proposal status
|
||||
func (g *Governance) GetStatus(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(p.Status))
|
||||
}
|
||||
|
||||
// Get affirmative vote information
|
||||
func (g *Governance) GetApprove(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
approveMap := map[string]Ballot{}
|
||||
for k, v := range p.BallotMap {
|
||||
if v.Approve == BallotApprove {
|
||||
approveMap[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
retData, err := json.Marshal(approveMap)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(retData)
|
||||
}
|
||||
|
||||
// Get negative vote information
|
||||
func (g *Governance) GetAgainst(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
againstMap := map[string]Ballot{}
|
||||
for k, v := range p.BallotMap {
|
||||
if v.Approve == BallotReject {
|
||||
againstMap[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
retData, err := json.Marshal(againstMap)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(retData)
|
||||
}
|
||||
|
||||
// Get the total number of affirmative votes
|
||||
func (g *Governance) GetApproveNum(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(strconv.Itoa(int(p.ApproveNum))))
|
||||
}
|
||||
|
||||
// Get the total number of negative votes
|
||||
func (g *Governance) GetAgainstNum(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(strconv.Itoa(int(p.AgainstNum))))
|
||||
}
|
||||
|
||||
// Get the number of total votes, include all votes cast and all votes not cast
|
||||
func (g *Governance) GetElectorateNum(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(strconv.Itoa(int(p.ElectorateNum))))
|
||||
}
|
||||
|
||||
// Get the minimum number of votes required for the current voting strategy
|
||||
func (g *Governance) GetThresholdNum(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(strconv.Itoa(int(p.ThresholdNum))))
|
||||
}
|
||||
|
||||
// Get the number of people who have voted
|
||||
func (g *Governance) GetVotedNum(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(strconv.Itoa(len(p.BallotMap))))
|
||||
}
|
||||
|
||||
// Get voted information
|
||||
func (g *Governance) GetVoted(id string) *boltvm.Response {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
retData, err := json.Marshal(p.BallotMap)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
return boltvm.Success(retData)
|
||||
}
|
||||
|
||||
// Get Unvoted information
|
||||
func (g *Governance) GetUnvote(id string) *boltvm.Response {
|
||||
ret, err := g.getUnvote(id)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
retData, err := json.Marshal(ret)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
return boltvm.Success(retData)
|
||||
}
|
||||
|
||||
func (g *Governance) getUnvote(id string) ([]*repo.Admin, error) {
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return nil, fmt.Errorf("proposal does not exist")
|
||||
}
|
||||
|
||||
res := g.CrossInvoke(constant.RoleContractAddr.String(), "GetAdminRoles")
|
||||
if !res.Ok {
|
||||
return nil, fmt.Errorf("get admin roles error: " + string(res.Result))
|
||||
}
|
||||
var admins []*repo.Admin
|
||||
if err := json.Unmarshal(res.Result, &admins); err != nil {
|
||||
return nil, fmt.Errorf("get admin roles error: " + err.Error())
|
||||
}
|
||||
|
||||
ret := make([]*repo.Admin, 0)
|
||||
for _, admin := range admins {
|
||||
if _, ok := p.BallotMap[admin.Address]; !ok {
|
||||
ret = append(ret, admin)
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Get Unvoted information
|
||||
func (g *Governance) GetUnvoteNum(id string) *boltvm.Response {
|
||||
ret, err := g.getUnvote(id)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(strconv.Itoa(len(ret))))
|
||||
}
|
||||
|
||||
// Add someone's voting information (each person can only vote once)
|
||||
func (g *Governance) Vote(id, approve string, reason string) *boltvm.Response {
|
||||
addr := g.Caller()
|
||||
// 1. Determine if the proposal exists
|
||||
p := &Proposal{}
|
||||
if !g.GetObject(ProposalKey(id), p) {
|
||||
return boltvm.Error("proposal does not exist")
|
||||
}
|
||||
|
||||
// 2. Set vote
|
||||
if err := g.setVote(p, addr, approve, reason); err != nil {
|
||||
return boltvm.Error("get vote error: " + err.Error())
|
||||
}
|
||||
|
||||
// 3. Count votes
|
||||
// If the threshold for participation is reached, the result of the vote can be judged.
|
||||
// If the policy determines that the current vote has closed, the proposal state is modified.
|
||||
ok, err := g.countVote(p)
|
||||
if err != nil {
|
||||
return boltvm.Error("count vote error: " + err.Error())
|
||||
}
|
||||
if !ok {
|
||||
// the round of the voting is not over, wait the next vote
|
||||
return boltvm.Success(nil)
|
||||
}
|
||||
|
||||
// 4. Handle result
|
||||
switch p.Typ {
|
||||
case RuleMgr, NodeMgr, ServiceMgr:
|
||||
return boltvm.Error("waiting for subsequent implementation")
|
||||
default: // APPCHAIN_MGR
|
||||
res := g.CrossInvoke(constant.AppchainMgrContractAddr.String(), "Manager", pb.String(p.Des), pb.String(string(p.Status)), pb.Bytes(p.Extra))
|
||||
if !res.Ok {
|
||||
return boltvm.Error("cross invoke Manager error:" + string(res.Result))
|
||||
}
|
||||
return boltvm.Success(nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Set vote of an administrator
|
||||
func (g *Governance) setVote(p *Proposal, addr string, approve string, reason string) error {
|
||||
// Determine if the proposal has been approved or rejected
|
||||
if p.Status != PROPOSED {
|
||||
return fmt.Errorf("the vote on the proposal has been closed")
|
||||
}
|
||||
|
||||
// Determine if the administrator has voted
|
||||
if _, ok := p.BallotMap[addr]; ok {
|
||||
return fmt.Errorf("administrator of the address has voted")
|
||||
}
|
||||
|
||||
res := g.CrossInvoke(constant.RoleContractAddr.String(), "GetRoleWeight", pb.String(addr))
|
||||
if !res.Ok {
|
||||
return fmt.Errorf(string(res.Result))
|
||||
}
|
||||
num, err := strconv.Atoi(string(res.Result))
|
||||
if err != nil {
|
||||
return fmt.Errorf(err.Error())
|
||||
}
|
||||
|
||||
// Record Voting Information
|
||||
ballot := Ballot{
|
||||
VoterAddr: addr,
|
||||
Approve: approve,
|
||||
Num: uint64(num),
|
||||
Reason: reason,
|
||||
}
|
||||
p.BallotMap[addr] = ballot
|
||||
switch approve {
|
||||
case BallotApprove:
|
||||
p.ApproveNum = p.ApproveNum + uint64(num)
|
||||
case BallotReject:
|
||||
p.AgainstNum = p.AgainstNum + uint64(num)
|
||||
}
|
||||
|
||||
g.SetObject(ProposalKey(p.Id), *p)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Count votes to see if this round is over.
|
||||
// If the vote is over change the status of the proposal.
|
||||
func (g *Governance) countVote(p *Proposal) (bool, error) {
|
||||
// Get proposal strategy
|
||||
ps := ProposalStrategy{}
|
||||
if !g.GetObject(string(p.Typ), &ps) {
|
||||
// SimpleMajority is used by default
|
||||
ps.Typ = SimpleMajority
|
||||
ps.ParticipateThreshold = 0.75
|
||||
g.SetObject(string(p.Typ), ps)
|
||||
}
|
||||
|
||||
// Determine whether the participation threshold for the strategy has been met
|
||||
if p.ApproveNum+p.AgainstNum < p.ThresholdNum {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// Votes are counted according to strategy
|
||||
switch ps.Typ {
|
||||
case SuperMajorityApprove:
|
||||
// TODO: SUPER_MAJORITY_APPROVE
|
||||
return false, fmt.Errorf("this policy is not supported currently")
|
||||
case SuperMajorityAgainst:
|
||||
// TODO: SUPER_MAJORITY_AGAINST
|
||||
return false, fmt.Errorf("this policy is not supported currently")
|
||||
default: // SIMPLE_MAJORITY
|
||||
if p.ApproveNum > p.AgainstNum {
|
||||
p.Status = APPOVED
|
||||
} else {
|
||||
p.Status = REJECTED
|
||||
}
|
||||
g.SetObject(ProposalKey(p.Id), *p)
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Proposal strategy ===============================================================
|
||||
|
||||
type ProposalStrategyType string
|
||||
|
||||
const (
|
||||
SuperMajorityApprove ProposalStrategyType = "SuperMajorityApprove"
|
||||
SuperMajorityAgainst ProposalStrategyType = "SuperMajorityAgainst"
|
||||
SimpleMajority ProposalStrategyType = "SimpleMajority"
|
||||
)
|
||||
|
||||
type ProposalStrategy struct {
|
||||
Typ ProposalStrategyType `json:"typ"`
|
||||
// The minimum participation threshold.
|
||||
// Only when the number of voting participants reaches this proportion,
|
||||
// the proposal will take effect. That is, the proposal can be judged
|
||||
// according to the voting situation.
|
||||
ParticipateThreshold float64 `json:"participate_threshold"`
|
||||
Extra []byte `json:"extra"`
|
||||
}
|
||||
|
||||
func (g *Governance) NewProposalStrategy(typ string, participateThreshold float64, extra []byte) *boltvm.Response {
|
||||
ps := &ProposalStrategy{
|
||||
Typ: ProposalStrategyType(typ),
|
||||
ParticipateThreshold: participateThreshold,
|
||||
Extra: extra,
|
||||
}
|
||||
if err := checkStrategyInfo(ps); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
pData, err := json.Marshal(ps)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(pData)
|
||||
}
|
||||
|
||||
// set proposal strategy for a proposal type
|
||||
func (g *Governance) SetProposalStrategy(pt string, psData []byte) *boltvm.Response {
|
||||
ps := &ProposalStrategy{}
|
||||
if err := json.Unmarshal(psData, ps); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
if err := checkProposalType(ProposalType(pt)); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
if err := checkStrategyInfo(ps); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
g.SetObject(string(pt), *ps)
|
||||
return boltvm.Success(nil)
|
||||
}
|
||||
|
||||
func (g *Governance) GetProposalStrategy(pt string) *boltvm.Response {
|
||||
if err := checkProposalType(ProposalType(pt)); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
ps := &ProposalStrategy{}
|
||||
if !g.GetObject(string(pt), ps) {
|
||||
return boltvm.Error("strategy does not exists")
|
||||
}
|
||||
|
||||
pData, err := json.Marshal(ps)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
return boltvm.Success(pData)
|
||||
}
|
||||
|
||||
func (g *Governance) GetProposalStrategyType(pt string) *boltvm.Response {
|
||||
if err := checkProposalType(ProposalType(pt)); err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
ps := &ProposalStrategy{}
|
||||
if !g.GetObject(string(pt), ps) {
|
||||
return boltvm.Error("strategy does not exists")
|
||||
}
|
||||
|
||||
return boltvm.Success([]byte(ps.Typ))
|
||||
}
|
||||
|
||||
// Key ====================================================================
|
||||
func ProposalKey(id string) string {
|
||||
return fmt.Sprintf("%s-%s", PROPOSAL_PREFIX, id)
|
||||
}
|
||||
|
||||
// Check info =============================================================
|
||||
func checkProposalInfo(p *Proposal) error {
|
||||
if checkProposalType(p.Typ) != nil || strings.Index(p.Id, "-") == -1 || p.Id[0:strings.Index(p.Id, "-")] == "" {
|
||||
return fmt.Errorf("illegal proposal info")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkProposalType(pt ProposalType) error {
|
||||
if pt != AppchainMgr &&
|
||||
pt != RuleMgr &&
|
||||
pt != NodeMgr &&
|
||||
pt != ServiceMgr {
|
||||
return fmt.Errorf("illegal proposal type")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkProposalStauts(ps ProposalStatus) error {
|
||||
if ps != PROPOSED &&
|
||||
ps != APPOVED &&
|
||||
ps != REJECTED {
|
||||
return fmt.Errorf("illegal proposal status")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkStrategyInfo(ps *ProposalStrategy) error {
|
||||
if checkStrategyType(ps.Typ) != nil ||
|
||||
ps.ParticipateThreshold < 0 ||
|
||||
ps.ParticipateThreshold > 1 {
|
||||
return fmt.Errorf("illegal proposal strategy info")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkStrategyType(pst ProposalStrategyType) error {
|
||||
if pst != SuperMajorityApprove &&
|
||||
pst != SuperMajorityAgainst &&
|
||||
pst != SimpleMajority {
|
||||
return fmt.Errorf("illegal proposal strategy type")
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -23,16 +23,16 @@ type BxhValidators struct {
|
|||
Addresses []string `json:"addresses"`
|
||||
}
|
||||
|
||||
func (x *InterchainManager) Register() *boltvm.Response {
|
||||
interchain, ok := x.getInterchain(x.Caller())
|
||||
func (x *InterchainManager) Register(chainId string) *boltvm.Response {
|
||||
interchain, ok := x.getInterchain(chainId)
|
||||
if !ok {
|
||||
interchain = &pb.Interchain{
|
||||
ID: x.Caller(),
|
||||
ID: chainId,
|
||||
InterchainCounter: make(map[string]uint64),
|
||||
ReceiptCounter: make(map[string]uint64),
|
||||
SourceReceiptCounter: make(map[string]uint64),
|
||||
}
|
||||
x.setInterchain(x.Caller(), interchain)
|
||||
x.setInterchain(chainId, interchain)
|
||||
}
|
||||
body, err := interchain.Marshal()
|
||||
if err != nil {
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/meshplus/bitxhub-core/boltvm"
|
||||
"github.com/meshplus/bitxhub-model/constant"
|
||||
"github.com/meshplus/bitxhub/internal/repo"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -17,11 +18,11 @@ type Role struct {
|
|||
}
|
||||
|
||||
func (r *Role) GetRole() *boltvm.Response {
|
||||
var addrs []string
|
||||
r.GetObject(adminRolesKey, &addrs)
|
||||
var admins []*repo.Admin
|
||||
r.GetObject(adminRolesKey, &admins)
|
||||
|
||||
for _, addr := range addrs {
|
||||
if addr == r.Caller() {
|
||||
for _, admin := range admins {
|
||||
if admin.Address == r.Caller() {
|
||||
return boltvm.Success([]byte("admin"))
|
||||
}
|
||||
}
|
||||
|
@ -35,11 +36,11 @@ func (r *Role) GetRole() *boltvm.Response {
|
|||
}
|
||||
|
||||
func (r *Role) IsAdmin(address string) *boltvm.Response {
|
||||
var addrs []string
|
||||
r.GetObject(adminRolesKey, &addrs)
|
||||
var admins []*repo.Admin
|
||||
r.GetObject(adminRolesKey, &admins)
|
||||
|
||||
for _, addr := range addrs {
|
||||
if addr == address {
|
||||
for _, admin := range admins {
|
||||
if admin.Address == address {
|
||||
return boltvm.Success([]byte(strconv.FormatBool(true)))
|
||||
}
|
||||
}
|
||||
|
@ -48,10 +49,10 @@ func (r *Role) IsAdmin(address string) *boltvm.Response {
|
|||
}
|
||||
|
||||
func (r *Role) GetAdminRoles() *boltvm.Response {
|
||||
var addrs []string
|
||||
r.GetObject(adminRolesKey, &addrs)
|
||||
var admins []*repo.Admin
|
||||
r.GetObject(adminRolesKey, &admins)
|
||||
|
||||
ret, err := json.Marshal(addrs)
|
||||
ret, err := json.Marshal(admins)
|
||||
if err != nil {
|
||||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
@ -65,6 +66,27 @@ func (r *Role) SetAdminRoles(addrs string) *boltvm.Response {
|
|||
return boltvm.Error(err.Error())
|
||||
}
|
||||
|
||||
r.SetObject(adminRolesKey, as)
|
||||
admins := make([]*repo.Admin, 0)
|
||||
for _, addr := range as {
|
||||
admins = append(admins, &repo.Admin{
|
||||
Address: addr,
|
||||
Weight: 1,
|
||||
})
|
||||
}
|
||||
|
||||
r.SetObject(adminRolesKey, admins)
|
||||
return boltvm.Success(nil)
|
||||
}
|
||||
|
||||
func (r *Role) GetRoleWeight(address string) *boltvm.Response {
|
||||
var admins []*repo.Admin
|
||||
r.GetObject(adminRolesKey, &admins)
|
||||
|
||||
for _, admin := range admins {
|
||||
if admin.Address == address {
|
||||
return boltvm.Success([]byte(strconv.Itoa(int(admin.Weight))))
|
||||
}
|
||||
}
|
||||
|
||||
return boltvm.Error("account at the address does not exist:" + address)
|
||||
}
|
||||
|
|
|
@ -268,6 +268,12 @@ func registerBoltContracts() map[string]agency.Contract {
|
|||
Address: constant.InterRelayBrokerContractAddr.Address().String(),
|
||||
Contract: &contracts.InterRelayBroker{},
|
||||
},
|
||||
{
|
||||
Enabled: true,
|
||||
Name: "governance service",
|
||||
Address: constant.GovernanceContractAddr.Address().String(),
|
||||
Contract: &contracts.Governance{},
|
||||
},
|
||||
}
|
||||
|
||||
ContractsInfo := agency.GetRegisteredContractInfo()
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
|
||||
"github.com/meshplus/bitxhub-kit/bytesutil"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
"github.com/meshplus/bitxhub-model/constant"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/meshplus/bitxhub/internal/ledger"
|
||||
"github.com/meshplus/bitxhub/internal/repo"
|
||||
|
@ -16,17 +17,21 @@ var (
|
|||
|
||||
// Initialize initialize block
|
||||
func Initialize(genesis *repo.Genesis, lg ledger.Ledger) error {
|
||||
for _, addr := range genesis.Addresses {
|
||||
lg.SetBalance(types.NewAddressByStr(addr), 100000000)
|
||||
}
|
||||
|
||||
body, err := json.Marshal(genesis.Addresses)
|
||||
body, err := json.Marshal(genesis.Admins)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
lg.SetState(roleAddr, []byte("admin-roles"), body)
|
||||
|
||||
for _, admin := range genesis.Admins {
|
||||
lg.SetBalance(types.NewAddressByStr(admin.Address), 100000000)
|
||||
}
|
||||
|
||||
for k, v := range genesis.Strategy {
|
||||
lg.SetState(constant.GovernanceContractAddr.Address(), []byte(k), []byte(v))
|
||||
}
|
||||
|
||||
accounts, journal := lg.FlushDirtyDataAndComputeJournal()
|
||||
block := &pb.Block{
|
||||
BlockHeader: &pb.BlockHeader{
|
||||
|
|
|
@ -104,7 +104,13 @@ type LogModule struct {
|
|||
}
|
||||
|
||||
type Genesis struct {
|
||||
Addresses []string `json:"addresses" toml:"addresses"`
|
||||
Admins []*Admin `json:"admins" toml:"admins"`
|
||||
Strategy map[string]string `json:"strategy" toml:"strategy"`
|
||||
}
|
||||
|
||||
type Admin struct {
|
||||
Address string `json:"address" toml:"address"`
|
||||
Weight uint64 `json:"weight" toml:"weight"`
|
||||
}
|
||||
|
||||
type Cert struct {
|
||||
|
|
|
@ -90,8 +90,8 @@ func (config *NetworkConfig) GetVpInfos() map[uint64]*pb.VpInfo {
|
|||
// GetVpGenesisAccount gets genesis address from network config
|
||||
func (config *NetworkConfig) GetVpGenesisAccount() map[uint64]types.Address {
|
||||
m := make(map[uint64]types.Address)
|
||||
for i, address := range config.Genesis.Addresses {
|
||||
m[uint64(i)+1] = *types.NewAddressByStr(address)
|
||||
for i, admin := range config.Genesis.Admins {
|
||||
m[uint64(i)+1] = *types.NewAddressByStr(admin.Address)
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
|
|
@ -9,10 +9,26 @@ import (
|
|||
|
||||
func TestNetworkConfig(t *testing.T) {
|
||||
path := "./testdata"
|
||||
cfg, err := loadNetworkConfig(path, Genesis{Addresses: []string{"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
|
||||
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"}})
|
||||
cfg, err := loadNetworkConfig(path, Genesis{
|
||||
Admins: []*Admin{
|
||||
&Admin{
|
||||
Address: "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
Weight: 1,
|
||||
},
|
||||
&Admin{
|
||||
Address: "0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
Weight: 1,
|
||||
},
|
||||
&Admin{
|
||||
Address: "0x97c8B516D19edBf575D72a172Af7F418BE498C37",
|
||||
Weight: 1,
|
||||
},
|
||||
&Admin{
|
||||
Address: "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8",
|
||||
Weight: 1,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
require.Nil(t, err)
|
||||
peers, err := cfg.GetNetworkPeers()
|
||||
|
|
|
@ -6,12 +6,11 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
appchainMgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
||||
"github.com/meshplus/bitxhub-core/validator/mock_validator"
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-kit/log"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
"github.com/meshplus/bitxhub-model/constant"
|
||||
|
@ -123,11 +122,10 @@ func TestVerifyPool_CheckProof(t *testing.T) {
|
|||
|
||||
func TestVerifyPool_CheckProof2(t *testing.T) {
|
||||
mockCtl := gomock.NewController(t)
|
||||
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
||||
mockEngine := mock_validator.NewMockEngine(mockCtl)
|
||||
|
||||
chain := &appchainMgr.Appchain{
|
||||
Status: appchainMgr.APPROVED,
|
||||
Status: appchainMgr.AppchainAvailable,
|
||||
ID: from,
|
||||
Name: "appchain" + from,
|
||||
Validators: "",
|
||||
|
@ -154,10 +152,6 @@ func TestVerifyPool_CheckProof2(t *testing.T) {
|
|||
addrsData, err := json.Marshal(bv)
|
||||
require.Nil(t, err)
|
||||
|
||||
chainData, err := json.Marshal(chain)
|
||||
require.Nil(t, err)
|
||||
|
||||
mockLedger.EXPECT().GetState(constant.AppchainMgrContractAddr.Address(), gomock.Any()).Return(true, chainData)
|
||||
mockEngine.EXPECT().Validate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil).AnyTimes()
|
||||
|
||||
ibtp := getIBTP(t, 1, pb.IBTP_RECEIPT_SUCCESS, nil)
|
||||
|
@ -194,12 +188,6 @@ func TestVerifyPool_CheckProof3(t *testing.T) {
|
|||
mockLedger := mock_ledger.NewMockLedger(mockCtl)
|
||||
mockEngine := mock_validator.NewMockEngine(mockCtl)
|
||||
|
||||
rl := &contracts.Rule{
|
||||
Address: contract,
|
||||
}
|
||||
rlData, err := json.Marshal(rl)
|
||||
require.Nil(t, err)
|
||||
|
||||
mockLedger.EXPECT().GetState(constant.AppchainMgrContractAddr.Address(), gomock.Any()).Return(true, []byte("123"))
|
||||
mockEngine.EXPECT().Validate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(true, nil).AnyTimes()
|
||||
|
||||
|
@ -219,7 +207,6 @@ func TestVerifyPool_CheckProof3(t *testing.T) {
|
|||
Extra: proof,
|
||||
}
|
||||
|
||||
mockLedger.EXPECT().GetState(constant.RuleManagerContractAddr.Address(), gomock.Any()).Return(true, rlData)
|
||||
txWithIBTP.TransactionHash = txWithIBTP.Hash()
|
||||
ok, err := vp.CheckProof(txWithIBTP)
|
||||
require.NotNil(t, err)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/meshplus/bitxhub-core/agency"
|
||||
appchain_mgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
||||
"github.com/meshplus/bitxhub-core/validator/mock_validator"
|
||||
"github.com/meshplus/bitxhub-kit/log"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
|
@ -69,6 +70,12 @@ func GetBoltContracts() map[string]agency.Contract {
|
|||
Address: constant.AssetExchangeContractAddr.Address().String(),
|
||||
Contract: &contracts.AssetExchange{},
|
||||
},
|
||||
{
|
||||
Enabled: true,
|
||||
Name: "governance service",
|
||||
Address: constant.GovernanceContractAddr.Address().String(),
|
||||
Contract: &contracts.Governance{},
|
||||
},
|
||||
}
|
||||
|
||||
ContractsInfo := agency.GetRegisteredContractInfo()
|
||||
|
@ -85,7 +92,7 @@ func GetBoltContracts() map[string]agency.Contract {
|
|||
|
||||
func TestRegister(t *testing.T) {
|
||||
registers := GetBoltContracts()
|
||||
require.Equal(t, len(registers), 7)
|
||||
require.Equal(t, len(registers), 8)
|
||||
|
||||
contract, err := GetBoltContract(constant.StoreContractAddr.Address().String(), registers)
|
||||
require.Nil(t, err)
|
||||
|
@ -115,7 +122,23 @@ func TestBoltVM_Run(t *testing.T) {
|
|||
|
||||
data := make([][]byte, 0)
|
||||
data = append(data, []byte("1"))
|
||||
mockLedger.EXPECT().QueryByPrefix(gomock.Any(), gomock.Any()).Return(true, data).AnyTimes()
|
||||
proposalData, err := json.Marshal(&contracts.Proposal{
|
||||
Id: from + "-0",
|
||||
})
|
||||
require.Nil(t, err)
|
||||
proposals := make([][]byte, 0)
|
||||
proposals = append(proposals, proposalData)
|
||||
mockLedger.EXPECT().QueryByPrefix(gomock.Any(), contracts.PROPOSAL_PREFIX).Return(true, proposals).AnyTimes()
|
||||
mockLedger.EXPECT().QueryByPrefix(gomock.Any(), appchain_mgr.PREFIX).Return(true, data).AnyTimes()
|
||||
mockLedger.EXPECT().GetState(gomock.Any(), gomock.Any()).DoAndReturn(func(addr *types.Address, key []byte) (bool, []byte) {
|
||||
switch addr.String() {
|
||||
case constant.AppchainMgrContractAddr.String():
|
||||
return false, nil
|
||||
case constant.InterchainContractAddr.String():
|
||||
return false, nil
|
||||
}
|
||||
return false, nil
|
||||
}).Times(1)
|
||||
mockLedger.EXPECT().GetState(gomock.Any(), gomock.Any()).DoAndReturn(func(addr *types.Address, key []byte) (bool, []byte) {
|
||||
switch addr.String() {
|
||||
case constant.AppchainMgrContractAddr.String():
|
||||
|
|
|
@ -4,8 +4,10 @@ import (
|
|||
"encoding/json"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/meshplus/bitxhub/internal/executor/contracts"
|
||||
|
||||
appchainMgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-kit/types"
|
||||
|
@ -18,22 +20,10 @@ import (
|
|||
|
||||
type RegisterAppchain struct {
|
||||
suite.Suite
|
||||
api api.CoreAPI
|
||||
privKey crypto.PrivateKey
|
||||
from *types.Address
|
||||
}
|
||||
|
||||
type Appchain struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Validators string `json:"validators"`
|
||||
ConsensusType int32 `json:"consensus_type"`
|
||||
// 0 => registered, 1 => approved, -1 => rejected
|
||||
Status int32 `json:"status"`
|
||||
ChainType string `json:"chain_type"`
|
||||
Desc string `json:"desc"`
|
||||
Version string `json:"version"`
|
||||
PublicKey string `json:"public_key"`
|
||||
api api.CoreAPI
|
||||
privKey crypto.PrivateKey
|
||||
from *types.Address
|
||||
normalNonce uint64
|
||||
}
|
||||
|
||||
func (suite *RegisterAppchain) SetupSuite() {
|
||||
|
@ -43,6 +33,7 @@ func (suite *RegisterAppchain) SetupSuite() {
|
|||
|
||||
suite.from, err = suite.privKey.PublicKey().Address()
|
||||
suite.Require().Nil(err)
|
||||
suite.normalNonce = 1
|
||||
}
|
||||
|
||||
// Appchain registers in bitxhub
|
||||
|
@ -51,7 +42,7 @@ func (suite *RegisterAppchain) TestRegisterAppchain() {
|
|||
suite.Require().Nil(err)
|
||||
|
||||
args := []*pb.Arg{
|
||||
pb.String(""),
|
||||
pb.String("validators"),
|
||||
pb.Int32(0),
|
||||
pb.String("hyperchain"),
|
||||
pb.String("税务链"),
|
||||
|
@ -60,9 +51,19 @@ func (suite *RegisterAppchain) TestRegisterAppchain() {
|
|||
pb.String(string(pub)),
|
||||
}
|
||||
|
||||
ret, err := invokeBVMContract(suite.api, suite.privKey, 1, constant.AppchainMgrContractAddr.Address(), "Register", args...)
|
||||
ret, err := invokeBVMContract(suite.api, suite.privKey, suite.normalNonce, constant.AppchainMgrContractAddr.Address(), "Register", args...)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
suite.normalNonce++
|
||||
registerRes := &contracts.RegisterResult{}
|
||||
err = json.Unmarshal(ret.Ret, registerRes)
|
||||
suite.Require().Nil(err)
|
||||
chainId := registerRes.ChainID
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, suite.privKey, suite.normalNonce, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(chainId))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
suite.normalNonce++
|
||||
suite.Require().Equal("hyperchain", gjson.Get(string(ret.Ret), "chain_type").String())
|
||||
}
|
||||
|
||||
|
@ -92,11 +93,7 @@ func (suite *RegisterAppchain) TestFetchAppchains() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
appchain := Appchain{}
|
||||
err = json.Unmarshal(ret.Ret, &appchain)
|
||||
suite.Require().Nil(err)
|
||||
id1 := appchain.ID
|
||||
id1 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
args = []*pb.Arg{
|
||||
pb.String(""),
|
||||
|
@ -126,7 +123,7 @@ func (suite *RegisterAppchain) TestFetchAppchains() {
|
|||
suite.Require().GreaterOrEqual(num, len(result.Array()))
|
||||
k2Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "CountApprovedAppchains")
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "CountAvailableAppchains")
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess())
|
||||
num, err = strconv.Atoi(string(ret.Ret))
|
||||
|
@ -134,12 +131,6 @@ func (suite *RegisterAppchain) TestFetchAppchains() {
|
|||
suite.Require().EqualValues(0, num)
|
||||
k2Nonce++
|
||||
|
||||
//FetchAuditRecords
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "FetchAuditRecords", pb.String(string(id1)))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess())
|
||||
k1Nonce++
|
||||
|
||||
//AppChain
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "Appchain")
|
||||
suite.Require().Nil(err)
|
||||
|
@ -194,11 +185,15 @@ func (suite *RegisterAppchain) TestGetPubKeyByChainID() {
|
|||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
suite.Require().Nil(err)
|
||||
k2Nonce++
|
||||
id2 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
appchain2 := Appchain{}
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(id2))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k2Nonce++
|
||||
appchain2 := appchainMgr.Appchain{}
|
||||
err = json.Unmarshal(ret.Ret, &appchain2)
|
||||
suite.Require().Nil(err)
|
||||
id2 := appchain2.ID
|
||||
|
||||
//GetPubKeyByChainID
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "GetPubKeyByChainID", pb.String(string(id2)))
|
||||
|
@ -229,13 +224,8 @@ func (suite *RegisterAppchain) TestUpdateAppchains() {
|
|||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
appchain := Appchain{}
|
||||
err = json.Unmarshal(ret.Ret, &appchain)
|
||||
suite.Require().Nil(err)
|
||||
id1 := appchain.ID
|
||||
|
||||
//Admin Chain
|
||||
path := "./test_data/config/node1/key.json"
|
||||
path := "./test_data/config/node2/key.json"
|
||||
keyPath := filepath.Join(path)
|
||||
priAdmin, err := asym.RestorePrivateKey(keyPath, "bitxhub")
|
||||
suite.Require().Nil(err)
|
||||
|
@ -257,16 +247,6 @@ func (suite *RegisterAppchain) TestUpdateAppchains() {
|
|||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce++
|
||||
|
||||
//Audit
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin, adminNonce, constant.AppchainMgrContractAddr.Address(), "Audit",
|
||||
pb.String(string(id1)),
|
||||
pb.Int32(1),
|
||||
pb.String("通过"),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess())
|
||||
adminNonce++
|
||||
|
||||
//UpdateAppchain
|
||||
args = []*pb.Arg{
|
||||
pb.String(""),
|
||||
|
@ -279,10 +259,11 @@ func (suite *RegisterAppchain) TestUpdateAppchains() {
|
|||
}
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "UpdateAppchain", args...)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess())
|
||||
// this appchain is registing, can not be updated
|
||||
suite.Require().False(ret.IsSuccess())
|
||||
k1Nonce++
|
||||
}
|
||||
|
||||
func TestRegisterAppchain(t *testing.T) {
|
||||
suite.Run(t, &RegisterAppchain{})
|
||||
}
|
||||
//func TestRegisterAppchain(t *testing.T) {
|
||||
// suite.Run(t, &RegisterAppchain{})
|
||||
//}
|
||||
|
|
|
@ -2,11 +2,15 @@ package tester
|
|||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/meshplus/bitxhub/internal/executor/contracts"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
|
||||
appchain_mgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
||||
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-model/constant"
|
||||
|
@ -53,6 +57,21 @@ func (suite *Interchain) TestHandleIBTP() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
id1 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(id1))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "Manager",
|
||||
pb.String(string(appchain_mgr.EventRegister)),
|
||||
pb.String(string(contracts.APPOVED)),
|
||||
pb.Bytes(ret.Ret),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "Register",
|
||||
pb.String(""),
|
||||
|
@ -66,6 +85,21 @@ func (suite *Interchain) TestHandleIBTP() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess())
|
||||
k2Nonce++
|
||||
id2 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(id2))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k2Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "Manager",
|
||||
pb.String(string(appchain_mgr.EventRegister)),
|
||||
pb.String(string(contracts.APPOVED)),
|
||||
pb.Bytes(ret.Ret),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k2Nonce++
|
||||
|
||||
// deploy rule
|
||||
bytes, err := ioutil.ReadFile("./test_data/hpc_rule.wasm")
|
||||
|
@ -126,6 +160,21 @@ func (suite *Interchain) TestGetIBTPByID() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
id1 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(id1))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "Manager",
|
||||
pb.String(string(appchain_mgr.EventRegister)),
|
||||
pb.String(string(contracts.APPOVED)),
|
||||
pb.Bytes(ret.Ret),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "Register",
|
||||
pb.String(""),
|
||||
|
@ -139,6 +188,21 @@ func (suite *Interchain) TestGetIBTPByID() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k2Nonce++
|
||||
id2 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(id2))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k2Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "Manager",
|
||||
pb.String(string(appchain_mgr.EventRegister)),
|
||||
pb.String(string(contracts.APPOVED)),
|
||||
pb.Bytes(ret.Ret),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k2Nonce++
|
||||
|
||||
contractByte, err := ioutil.ReadFile("./test_data/fabric_policy.wasm")
|
||||
suite.Require().Nil(err)
|
||||
|
@ -188,21 +252,6 @@ func (suite *Interchain) TestGetIBTPByID() {
|
|||
k1Nonce++
|
||||
}
|
||||
|
||||
func (suite *Interchain) TestAudit() {
|
||||
k, err := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
suite.Require().Nil(err)
|
||||
kNonce := uint64(1)
|
||||
|
||||
ret, err := invokeBVMContract(suite.api, k, kNonce, constant.AppchainMgrContractAddr.Address(), "Audit",
|
||||
pb.String("0x123"),
|
||||
pb.Int32(1),
|
||||
pb.String("通过"),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Contains(string(ret.Ret), "caller is not an admin account")
|
||||
kNonce++
|
||||
}
|
||||
|
||||
func (suite *Interchain) TestInterchain() {
|
||||
k1, err := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
suite.Require().Nil(err)
|
||||
|
@ -223,11 +272,21 @@ func (suite *Interchain) TestInterchain() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
id1 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
appchain := Appchain{}
|
||||
err = json.Unmarshal(ret.Ret, &appchain)
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(id1))
|
||||
suite.Require().Nil(err)
|
||||
id1 := appchain.ID
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.AppchainMgrContractAddr.Address(), "Manager",
|
||||
pb.String(string(appchain_mgr.EventRegister)),
|
||||
pb.String(string(contracts.APPOVED)),
|
||||
pb.Bytes(ret.Ret),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k1, k1Nonce, constant.InterchainContractAddr.Address(), "Interchain")
|
||||
suite.Require().Nil(err)
|
||||
|
@ -246,14 +305,16 @@ func (suite *Interchain) TestInterchain() {
|
|||
func (suite *Interchain) TestRegister() {
|
||||
k1, err := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
suite.Require().Nil(err)
|
||||
from1, err := k1.PublicKey().Address()
|
||||
suite.Require().Nil(err)
|
||||
k1Nonce := uint64(1)
|
||||
|
||||
ret, err := invokeBVMContract(suite.api, k1, k1Nonce, constant.InterchainContractAddr.Address(), "Register")
|
||||
ret, err := invokeBVMContract(suite.api, k1, k1Nonce, constant.InterchainContractAddr.Address(), "Register", pb.String(from1.Address))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
}
|
||||
|
||||
func TestInterchain(t *testing.T) {
|
||||
suite.Run(t, &Interchain{})
|
||||
}
|
||||
//func TestInterchain(t *testing.T) {
|
||||
// suite.Run(t, &Interchain{})
|
||||
//}
|
||||
|
|
|
@ -136,11 +136,7 @@ func (suite *Role) TestGetRuleAddress() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k1Nonce++
|
||||
|
||||
appchain := Appchain{}
|
||||
err = json.Unmarshal(ret.Ret, &appchain)
|
||||
suite.Require().Nil(err)
|
||||
id1 := appchain.ID
|
||||
id1 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
ret, err = invokeBVMContract(suite.api, k2, k2Nonce, constant.AppchainMgrContractAddr.Address(), "Register",
|
||||
pb.String(""),
|
||||
|
@ -154,11 +150,7 @@ func (suite *Role) TestGetRuleAddress() {
|
|||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
k2Nonce++
|
||||
|
||||
appchain = Appchain{}
|
||||
err = json.Unmarshal(ret.Ret, &appchain)
|
||||
suite.Require().Nil(err)
|
||||
id2 := appchain.ID
|
||||
id2 := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
|
||||
// deploy rule
|
||||
bytes, err := ioutil.ReadFile("./test_data/hpc_rule.wasm")
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
package tester
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
appchainMgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
||||
"github.com/meshplus/bitxhub-kit/crypto"
|
||||
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
||||
"github.com/meshplus/bitxhub-model/constant"
|
||||
"github.com/meshplus/bitxhub-model/pb"
|
||||
"github.com/meshplus/bitxhub/internal/coreapi/api"
|
||||
"github.com/meshplus/bitxhub/internal/executor/contracts"
|
||||
"github.com/stretchr/testify/suite"
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
type Governance struct {
|
||||
suite.Suite
|
||||
api api.CoreAPI
|
||||
privKey crypto.PrivateKey
|
||||
}
|
||||
|
||||
func (suite *Governance) SetupSuite() {
|
||||
}
|
||||
|
||||
func (suite *Governance) TestGovernance() {
|
||||
path1 := "./test_data/config/node1/key.json"
|
||||
path2 := "./test_data/config/node2/key.json"
|
||||
path3 := "./test_data/config/node3/key.json"
|
||||
path4 := "./test_data/config/node4/key.json"
|
||||
keyPath1 := filepath.Join(path1)
|
||||
keyPath2 := filepath.Join(path2)
|
||||
keyPath3 := filepath.Join(path3)
|
||||
keyPath4 := filepath.Join(path4)
|
||||
priAdmin1, err := asym.RestorePrivateKey(keyPath1, "bitxhub")
|
||||
suite.Require().Nil(err)
|
||||
priAdmin2, err := asym.RestorePrivateKey(keyPath2, "bitxhub")
|
||||
suite.Require().Nil(err)
|
||||
priAdmin3, err := asym.RestorePrivateKey(keyPath3, "bitxhub")
|
||||
suite.Require().Nil(err)
|
||||
priAdmin4, err := asym.RestorePrivateKey(keyPath4, "bitxhub")
|
||||
suite.Require().Nil(err)
|
||||
fromAdmin1, err := priAdmin1.PublicKey().Address()
|
||||
suite.Require().Nil(err)
|
||||
fromAdmin2, err := priAdmin2.PublicKey().Address()
|
||||
suite.Require().Nil(err)
|
||||
fromAdmin3, err := priAdmin3.PublicKey().Address()
|
||||
suite.Require().Nil(err)
|
||||
fromAdmin4, err := priAdmin4.PublicKey().Address()
|
||||
suite.Require().Nil(err)
|
||||
adminNonce1 := suite.api.Broker().GetPendingNonceByAccount(fromAdmin1.String())
|
||||
adminNonce2 := suite.api.Broker().GetPendingNonceByAccount(fromAdmin2.String())
|
||||
adminNonce3 := suite.api.Broker().GetPendingNonceByAccount(fromAdmin3.String())
|
||||
adminNonce4 := suite.api.Broker().GetPendingNonceByAccount(fromAdmin4.String())
|
||||
|
||||
appchainPri, err := asym.GenerateKeyPair(crypto.Secp256k1)
|
||||
suite.Require().Nil(err)
|
||||
appchainPub, err := appchainPri.PublicKey().Bytes()
|
||||
suite.Require().Nil(err)
|
||||
appchainNonce := uint64(1)
|
||||
|
||||
// 1. Register ==============================================
|
||||
ret, err := invokeBVMContract(suite.api, appchainPri, appchainNonce, constant.AppchainMgrContractAddr.Address(), "Register",
|
||||
pb.String("validators"),
|
||||
pb.Int32(0),
|
||||
pb.String("hyperchain"),
|
||||
pb.String("税务链"),
|
||||
pb.String("趣链税务链"),
|
||||
pb.String("1.8"),
|
||||
pb.String(string(appchainPub)),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
appchainNonce++
|
||||
chainId := gjson.Get(string(ret.Ret), "chain_id").String()
|
||||
registerProposalId := gjson.Get(string(ret.Ret), "proposal_id").String()
|
||||
|
||||
// repeated registration
|
||||
ret, err = invokeBVMContract(suite.api, appchainPri, appchainNonce, constant.AppchainMgrContractAddr.Address(), "Register",
|
||||
pb.String("validators"),
|
||||
pb.Int32(0),
|
||||
pb.String("hyperchain"),
|
||||
pb.String("税务链"),
|
||||
pb.String("趣链税务链"),
|
||||
pb.String("1.8"),
|
||||
pb.String(string(appchainPub)),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().False(ret.IsSuccess(), string(ret.Ret))
|
||||
appchainNonce++
|
||||
|
||||
// get proposal
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.GovernanceContractAddr.Address(), "GetProposal", pb.String(registerProposalId))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
p := contracts.Proposal{}
|
||||
err = json.Unmarshal(ret.Ret, &p)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().Equal("register", p.Des, "des")
|
||||
|
||||
// get chain status
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(chainId))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
chain := appchainMgr.Appchain{}
|
||||
err = json.Unmarshal(ret.Ret, &chain)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().Equal(appchainMgr.AppchainRegisting, chain.Status)
|
||||
|
||||
// get role weight
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.RoleContractAddr.Address(), "GetRoleWeight", pb.String(fromAdmin1.Address))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
w, err := strconv.Atoi(string(ret.Ret))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().Equal(1, w, "weight")
|
||||
|
||||
// vote1: approve
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.GovernanceContractAddr.Address(), "Vote",
|
||||
pb.String(registerProposalId),
|
||||
pb.String(contracts.BallotApprove),
|
||||
pb.String("reason"),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
|
||||
// get ballot
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.GovernanceContractAddr.Address(), "GetBallot",
|
||||
pb.String(fromAdmin1.Address),
|
||||
pb.String(registerProposalId),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
b := &contracts.Ballot{}
|
||||
err = json.Unmarshal(ret.Ret, &b)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().Equal(string(contracts.APPOVED), b.Approve)
|
||||
|
||||
// vote2: reject
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin2, adminNonce2, constant.GovernanceContractAddr.Address(), "Vote",
|
||||
pb.String(registerProposalId),
|
||||
pb.String(contracts.BallotReject),
|
||||
pb.String("reason"),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce2++
|
||||
|
||||
// vote3: approve -> proposal approve
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin3, adminNonce3, constant.GovernanceContractAddr.Address(), "Vote",
|
||||
pb.String(registerProposalId),
|
||||
pb.String(contracts.BallotApprove),
|
||||
pb.String("reason"),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce3++
|
||||
|
||||
// vote4: error, the proposal is closed
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin4, adminNonce4, constant.GovernanceContractAddr.Address(), "Vote",
|
||||
pb.String(registerProposalId),
|
||||
pb.String(contracts.BallotApprove),
|
||||
pb.String("reason"),
|
||||
)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().False(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce4++
|
||||
|
||||
// get approve num
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.GovernanceContractAddr.Address(), "GetApproveNum", pb.String(registerProposalId))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
num, err := strconv.Atoi(string(ret.Ret))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().Equal(2, num, "approveNum")
|
||||
|
||||
// get against num
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.GovernanceContractAddr.Address(), "GetAgainstNum", pb.String(registerProposalId))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
num, err = strconv.Atoi(string(ret.Ret))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().Equal(1, num, "againstNum")
|
||||
|
||||
// get proposal status
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.GovernanceContractAddr.Address(), "GetStatus", pb.String(registerProposalId))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
proposalStatus := string(ret.Ret)
|
||||
suite.Require().Equal(contracts.APPOVED, contracts.ProposalStatus(proposalStatus))
|
||||
|
||||
// get chain status
|
||||
ret, err = invokeBVMContract(suite.api, priAdmin1, adminNonce1, constant.AppchainMgrContractAddr.Address(), "GetAppchain", pb.String(chainId))
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().True(ret.IsSuccess(), string(ret.Ret))
|
||||
adminNonce1++
|
||||
err = json.Unmarshal(ret.Ret, &chain)
|
||||
suite.Require().Nil(err)
|
||||
suite.Require().Equal(appchainMgr.AppchainAvailable, chain.Status)
|
||||
}
|
|
@ -33,9 +33,20 @@ solo = false
|
|||
plugin = "plugins/raft.so"
|
||||
|
||||
[genesis]
|
||||
addresses = [
|
||||
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
|
||||
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
]
|
||||
[[genesis.admins]]
|
||||
address = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
weight = 1
|
||||
[genesis.strategy]
|
||||
AppchainMgr = "SimpleMajority"
|
||||
RuleMgr = "SimpleMajority"
|
||||
NodeMgr = "SimpleMajority"
|
||||
ServiceMgr = "SimpleMajority"
|
|
@ -33,9 +33,20 @@ solo = false
|
|||
plugin = "plugins/raft.so"
|
||||
|
||||
[genesis]
|
||||
addresses = [
|
||||
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
|
||||
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
]
|
||||
[[genesis.admins]]
|
||||
address = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
weight = 1
|
||||
[genesis.strategy]
|
||||
AppchainMgr = "SimpleMajority"
|
||||
RuleMgr = "SimpleMajority"
|
||||
NodeMgr = "SimpleMajority"
|
||||
ServiceMgr = "SimpleMajority"
|
|
@ -33,9 +33,20 @@ solo = false
|
|||
plugin = "plugins/raft3.so"
|
||||
|
||||
[genesis]
|
||||
addresses = [
|
||||
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
|
||||
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
]
|
||||
[[genesis.admins]]
|
||||
address = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
weight = 1
|
||||
[genesis.strategy]
|
||||
AppchainMgr = "SimpleMajority"
|
||||
RuleMgr = "SimpleMajority"
|
||||
NodeMgr = "SimpleMajority"
|
||||
ServiceMgr = "SimpleMajority"
|
|
@ -33,9 +33,20 @@ solo = false
|
|||
plugin = "plugins/raft4.so"
|
||||
|
||||
[genesis]
|
||||
addresses = [
|
||||
"0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013",
|
||||
"0x79a1215469FaB6f9c63c1816b45183AD3624bE34",
|
||||
"0x97c8B516D19edBf575D72a172Af7F418BE498C37",
|
||||
"0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
]
|
||||
[[genesis.admins]]
|
||||
address = "0xc7F999b83Af6DF9e67d0a37Ee7e900bF38b3D013"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x79a1215469FaB6f9c63c1816b45183AD3624bE34"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0x97c8B516D19edBf575D72a172Af7F418BE498C37"
|
||||
weight = 1
|
||||
[[genesis.admins]]
|
||||
address = "0xc0Ff2e0b3189132D815b8eb325bE17285AC898f8"
|
||||
weight = 1
|
||||
[genesis.strategy]
|
||||
AppchainMgr = "SimpleMajority"
|
||||
RuleMgr = "SimpleMajority"
|
||||
NodeMgr = "SimpleMajority"
|
||||
ServiceMgr = "SimpleMajority"
|
|
@ -43,6 +43,7 @@ func TestTester(t *testing.T) {
|
|||
suite.Run(t, &Interchain{api: node3})
|
||||
suite.Run(t, &Role{api: node4})
|
||||
suite.Run(t, &Store{api: node1})
|
||||
suite.Run(t, &Governance{api: node2})
|
||||
}
|
||||
|
||||
func setupNode(t *testing.T, path string) api.CoreAPI {
|
||||
|
@ -115,7 +116,7 @@ func newTesterBitXHub(rep *repo.Repo) (*app.BitXHub, error) {
|
|||
}
|
||||
|
||||
func cleanStorage(basePath string) {
|
||||
filePath := path.Join(basePath,"storage")
|
||||
filePath := path.Join(basePath, "storage")
|
||||
err := os.RemoveAll(filePath)
|
||||
if err != nil {
|
||||
fmt.Printf("Clean storage failed, error: %s", err.Error())
|
||||
|
|
Loading…
Reference in New Issue