feat(*): add governance module

1.Add governance built-in contract;
2.Add governance related tests.
This commit is contained in:
dawn-to-dusk 2021-03-19 09:41:19 +08:00
parent 917186f216
commit 2902f16647
25 changed files with 1990 additions and 265 deletions

View File

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

View File

@ -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
View File

@ -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
View File

@ -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=

View File

@ -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 {

View File

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

View File

@ -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
}

View File

@ -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 {

View File

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

View File

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

View File

@ -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{

View File

@ -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 {

View File

@ -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
}

View File

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

View File

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

View File

@ -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():

View File

@ -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{})
//}

View File

@ -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{})
//}

View File

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

210
tester/case006_vote_test.go Normal file
View File

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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

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