diff --git a/Makefile b/Makefile index 7fe2c69..bb17f94 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,6 @@ packages = ./model/... ./core/... ./contract/... ./contentadrstorage/... +.PHONY: test test: go test ${packages} diff --git a/contract/go.mod b/contract/go.mod index 4be2a4b..31e5141 100644 --- a/contract/go.mod +++ b/contract/go.mod @@ -3,6 +3,7 @@ module github.com/cerebellum-network/cere-ddc-sdk-go/contract require ( github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.8 github.com/decred/base58 v1.0.3 + github.com/ethereum/go-ethereum v1.10.17 github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pkg/errors v0.9.1 @@ -17,7 +18,6 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect - github.com/ethereum/go-ethereum v1.10.17 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gtank/merlin v0.1.1 // indirect diff --git a/contract/pkg/actcapture/activity_capture_contract.go b/contract/pkg/actcapture/activity_capture_contract.go index b42f816..6b32e4b 100644 --- a/contract/pkg/actcapture/activity_capture_contract.go +++ b/contract/pkg/actcapture/activity_capture_contract.go @@ -3,12 +3,13 @@ package actcapture import ( "context" "encoding/hex" + "math/big" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" log "github.com/sirupsen/logrus" - "math/big" ) const ( @@ -106,7 +107,7 @@ func (a *activityCaptureContract) SetCommit(ctx context.Context, hash []byte, ga ContractAddressSS58: a.contractAddressSS58, From: a.keyringPair, Value: 0, - GasLimit: -1, + GasLimit: 0, Method: a.setCommitMethodId, Args: []interface{}{a.account, types.NewHash(hash), Gas, From, To}, } diff --git a/contract/pkg/bucket/cdn_node_param.go b/contract/pkg/bucket/cdn_node_param.go index 40f735b..d53a06f 100644 --- a/contract/pkg/bucket/cdn_node_param.go +++ b/contract/pkg/bucket/cdn_node_param.go @@ -6,10 +6,9 @@ import ( // Structure-helper for json on the CDN Node Params string type CDNNodeParams struct { - Url string `json:"url"` - Size FlexInt `json:"size"` - Location string `json:"location"` - PublicKey string `json:"publicKey"` + Url string `json:"url"` + Size FlexInt `json:"size"` + Location string `json:"location"` } func ReadCDNNodeParams(s string) (p CDNNodeParams, err error) { diff --git a/contract/pkg/bucket/cdn_node_param_test.go b/contract/pkg/bucket/cdn_node_param_test.go index e4b015a..03a9b6b 100644 --- a/contract/pkg/bucket/cdn_node_param_test.go +++ b/contract/pkg/bucket/cdn_node_param_test.go @@ -17,23 +17,21 @@ func TestReadCDNNodeParams(t *testing.T) { }{ { name: "Positive test", - args: args{s: `{"url":"http://localhost:8080", "publicKey": "NodePublicKey", "size":1, "location":"US"}`}, + args: args{s: `{"url":"http://localhost:8080", "size":1, "location":"US"}`}, wantP: CDNNodeParams{ - Url: "http://localhost:8080", - Size: 1, - Location: "US", - PublicKey: "NodePublicKey", + Url: "http://localhost:8080", + Size: 1, + Location: "US", }, wantErr: false, }, { name: "Positive test with size as string", - args: args{s: `{"url":"http://localhost:8080", "publicKey": "NodePublicKey", "size":"1", "location":"US"}`}, + args: args{s: `{"url":"http://localhost:8080", "size":"1", "location":"US"}`}, wantP: CDNNodeParams{ - Url: "http://localhost:8080", - Size: 1, - Location: "US", - PublicKey: "NodePublicKey", + Url: "http://localhost:8080", + Size: 1, + Location: "US", }, wantErr: false, }, diff --git a/contract/pkg/bucket/ddc_bucket_contract.go b/contract/pkg/bucket/ddc_bucket_contract.go index eaf8ab8..b9bbf2d 100644 --- a/contract/pkg/bucket/ddc_bucket_contract.go +++ b/contract/pkg/bucket/ddc_bucket_contract.go @@ -1,6 +1,7 @@ package bucket import ( + "context" _ "embed" "encoding/hex" "errors" @@ -9,33 +10,97 @@ import ( "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" + "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" log "github.com/sirupsen/logrus" ) const ( - bucketGetMethod = "3802cb77" - clusterGetMethod = "e75411f5" - nodeGetMethod = "847f3997" - accountGetMethod = "1d4220fa" - cdnClusterGetMethod = "4b22fbf1" - cdnNodeGetMethod = "f9a5a813" + nodeCreateMethod = "e8aa4ade" + nodeRemoveMethod = "e068fb34" + nodeSetParamsMethod = "df8b696e" + nodeGetMethod = "847f3997" + nodeListMethod = "423286d6" + cdnNodeCreateMethod = "e8aa4ade" + cdnNodeRemoveMethod = "e068fb34" + cdnNodeSetParamsMethod = "df8b696e" + cdnNodeGetMethod = "f9a5a813" + cdnNodeListMethod = "f8589aae" + clusterCreateMethod = "4c0f21f6" + clusterAddNodeMethod = "f7496bdc" + clusterRemoveNodeMethod = "793e0778" + clusterResetNodeMethod = "a78b2e19" + clusterReplaceNodeMethod = "48194ab1" + clusterAddCdnNodeMethod = "0b4199f3" + clusterRemoveCdnNodeMethod = "ff8531d8" + clusterSetParamsMethod = "7dac5f9a" + clusterRemoveMethod = "2248742a" + clusterSetNodeStatusMethod = "8078df7f" + clusterSetCdnNodeStatusMethod = "577027ba" + clusterGetMethod = "e75411f5" + clusterListMethod = "d9db9d44" + hasPermissionMethod = "e0942492" + grantTrustedManagerPermissionMethod = "ea0cbdcd" + revokeTrustedManagerPermissionMethod = "83532355" + adminGrantPermissionMethod = "be41ea55" + adminRevokePermissionMethod = "6b150666" + adminTransferNodeOwnershipMethod = "783b382d" + adminTransferCdnNodeOwnershipMethod = "cd9821be" + bucketGetMethod = "3802cb77" + accountGetMethod = "1d4220fa" + accountDepositMethod = "c311af62" + accountBondMethod = "e9fad0bf" + accountUnbondMethod = "f7ea2c67" + accountGetUsdPerCereMethod = "e4a4652a" + accountSetUsdPerCereMethod = "48d45ee8" + accountWithdrawUnbondedMethod = "98173716" + getAccountsMethod = "ef03ead7" + bucketCreateMethod = "0aeb2379" + bucketChangeOwnerMethod = "c7d0c2cd" + bucketAllocIntoClusterMethod = "4c482d19" + bucketSettlePaymentMethod = "15974555" + bucketChangeParamsMethod = "9f2d075b" + bucketListMethod = "417ab584" + bucketListForAccountMethod = "c434cf57" + bucketSetAvailabilityMethod = "053eb3ce" + bucketSetResourceCapMethod = "85010c6d" + getBucketWritersMethod = "499cd4b7" + getBucketReadersMethod = "b9a7cc1c" + bucketSetWriterPermMethod = "ea2e477a" + bucketRevokeWriterPermMethod = "2b3d8dd1" + bucketSetReaderPermMethod = "fc0e94ea" + bucketRevokeReaderPermMethod = "e9bfed5a" BucketCreatedEventId = "004464634275636b65743a3a4275636b65744372656174656400000000000000" BucketAllocatedEventId = "004464634275636b65743a3a4275636b6574416c6c6f63617465640000000000" BucketSettlePaymentEventId = "004464634275636b65743a3a4275636b6574536574746c655061796d656e7400" BucketAvailabilityUpdatedId = "8d8714b3df602b0ce92b8a3de12daedf222ff9198078f834d57176ca2a06359c" + BucketParamsSetEventId = "004464634275636b65743a3a4275636b6574506172616d735365740000000000" ClusterCreatedEventId = "004464634275636b65743a3a436c757374657243726561746564000000000000" + ClusterNodeAddedEventId = "004464634275636b65743a3a436c75737465724e6f6465416464656400000000" + ClusterNodeRemovedEventId = "004464634275636b65743a3a436c75737465724e6f646552656d6f7665640000" + ClusterCdnNodeAddedEventId = "004464634275636b65743a3a436c757374657243646e4e6f6465416464656400" + ClusterCdnNodeRemovedEventId = "e8920de02c833de0d4c7a1cc213877437ddcc0e1f03f65dd88c7a79c91cde9d9" + ClusterParamsSetEventId = "004464634275636b65743a3a436c7573746572506172616d7353657400000000" + ClusterRemovedEventId = "004464634275636b65743a3a436c757374657252656d6f766564000000000000" + ClusterNodeStatusSetEventId = "004464634275636b65743a3a436c75737465724e6f6465537461747573536574" + ClusterCdnNodeStatusSetEventId = "b3c6265529c37cd82b1e4875fa439024770d825e335f643195801131645f3d26" ClusterNodeReplacedEventId = "004464634275636b65743a3a436c75737465724e6f64655265706c6163656400" + ClusterNodeResetEventId = "004464634275636b65743a3a436c75737465724e6f6465526573657400000000" ClusterReserveResourceEventId = "84d6d26a3275dced8e359779bf21488762a1d88029f52522d8fc27607759399e" ClusterDistributeRevenuesEventId = "65441936759a16fb28d0e059b878f2e48283ca2eac57c396a8035cce9e2acdd3" - CdnClusterCreatedEventId = "004464634275636b65743a3a43646e436c757374657243726561746564000000" - CdnClusterDistributeRevenuesEventId = "4e19fc4683a9a741a09d89a1d62b22d592a8bf10e2b8b6eff7c6742a0ed88bb4" + ClusterDistributeCdnRevenuesEventId = "ec0e9cad0816c5f7e9c252a83e85ca177e162dcb4a284bf80b342942f3e9faa5" CdnNodeCreatedEventId = "004464634275636b65743a3a43646e4e6f646543726561746564000000000000" - NodeCreatedEventId = "004464634275636b65743a3a4e6f646543726561746564000000000000000000" + CdnNodeRemovedEventId = "004464634275636b65743a3a43646e4e6f646552656d6f766564000000000000" + CdnNodeParamsSetEventId = "004464634275636b65743a3a43646e4e6f6465506172616d7353657400000000" DepositEventId = "004464634275636b65743a3a4465706f73697400000000000000000000000000" - GrantPermissionEventId = "004464634275636b65743a3a4772616e745065726d697373696f6e0000000000" - RevokePermissionEventId = "004464634275636b65743a3a5265766f6b655065726d697373696f6e00000000" + NodeRemovedEventId = "004464634275636b65743a3a4e6f646552656d6f766564000000000000000000" + NodeParamsSetEventId = "004464634275636b65743a3a4e6f6465506172616d7353657400000000000000" + NodeCreatedEventId = "004464634275636b65743a3a4e6f646543726561746564000000000000000000" + GrantPermissionEventId = "004464634275636b65743a3a5065726d697373696f6e4772616e746564000000" + RevokePermissionEventId = "004464634275636b65743a3a5065726d697373696f6e5265766f6b6564000000" + NodeOwnershipTransferredEventId = "f8da30f579016091acfaa384eee0ddbfcb94d408abc09fde35338ea47c83a0a2" + CdnNodeOwnershipTransferredEventId = "ad2b04ceaba2414e23695e96e4bd645d7616ba94cc155679497ef730c086b224" ) type ( @@ -43,28 +108,129 @@ type ( GetContractAddress() string GetLastAccessTime() time.Time - BucketGet(bucketId uint32) (*BucketStatus, error) - ClusterGet(clusterId uint32) (*ClusterStatus, error) - NodeGet(nodeId uint32) (*NodeStatus, error) - CDNClusterGet(clusterId uint32) (*CDNClusterStatus, error) - CDNNodeGet(nodeId uint32) (*CDNNodeStatus, error) - AccountGet(account types.AccountID) (*Account, error) + AccountDeposit(ctx context.Context, keyPair signature.KeyringPair) error + AccountBond(ctx context.Context, keyPair signature.KeyringPair, bondAmount Balance) error + AccountUnbond(ctx context.Context, keyPair signature.KeyringPair, bondAmount Cash) error + AccountGetUsdPerCere() (Balance, error) + AccountSetUsdPerCere(ctx context.Context, keyPair signature.KeyringPair, usdPerCere Balance) error + AccountWithdrawUnbonded(ctx context.Context, keyPair signature.KeyringPair) error + GetAccounts() ([]AccountId, error) + + BucketGet(bucketId BucketId) (*BucketInfo, error) + BucketCreate(ctx context.Context, keyPair signature.KeyringPair, bucketParams BucketParams, clusterId ClusterId, ownerId types.OptionAccountID) (blockHash types.Hash, err error) + BucketChangeOwner(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, ownerId AccountId) error + BucketAllocIntoCluster(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, resource Resource) error + BucketSettlePayment(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId) error + BucketChangeParams(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, bucketParams BucketParams) error + BucketList(offset types.U32, limit types.U32, ownerId types.OptionAccountID) (*BucketListInfo, error) + BucketListForAccount(ownerId AccountId) ([]Bucket, error) + BucketSetAvailability(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, publicAvailability bool) error + BucketSetResourceCap(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, newResourceCap Resource) error + GetBucketWriters(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId) ([]AccountId, error) + GetBucketReaders(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId) ([]AccountId, error) + BucketSetWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, writer AccountId) error + BucketRevokeWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, writer AccountId) error + BucketSetReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, reader AccountId) error + BucketRevokeReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, reader AccountId) error + + ClusterGet(clusterId ClusterId) (*ClusterInfo, error) + ClusterCreate(ctx context.Context, keyPair signature.KeyringPair, params Params, resourcePerVNode Resource) (blockHash types.Hash, err error) + ClusterAddNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey, vNodes [][]Token) error + ClusterRemoveNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey) error + ClusterResetNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey, vNodes [][]Token) error + ClusterReplaceNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, vNodes [][]Token, newNodeKey NodeKey) error + ClusterAddCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey CdnNodeKey) error + ClusterRemoveCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey CdnNodeKey) error + ClusterSetParams(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, params Params) error + ClusterRemove(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId) error + ClusterSetNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey, statusInCluster string) error + ClusterSetCdnNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey CdnNodeKey, statusInCluster string) error + ClusterList(offset types.U32, limit types.U32, filterManagerId types.OptionAccountID) (*ClusterListInfo, error) + + NodeGet(nodeKey NodeKey) (*NodeInfo, error) + NodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey, params Params, capacity Resource, rent Rent) (blockHash types.Hash, err error) + NodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey) error + NodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey, params Params) error + NodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*NodeListInfo, error) + CdnNodeGet(nodeKey CdnNodeKey) (*CdnNodeInfo, error) + CdnNodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey, params CDNNodeParams) error + CdnNodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey) error + CdnNodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey, params CDNNodeParams) error + CdnNodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*CdnNodeListInfo, error) + + AccountGet(account AccountId) (*Account, error) + HasPermission(account AccountId, permission string) (bool, error) + GrantTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId AccountId) error + RevokeTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId AccountId) error + AdminGrantPermission(ctx context.Context, keyPair signature.KeyringPair, grantee AccountId, permission string) error + AdminRevokePermission(ctx context.Context, keyPair signature.KeyringPair, grantee AccountId, permission string) error + AdminTransferNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey, newOwner AccountId) error + AdminTransferCdnNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey, newOwner AccountId) error AddContractEventHandler(event string, handler func(interface{})) error GetEventDispatcher() map[types.Hash]pkg.ContractEventDispatchEntry } ddcBucketContract struct { - contract pkg.BlockchainClient - lastAccessTime time.Time - contractAddressSS58 string - keyringPair signature.KeyringPair - bucketGetMethodId []byte - clusterGetMethodId []byte - nodeGetMethodId []byte - cdnClusterGetMethodId []byte - cdnNodeGetMethodId []byte - accountGetMethodId []byte - eventDispatcher map[types.Hash]pkg.ContractEventDispatchEntry + chainClient pkg.BlockchainClient + lastAccessTime time.Time + contractAddressSS58 string + keyringPair signature.KeyringPair + nodeCreateMethodId []byte + nodeRemoveMethodId []byte + nodeSetParamsMethodId []byte + nodeGetMethodId []byte + nodeListMethodId []byte + cdnNodeCreateMethodId []byte + cdnNodeRemoveMethodId []byte + cdnNodeSetParamsMethodId []byte + cdnNodeGetMethodId []byte + cdnNodeListMethodId []byte + clusterCreateMethodId []byte + clusterAddNodeMethodId []byte + clusterRemoveNodeMethodId []byte + clusterResetNodeMethodId []byte + clusterReplaceNodeMethodId []byte + clusterAddCdnNodeMethodId []byte + clusterRemoveCdnNodeMethodId []byte + clusterSetParamsMethodId []byte + clusterRemoveMethodId []byte + clusterSetNodeStatusMethodId []byte + clusterSetCdnNodeStatusMethodId []byte + clusterGetMethodId []byte + clusterListMethodId []byte + hasPermissionMethodId []byte + grantTrustedManagerPermissionMethodId []byte + revokeTrustedManagerPermissionMethodId []byte + adminGrantPermissionMethodId []byte + adminRevokePermissionMethodId []byte + adminTransferNodeOwnershipMethodId []byte + adminTransferCdnNodeOwnershipMethodId []byte + accountGetMethodId []byte + accountDepositMethodId []byte + accountBondMethodId []byte + accountUnbondMethodId []byte + accountGetUsdPerCereMethodId []byte + accountSetUsdPerCereMethodId []byte + accountWithdrawUnbondedMethodId []byte + getAccountsMethodId []byte + bucketGetMethodId []byte + bucketCreateMethodId []byte + bucketChangeOwnerMethodId []byte + bucketAllocIntoClusterMethodId []byte + bucketSettlePaymentMethodId []byte + bucketChangeParamsMethodId []byte + bucketListMethodId []byte + bucketListForAccountMethodId []byte + bucketSetAvailabilityMethodId []byte + bucketSetResourceCapMethodId []byte + getBucketWritersMethodId []byte + getBucketReadersMethodId []byte + bucketSetWriterPermMethodId []byte + bucketRevokeWriterPermMethodId []byte + bucketSetReaderPermMethodId []byte + bucketRevokeReaderPermMethodId []byte + + eventDispatcher map[types.Hash]pkg.ContractEventDispatchEntry } ) @@ -77,13 +243,33 @@ var eventDispatchTable = map[string]reflect.Type{ ClusterNodeReplacedEventId: reflect.TypeOf(ClusterNodeReplacedEvent{}), ClusterReserveResourceEventId: reflect.TypeOf(ClusterReserveResourceEvent{}), ClusterDistributeRevenuesEventId: reflect.TypeOf(ClusterDistributeRevenuesEvent{}), - CdnClusterCreatedEventId: reflect.TypeOf(CdnClusterCreatedEvent{}), - CdnClusterDistributeRevenuesEventId: reflect.TypeOf(CdnClusterDistributeRevenuesEvent{}), CdnNodeCreatedEventId: reflect.TypeOf(CdnNodeCreatedEvent{}), NodeCreatedEventId: reflect.TypeOf(NodeCreatedEvent{}), DepositEventId: reflect.TypeOf(DepositEvent{}), GrantPermissionEventId: reflect.TypeOf(GrantPermissionEvent{}), - RevokePermissionEventId: reflect.TypeOf(RevokePermissionEvent{})} + RevokePermissionEventId: reflect.TypeOf(RevokePermissionEvent{}), + BucketParamsSetEventId: reflect.TypeOf(BucketParamsSetEvent{}), + ClusterNodeAddedEventId: reflect.TypeOf(ClusterNodeAddedEvent{}), + ClusterNodeRemovedEventId: reflect.TypeOf(ClusterNodeRemovedEvent{}), + ClusterCdnNodeAddedEventId: reflect.TypeOf(ClusterCdnNodeAddedEvent{}), + ClusterCdnNodeRemovedEventId: reflect.TypeOf(ClusterCdnNodeRemovedEvent{}), + ClusterParamsSetEventId: reflect.TypeOf(ClusterParamsSetEvent{}), + ClusterRemovedEventId: reflect.TypeOf(ClusterRemovedEvent{}), + ClusterNodeStatusSetEventId: reflect.TypeOf(ClusterNodeStatusSetEvent{}), + ClusterCdnNodeStatusSetEventId: reflect.TypeOf(ClusterCdnNodeStatusSetEvent{}), + ClusterNodeResetEventId: reflect.TypeOf(ClusterNodeResetEvent{}), + ClusterDistributeCdnRevenuesEventId: reflect.TypeOf(ClusterDistributeCdnRevenuesEvent{}), + CdnNodeRemovedEventId: reflect.TypeOf(CdnNodeRemovedEvent{}), + CdnNodeParamsSetEventId: reflect.TypeOf(CdnNodeParamsSetEvent{}), + NodeRemovedEventId: reflect.TypeOf(NodeRemovedEvent{}), + NodeParamsSetEventId: reflect.TypeOf(NodeParamsSetEvent{}), + NodeOwnershipTransferredEventId: reflect.TypeOf(NodeOwnershipTransferredEvent{}), + CdnNodeOwnershipTransferredEventId: reflect.TypeOf(CdnNodeOwnershipTransferredEvent{}), +} + +const ( + DEFAULT_GAS_LIMIT uint64 = 500_000 * pkg.MGAS +) func CreateDdcBucketContract(client pkg.BlockchainClient, contractAddressSS58 string) DdcBucketContract { bucketGetMethodId, err := hex.DecodeString(bucketGetMethod) @@ -101,11 +287,6 @@ func CreateDdcBucketContract(client pkg.BlockchainClient, contractAddressSS58 st log.WithError(err).WithField("method", nodeGetMethod).Fatal("Can't decode method nodeGetMethod") } - cdnClusterGetMethodId, err := hex.DecodeString(cdnClusterGetMethod) - if err != nil { - log.WithError(err).WithField("method", cdnClusterGetMethod).Fatal("Can't decode method cdnClusterGetMethod") - } - cdnNodeGetMethodId, err := hex.DecodeString(cdnNodeGetMethod) if err != nil { log.WithError(err).WithField("method", cdnNodeGetMethod).Fatal("Can't decode method cdnNodeGetMethod") @@ -116,65 +297,351 @@ func CreateDdcBucketContract(client pkg.BlockchainClient, contractAddressSS58 st log.WithError(err).WithField("method", accountGetMethod).Fatal("Can't decode method accountGetMethod") } + nodeCreateMethodId, err := hex.DecodeString(nodeCreateMethod) + if err != nil { + log.WithError(err).WithField("method", nodeCreateMethod).Fatal("Can't decode method nodeCreateMethod") + } + + nodeRemoveMethodId, err := hex.DecodeString(nodeRemoveMethod) + if err != nil { + log.WithError(err).WithField("method", nodeRemoveMethod).Fatal("Can't decode method nodeRemoveMethod") + } + + nodeSetParamsMethodId, err := hex.DecodeString(nodeSetParamsMethod) + if err != nil { + log.WithError(err).WithField("method", nodeSetParamsMethod).Fatal("Can't decode method nodeSetParamsMethod") + } + + nodeListMethodId, err := hex.DecodeString(nodeListMethod) + if err != nil { + log.WithError(err).WithField("method", nodeListMethod).Fatal("Can't decode method nodeListMethod") + } + + cdnNodeCreateMethodId, err := hex.DecodeString(cdnNodeCreateMethod) + if err != nil { + log.WithError(err).WithField("method", cdnNodeCreateMethod).Fatal("Can't decode method cdnNodeCreateMethod") + } + + cdnNodeRemoveMethodId, err := hex.DecodeString(cdnNodeRemoveMethod) + if err != nil { + log.WithError(err).WithField("method", cdnNodeRemoveMethod).Fatal("Can't decode method cdnNodeRemoveMethod") + } + + cdnNodeSetParamsMethodId, err := hex.DecodeString(cdnNodeSetParamsMethod) + if err != nil { + log.WithError(err).WithField("method", cdnNodeSetParamsMethod).Fatal("Can't decode method cdnNodeSetParamsMethod") + } + + cdnNodeListMethodId, err := hex.DecodeString(cdnNodeListMethod) + if err != nil { + log.WithError(err).WithField("method", cdnNodeListMethod).Fatal("Can't decode method cdnNodeListMethod") + } + + clusterCreateMethodId, err := hex.DecodeString(clusterCreateMethod) + if err != nil { + log.WithError(err).WithField("method", clusterCreateMethod).Fatal("Can't decode method clusterCreateMethod") + } + + clusterAddNodeMethodId, err := hex.DecodeString(clusterAddNodeMethod) + if err != nil { + log.WithError(err).WithField("method", clusterAddNodeMethod).Fatal("Can't decode method clusterAddNodeMethod") + } + + clusterRemoveNodeMethodId, err := hex.DecodeString(clusterRemoveNodeMethod) + if err != nil { + log.WithError(err).WithField("method", clusterRemoveNodeMethod).Fatal("Can't decode method clusterRemoveNodeMethod") + } + + clusterResetNodeMethodId, err := hex.DecodeString(clusterResetNodeMethod) + if err != nil { + log.WithError(err).WithField("method", clusterResetNodeMethod).Fatal("Can't decode method clusterResetNodeMethod") + } + + clusterReplaceNodeMethodId, err := hex.DecodeString(clusterReplaceNodeMethod) + if err != nil { + log.WithError(err).WithField("method", clusterReplaceNodeMethod).Fatal("Can't decode method clusterReplaceNodeMethod") + } + + clusterAddCdnNodeMethodId, err := hex.DecodeString(clusterAddCdnNodeMethod) + if err != nil { + log.WithError(err).WithField("method", clusterAddCdnNodeMethod).Fatal("Can't decode method clusterAddCdnNodeMethod") + } + + clusterRemoveCdnNodeMethodId, err := hex.DecodeString(clusterRemoveCdnNodeMethod) + if err != nil { + log.WithError(err).WithField("method", clusterRemoveCdnNodeMethod).Fatal("Can't decode method clusterRemoveCdnNodeMethod") + } + + clusterSetParamsMethodId, err := hex.DecodeString(clusterSetParamsMethod) + if err != nil { + log.WithError(err).WithField("method", clusterSetParamsMethod).Fatal("Can't decode method clusterSetParamsMethod") + } + + clusterRemoveMethodId, err := hex.DecodeString(clusterRemoveMethod) + if err != nil { + log.WithError(err).WithField("method", clusterRemoveMethod).Fatal("Can't decode method clusterRemoveMethod") + } + + clusterSetNodeStatusMethodId, err := hex.DecodeString(clusterSetNodeStatusMethod) + if err != nil { + log.WithError(err).WithField("method", clusterSetNodeStatusMethod).Fatal("Can't decode method clusterSetNodeStatusMethod") + } + + clusterSetCdnNodeStatusMethodId, err := hex.DecodeString(clusterSetCdnNodeStatusMethod) + if err != nil { + log.WithError(err).WithField("method", clusterSetCdnNodeStatusMethod).Fatal("Can't decode method clusterSetCdnNodeStatusMethod") + } + + clusterListMethodId, err := hex.DecodeString(clusterListMethod) + if err != nil { + log.WithError(err).WithField("method", clusterListMethod).Fatal("Can't decode method clusterListMethod") + } + + hasPermissionMethodId, err := hex.DecodeString(hasPermissionMethod) + if err != nil { + log.WithError(err).WithField("method", hasPermissionMethod).Fatal("Can't decode method hasPermissionMethod") + } + + grantTrustedManagerPermissionMethodId, err := hex.DecodeString(grantTrustedManagerPermissionMethod) + if err != nil { + log.WithError(err).WithField("method", grantTrustedManagerPermissionMethod).Fatal("Can't decode method grantTrustedManagerPermissionMethod") + } + + revokeTrustedManagerPermissionMethodId, err := hex.DecodeString(revokeTrustedManagerPermissionMethod) + if err != nil { + log.WithError(err).WithField("method", revokeTrustedManagerPermissionMethod).Fatal("Can't decode method revokeTrustedManagerPermissionMethod") + } + + adminGrantPermissionMethodId, err := hex.DecodeString(adminGrantPermissionMethod) + if err != nil { + log.WithError(err).WithField("method", adminGrantPermissionMethod).Fatal("Can't decode method adminGrantPermissionMethod") + } + + adminRevokePermissionMethodId, err := hex.DecodeString(adminRevokePermissionMethod) + if err != nil { + log.WithError(err).WithField("method", adminRevokePermissionMethod).Fatal("Can't decode method adminRevokePermissionMethod") + } + + adminTransferNodeOwnershipMethodId, err := hex.DecodeString(adminTransferNodeOwnershipMethod) + if err != nil { + log.WithError(err).WithField("method", adminTransferNodeOwnershipMethod).Fatal("Can't decode method adminTransferNodeOwnershipMethod") + } + + adminTransferCdnNodeOwnershipMethodId, err := hex.DecodeString(adminTransferCdnNodeOwnershipMethod) + if err != nil { + log.WithError(err).WithField("method", adminTransferCdnNodeOwnershipMethod).Fatal("Can't decode method adminTransferCdnNodeOwnershipMethodId") + } + + accountDepositMethodId, err := hex.DecodeString(accountDepositMethod) + if err != nil { + log.WithError(err).WithField("method", accountDepositMethod).Fatal("Can't decode method accountDepositMethodId") + } + + accountBondMethodId, err := hex.DecodeString(accountBondMethod) + if err != nil { + log.WithError(err).WithField("method", accountBondMethod).Fatal("Can't decode method accountBondMethodId") + } + + accountUnbondMethodId, err := hex.DecodeString(accountUnbondMethod) + if err != nil { + log.WithError(err).WithField("method", accountUnbondMethod).Fatal("Can't decode method accountUnbondMethodId") + } + + accountGetUsdPerCereMethodId, err := hex.DecodeString(accountGetUsdPerCereMethod) + if err != nil { + log.WithError(err).WithField("method", accountGetUsdPerCereMethod).Fatal("Can't decode method accountGetUsdPerCereMethodId") + } + + accountSetUsdPerCereMethodId, err := hex.DecodeString(accountSetUsdPerCereMethod) + if err != nil { + log.WithError(err).WithField("method", accountSetUsdPerCereMethod).Fatal("Can't decode method accountSetUsdPerCereMethodId") + } + + accountWithdrawUnbondedMethodId, err := hex.DecodeString(accountWithdrawUnbondedMethod) + if err != nil { + log.WithError(err).WithField("method", accountWithdrawUnbondedMethod).Fatal("Can't decode method accountWithdrawUnbondedMethodId") + } + + getAccountsMethodId, err := hex.DecodeString(getAccountsMethod) + if err != nil { + log.WithError(err).WithField("method", getAccountsMethod).Fatal("Can't decode method getAccountsMethodId") + } + + bucketCreateMethodId, err := hex.DecodeString(bucketCreateMethod) + if err != nil { + log.WithError(err).WithField("method", bucketCreateMethod).Fatal("Can't decode method bucketCreateMethodId") + } + + bucketChangeOwnerMethodId, err := hex.DecodeString(bucketChangeOwnerMethod) + if err != nil { + log.WithError(err).WithField("method", bucketChangeOwnerMethod).Fatal("Can't decode method bucketChangeOwnerMethodId") + } + + bucketAllocIntoClusterMethodId, err := hex.DecodeString(bucketAllocIntoClusterMethod) + if err != nil { + log.WithError(err).WithField("method", bucketAllocIntoClusterMethod).Fatal("Can't decode method bucketAllocIntoClusterMethodId") + } + + bucketSettlePaymentMethodId, err := hex.DecodeString(bucketSettlePaymentMethod) + if err != nil { + log.WithError(err).WithField("method", bucketSettlePaymentMethod).Fatal("Can't decode method bucketSettlePaymentMethodId") + } + + bucketChangeParamsMethodId, err := hex.DecodeString(bucketChangeParamsMethod) + if err != nil { + log.WithError(err).WithField("method", bucketChangeParamsMethod).Fatal("Can't decode method bucketChangeParamsMethodId") + } + + bucketListMethodId, err := hex.DecodeString(bucketListMethod) + if err != nil { + log.WithError(err).WithField("method", bucketListMethod).Fatal("Can't decode method bucketListMethodId") + } + + bucketListForAccountMethodId, err := hex.DecodeString(bucketListForAccountMethod) + if err != nil { + log.WithError(err).WithField("method", bucketListForAccountMethod).Fatal("Can't decode method bucketListForAccountMethodId") + } + + bucketSetAvailabilityMethodId, err := hex.DecodeString(bucketSetAvailabilityMethod) + if err != nil { + log.WithError(err).WithField("method", bucketSetAvailabilityMethod).Fatal("Can't decode method bucketSetAvailabilityMethodId") + } + + bucketSetResourceCapMethodId, err := hex.DecodeString(bucketSetResourceCapMethod) + if err != nil { + log.WithError(err).WithField("method", bucketSetResourceCapMethod).Fatal("Can't decode method bucketSetResourceCapMethodId") + } + + getBucketWritersMethodId, err := hex.DecodeString(bucketSetResourceCapMethod) + if err != nil { + log.WithError(err).WithField("method", getBucketWritersMethodId).Fatal("Can't decode method getBucketWritersMethodId") + } + + getBucketReadersMethodId, err := hex.DecodeString(getBucketReadersMethod) + if err != nil { + log.WithError(err).WithField("method", getBucketReadersMethod).Fatal("Can't decode method getBucketReadersMethodId") + } + + bucketSetWriterPermMethodId, err := hex.DecodeString(bucketSetWriterPermMethod) + if err != nil { + log.WithError(err).WithField("method", bucketSetWriterPermMethod).Fatal("Can't decode method bucketSetWriterPermMethod") + } + + bucketRevokeWriterPermMethodId, err := hex.DecodeString(bucketRevokeWriterPermMethod) + if err != nil { + log.WithError(err).WithField("method", bucketRevokeWriterPermMethod).Fatal("Can't decode method bucketRevokeWriterPermMethodId") + } + + bucketSetReaderPermMethodId, err := hex.DecodeString(bucketSetReaderPermMethod) + if err != nil { + log.WithError(err).WithField("method", bucketSetReaderPermMethod).Fatal("Can't decode method bucketSetReaderPermMethodId") + } + + bucketRevokeReaderPermMethodId, err := hex.DecodeString(bucketRevokeReaderPermMethod) + if err != nil { + log.WithError(err).WithField("method", bucketRevokeReaderPermMethod).Fatal("Can't decode method bucketRevokeReaderPermMethodId") + } + eventDispatcher := make(map[types.Hash]pkg.ContractEventDispatchEntry) for k, v := range eventDispatchTable { - if key, err := types.NewHashFromHexString(k); err != nil { + if eventKey, err := types.NewHashFromHexString(k); err != nil { log.WithError(err).WithField("hash", k).Fatalf("Bad event hash for event %s", v.Name()) } else { - eventDispatcher[key] = pkg.ContractEventDispatchEntry{ArgumentType: v} + eventDispatcher[eventKey] = pkg.ContractEventDispatchEntry{ArgumentType: v} } } return &ddcBucketContract{ - contract: client, - contractAddressSS58: contractAddressSS58, - keyringPair: signature.KeyringPair{Address: contractAddressSS58}, - bucketGetMethodId: bucketGetMethodId, - clusterGetMethodId: clusterGetMethodId, - nodeGetMethodId: nodeGetMethodId, - cdnClusterGetMethodId: cdnClusterGetMethodId, - cdnNodeGetMethodId: cdnNodeGetMethodId, - accountGetMethodId: accountGetMethodId, - eventDispatcher: eventDispatcher, + chainClient: client, + contractAddressSS58: contractAddressSS58, + keyringPair: signature.KeyringPair{Address: contractAddressSS58}, + bucketGetMethodId: bucketGetMethodId, + clusterGetMethodId: clusterGetMethodId, + nodeGetMethodId: nodeGetMethodId, + cdnNodeGetMethodId: cdnNodeGetMethodId, + accountGetMethodId: accountGetMethodId, + nodeCreateMethodId: nodeCreateMethodId, + nodeRemoveMethodId: nodeRemoveMethodId, + nodeSetParamsMethodId: nodeSetParamsMethodId, + nodeListMethodId: nodeListMethodId, + cdnNodeCreateMethodId: cdnNodeCreateMethodId, + cdnNodeRemoveMethodId: cdnNodeRemoveMethodId, + cdnNodeSetParamsMethodId: cdnNodeSetParamsMethodId, + cdnNodeListMethodId: cdnNodeListMethodId, + clusterCreateMethodId: clusterCreateMethodId, + clusterAddNodeMethodId: clusterAddNodeMethodId, + clusterRemoveNodeMethodId: clusterRemoveNodeMethodId, + clusterResetNodeMethodId: clusterResetNodeMethodId, + clusterReplaceNodeMethodId: clusterReplaceNodeMethodId, + clusterAddCdnNodeMethodId: clusterAddCdnNodeMethodId, + clusterRemoveCdnNodeMethodId: clusterRemoveCdnNodeMethodId, + clusterSetParamsMethodId: clusterSetParamsMethodId, + clusterRemoveMethodId: clusterRemoveMethodId, + clusterSetNodeStatusMethodId: clusterSetNodeStatusMethodId, + clusterSetCdnNodeStatusMethodId: clusterSetCdnNodeStatusMethodId, + clusterListMethodId: clusterListMethodId, + hasPermissionMethodId: hasPermissionMethodId, + grantTrustedManagerPermissionMethodId: grantTrustedManagerPermissionMethodId, + revokeTrustedManagerPermissionMethodId: revokeTrustedManagerPermissionMethodId, + adminGrantPermissionMethodId: adminGrantPermissionMethodId, + adminRevokePermissionMethodId: adminRevokePermissionMethodId, + adminTransferNodeOwnershipMethodId: adminTransferNodeOwnershipMethodId, + adminTransferCdnNodeOwnershipMethodId: adminTransferCdnNodeOwnershipMethodId, + eventDispatcher: eventDispatcher, + accountDepositMethodId: accountDepositMethodId, + accountBondMethodId: accountBondMethodId, + accountUnbondMethodId: accountUnbondMethodId, + accountGetUsdPerCereMethodId: accountGetUsdPerCereMethodId, + accountSetUsdPerCereMethodId: accountSetUsdPerCereMethodId, + accountWithdrawUnbondedMethodId: accountWithdrawUnbondedMethodId, + getAccountsMethodId: getAccountsMethodId, + bucketCreateMethodId: bucketCreateMethodId, + bucketChangeOwnerMethodId: bucketChangeOwnerMethodId, + bucketAllocIntoClusterMethodId: bucketAllocIntoClusterMethodId, + bucketSettlePaymentMethodId: bucketSettlePaymentMethodId, + bucketChangeParamsMethodId: bucketChangeParamsMethodId, + bucketListMethodId: bucketListMethodId, + bucketListForAccountMethodId: bucketListForAccountMethodId, + bucketSetAvailabilityMethodId: bucketSetAvailabilityMethodId, + bucketSetResourceCapMethodId: bucketSetResourceCapMethodId, + getBucketWritersMethodId: getBucketWritersMethodId, + getBucketReadersMethodId: getBucketReadersMethodId, + bucketSetWriterPermMethodId: bucketSetWriterPermMethodId, + bucketRevokeWriterPermMethodId: bucketRevokeWriterPermMethodId, + bucketSetReaderPermMethodId: bucketSetReaderPermMethodId, + bucketRevokeReaderPermMethodId: bucketRevokeReaderPermMethodId, } } -func (d *ddcBucketContract) BucketGet(bucketId uint32) (*BucketStatus, error) { - res := &BucketStatus{} +func (d *ddcBucketContract) BucketGet(bucketId BucketId) (*BucketInfo, error) { + res := &BucketInfo{} err := d.callToRead(res, d.bucketGetMethodId, types.U32(bucketId)) return res, err } -func (d *ddcBucketContract) ClusterGet(clusterId uint32) (*ClusterStatus, error) { - res := &ClusterStatus{} +func (d *ddcBucketContract) ClusterGet(clusterId ClusterId) (*ClusterInfo, error) { + res := &ClusterInfo{} err := d.callToRead(res, d.clusterGetMethodId, types.U32(clusterId)) return res, err } -func (d *ddcBucketContract) NodeGet(nodeId uint32) (*NodeStatus, error) { - res := &NodeStatus{} - err := d.callToRead(res, d.nodeGetMethodId, types.U32(nodeId)) - - return res, err -} - -func (d *ddcBucketContract) CDNClusterGet(clusterId uint32) (*CDNClusterStatus, error) { - res := &CDNClusterStatus{} - err := d.callToRead(res, d.cdnClusterGetMethodId, types.U32(clusterId)) +func (d *ddcBucketContract) NodeGet(nodeKey NodeKey) (*NodeInfo, error) { + res := &NodeInfo{} + err := d.callToRead(res, d.nodeGetMethodId, nodeKey) return res, err } -func (d *ddcBucketContract) CDNNodeGet(nodeId uint32) (*CDNNodeStatus, error) { - res := &CDNNodeStatus{} - err := d.callToRead(res, d.cdnNodeGetMethodId, types.U32(nodeId)) +func (d *ddcBucketContract) CdnNodeGet(nodeKey CdnNodeKey) (*CdnNodeInfo, error) { + res := &CdnNodeInfo{} + err := d.callToRead(res, d.cdnNodeGetMethodId, nodeKey) return res, err } -func (d *ddcBucketContract) AccountGet(account types.AccountID) (*Account, error) { +func (d *ddcBucketContract) AccountGet(account AccountId) (*Account, error) { res := &Account{} if err := d.callToRead(res, d.accountGetMethodId, account); err != nil { return nil, err @@ -183,8 +650,35 @@ func (d *ddcBucketContract) AccountGet(account types.AccountID) (*Account, error return res, nil } +func (d *ddcBucketContract) callToExec(ctx context.Context, keyPair signature.KeyringPair, method []byte, args ...interface{}) (types.Hash, error) { + + contractAddress, err := pkg.DecodeAccountIDFromSS58(d.contractAddressSS58) + if err != nil { + return types.Hash{}, err + } + + call := pkg.ContractCall{ + ContractAddress: contractAddress, + ContractAddressSS58: d.contractAddressSS58, + From: keyPair, + Value: 0, + GasLimit: DEFAULT_GAS_LIMIT, + Method: method, + Args: args, + } + + blockHash, err := d.chainClient.CallToExec(ctx, call) + if err != nil { + return types.Hash{}, err + } + + d.lastAccessTime = time.Now() + + return blockHash, nil +} + func (d *ddcBucketContract) callToRead(result interface{}, method []byte, args ...interface{}) error { - data, err := d.contract.CallToReadEncoded(d.contractAddressSS58, d.contractAddressSS58, method, args...) + data, err := d.chainClient.CallToReadEncoded(d.contractAddressSS58, d.contractAddressSS58, method, args...) if err != nil { return err } @@ -199,12 +693,23 @@ func (d *ddcBucketContract) callToRead(result interface{}, method []byte, args . return res.err } +func (d *ddcBucketContract) callToReadNoResult(res interface{}, method []byte, args ...interface{}) error { + data, err := d.chainClient.CallToReadEncoded(d.contractAddressSS58, d.contractAddressSS58, method, args...) + if err != nil { + return err + } + + d.lastAccessTime = time.Now() + + return codec.DecodeFromHex(data, res) +} + func (d *ddcBucketContract) AddContractEventHandler(event string, handler func(interface{})) error { - key, err := types.NewHashFromHexString(event) + eventKey, err := types.NewHashFromHexString(event) if err != nil { return err } - entry, found := d.eventDispatcher[key] + entry, found := d.eventDispatcher[eventKey] if !found { return errors.New("Event not found") } @@ -212,7 +717,7 @@ func (d *ddcBucketContract) AddContractEventHandler(event string, handler func(i return errors.New("Contract event handler already set for " + event) } entry.Handler = handler - d.eventDispatcher[key] = entry + d.eventDispatcher[eventKey] = entry return nil } @@ -227,3 +732,260 @@ func (d *ddcBucketContract) GetLastAccessTime() time.Time { func (d *ddcBucketContract) GetEventDispatcher() map[types.Hash]pkg.ContractEventDispatchEntry { return d.eventDispatcher } + +func (d *ddcBucketContract) ClusterCreate(ctx context.Context, keyPair signature.KeyringPair, params Params, resourcePerVNode Resource) (blockHash types.Hash, err error) { + blockHash, err = d.callToExec(ctx, keyPair, d.clusterCreateMethodId, params, resourcePerVNode) + return blockHash, err +} + +func (d *ddcBucketContract) ClusterAddNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey, vNodes [][]Token) error { + _, err := d.callToExec(ctx, keyPair, d.clusterAddNodeMethodId, clusterId, nodeKey, vNodes) + return err +} + +func (d *ddcBucketContract) ClusterRemoveNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey) error { + _, err := d.callToExec(ctx, keyPair, d.clusterRemoveNodeMethodId, clusterId, nodeKey) + return err +} + +func (d *ddcBucketContract) ClusterResetNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey, vNodes [][]Token) error { + _, err := d.callToExec(ctx, keyPair, d.clusterResetNodeMethodId, clusterId, nodeKey, vNodes) + return err +} + +func (d *ddcBucketContract) ClusterReplaceNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, vNodes [][]Token, newNodeKey NodeKey) error { + _, err := d.callToExec(ctx, keyPair, d.clusterReplaceNodeMethodId, clusterId, vNodes, newNodeKey) + return err +} + +func (d *ddcBucketContract) ClusterAddCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey CdnNodeKey) error { + _, err := d.callToExec(ctx, keyPair, d.clusterAddCdnNodeMethodId, clusterId, nodeKey) + return err +} + +func (d *ddcBucketContract) ClusterRemoveCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey CdnNodeKey) error { + _, err := d.callToExec(ctx, keyPair, d.clusterRemoveCdnNodeMethodId, clusterId, nodeKey) + return err +} + +func (d *ddcBucketContract) ClusterSetParams(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, params Params) error { + _, err := d.callToExec(ctx, keyPair, d.clusterSetParamsMethodId, clusterId, params) + return err +} + +func (d *ddcBucketContract) ClusterRemove(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId) error { + _, err := d.callToExec(ctx, keyPair, d.clusterRemoveMethodId, clusterId) + return err +} + +func (d *ddcBucketContract) ClusterSetNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey NodeKey, statusInCluster string) error { + _, err := d.callToExec(ctx, keyPair, d.clusterSetNodeStatusMethodId, clusterId, nodeKey, statusInCluster) + return err +} + +func (d *ddcBucketContract) ClusterSetCdnNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId ClusterId, nodeKey CdnNodeKey, statusInCluster string) error { + _, err := d.callToExec(ctx, keyPair, d.clusterSetCdnNodeStatusMethodId, clusterId, nodeKey, statusInCluster) + return err +} + +func (d *ddcBucketContract) ClusterList(offset types.U32, limit types.U32, filterManagerId types.OptionAccountID) (*ClusterListInfo, error) { + res := ClusterListInfo{} + err := d.callToReadNoResult(&res, d.clusterListMethodId, offset, limit, filterManagerId) + return &res, err +} + +func (d *ddcBucketContract) NodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey, params Params, capacity Resource, rent Rent) (blockHash types.Hash, err error) { + blockHash, err = d.callToExec(ctx, keyPair, d.nodeCreateMethodId, nodeKey, params, capacity, rent) + return blockHash, err +} + +func (d *ddcBucketContract) NodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey) error { + _, err := d.callToExec(ctx, keyPair, d.nodeRemoveMethodId, nodeKey) + return err +} + +func (d *ddcBucketContract) NodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey, params Params) error { + _, err := d.callToExec(ctx, keyPair, d.nodeSetParamsMethodId, nodeKey, params) + return err +} + +func (d *ddcBucketContract) NodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*NodeListInfo, error) { + res := NodeListInfo{} + err := d.callToReadNoResult(&res, d.nodeListMethodId, offset, limit, filterProviderId) + return &res, err +} + +func (d *ddcBucketContract) CdnNodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey, params CDNNodeParams) error { + _, err := d.callToExec(ctx, keyPair, d.cdnNodeCreateMethodId, nodeKey, params) + return err +} + +func (d *ddcBucketContract) CdnNodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey) error { + _, err := d.callToExec(ctx, keyPair, d.cdnNodeRemoveMethodId, nodeKey) + return err +} + +func (d *ddcBucketContract) CdnNodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey, params CDNNodeParams) error { + _, err := d.callToExec(ctx, keyPair, d.cdnNodeSetParamsMethodId, nodeKey, params) + return err +} + +func (d *ddcBucketContract) CdnNodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*CdnNodeListInfo, error) { + res := CdnNodeListInfo{} + err := d.callToReadNoResult(&res, d.cdnNodeListMethodId, offset, limit, filterProviderId) + return &res, err +} + +func (d *ddcBucketContract) HasPermission(account AccountId, permission string) (bool, error) { + hasPermission := false + err := d.callToRead(&hasPermission, d.hasPermissionMethodId, account, permission) + return hasPermission, err +} + +func (d *ddcBucketContract) GrantTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.grantTrustedManagerPermissionMethodId, managerId) + return err +} + +func (d *ddcBucketContract) RevokeTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.revokeTrustedManagerPermissionMethodId, managerId) + return err +} + +func (d *ddcBucketContract) AdminGrantPermission(ctx context.Context, keyPair signature.KeyringPair, grantee AccountId, permission string) error { + _, err := d.callToExec(ctx, keyPair, d.adminGrantPermissionMethodId, grantee, permission) + return err +} + +func (d *ddcBucketContract) AdminRevokePermission(ctx context.Context, keyPair signature.KeyringPair, grantee AccountId, permission string) error { + _, err := d.callToExec(ctx, keyPair, d.adminRevokePermissionMethodId, grantee, permission) + return err +} + +func (d *ddcBucketContract) AdminTransferNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, nodeKey NodeKey, newOwner AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.adminTransferNodeOwnershipMethodId, nodeKey, newOwner) + return err +} + +func (d *ddcBucketContract) AdminTransferCdnNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, nodeKey CdnNodeKey, newOwner AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.adminTransferCdnNodeOwnershipMethodId, nodeKey, newOwner) + return err +} + +func (d *ddcBucketContract) AccountDeposit(ctx context.Context, keyPair signature.KeyringPair) error { + + _, err := d.callToExec(ctx, keyPair, d.accountDepositMethodId) + return err +} + +func (d *ddcBucketContract) AccountBond(ctx context.Context, keyPair signature.KeyringPair, bondAmount Balance) error { + _, err := d.callToExec(ctx, keyPair, d.accountBondMethodId, bondAmount) + return err +} + +func (d *ddcBucketContract) AccountUnbond(ctx context.Context, keyPair signature.KeyringPair, bondAmount Balance) error { + _, err := d.callToExec(ctx, keyPair, d.accountUnbondMethodId, bondAmount) + return err +} + +func (d *ddcBucketContract) AccountGetUsdPerCere() (Balance, error) { + balance := Balance{} + err := d.callToRead(&balance, d.accountGetUsdPerCereMethodId) + return balance, err +} + +func (d *ddcBucketContract) AccountSetUsdPerCere(ctx context.Context, keyPair signature.KeyringPair, usdPerCere Balance) error { + _, err := d.callToExec(ctx, keyPair, d.accountSetUsdPerCereMethodId, usdPerCere) + return err +} + +func (d *ddcBucketContract) AccountWithdrawUnbonded(ctx context.Context, keyPair signature.KeyringPair) error { + _, err := d.callToExec(ctx, keyPair, d.accountWithdrawUnbondedMethodId) + return err +} + +func (d *ddcBucketContract) GetAccounts() ([]types.AccountID, error) { + var accounts []AccountId + err := d.callToRead(&accounts, d.getAccountsMethodId) + + return accounts, err +} + +func (d *ddcBucketContract) BucketCreate(ctx context.Context, keyPair signature.KeyringPair, bucketParams BucketParams, clusterId ClusterId, ownerId types.OptionAccountID) (blockHash types.Hash, err error) { + blockHash, err = d.callToExec(ctx, keyPair, d.bucketCreateMethodId, bucketParams, clusterId, ownerId) + return blockHash, err +} + +func (d *ddcBucketContract) BucketChangeOwner(ctx context.Context, keyPair signature.KeyringPair, bucketId BucketId, newOwnerId AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.bucketChangeOwnerMethodId, bucketId, newOwnerId) + return err +} + +func (d *ddcBucketContract) BucketAllocIntoCluster(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, resource Resource) error { + _, err := d.callToExec(ctx, keyPair, d.bucketAllocIntoClusterMethodId, resource, bucketId) + return err +} + +func (d *ddcBucketContract) BucketSettlePayment(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32) error { + _, err := d.callToExec(ctx, keyPair, d.bucketSettlePaymentMethodId, bucketId) + return err +} + +func (d *ddcBucketContract) BucketChangeParams(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, bucketParams BucketParams) error { + _, err := d.callToExec(ctx, keyPair, d.bucketChangeParamsMethodId, bucketParams, bucketId) + return err +} + +func (d *ddcBucketContract) BucketList(offset types.U32, limit types.U32, filterOwnerId types.OptionAccountID) (*BucketListInfo, error) { + res := BucketListInfo{} + err := d.callToReadNoResult(&res, d.bucketListMethodId, offset, limit, filterOwnerId) + return &res, err +} + +func (d *ddcBucketContract) BucketListForAccount(ownerId AccountId) ([]Bucket, error) { + res := []Bucket{} + err := d.callToRead(&res, d.bucketListForAccountMethodId, ownerId) + return res, err +} + +func (d *ddcBucketContract) BucketSetAvailability(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, publicAvailability bool) error { + _, err := d.callToExec(ctx, keyPair, d.bucketSetAvailabilityMethodId, publicAvailability, bucketId) + return err +} + +func (d *ddcBucketContract) BucketSetResourceCap(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, newResourceCap Resource) error { + _, err := d.callToExec(ctx, keyPair, d.bucketSetResourceCapMethodId, newResourceCap, bucketId) + return err +} + +func (d *ddcBucketContract) GetBucketWriters(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32) ([]AccountId, error) { + res := []AccountId{} + _, err := d.callToExec(ctx, keyPair, d.getBucketWritersMethodId, &res, bucketId) + return res, err +} + +func (d *ddcBucketContract) GetBucketReaders(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32) ([]AccountId, error) { + res := []AccountId{} + _, err := d.callToExec(ctx, keyPair, d.getBucketReadersMethodId, &res, bucketId) + return res, err +} + +func (d *ddcBucketContract) BucketSetWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, writer AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.bucketSetWriterPermMethodId, bucketId, writer) + return err +} + +func (d *ddcBucketContract) BucketRevokeWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, writer AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.bucketRevokeWriterPermMethodId, bucketId, writer) + return err +} + +func (d *ddcBucketContract) BucketSetReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, reader AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.bucketSetReaderPermMethodId, bucketId, reader) + return err +} + +func (d *ddcBucketContract) BucketRevokeReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId types.U32, reader AccountId) error { + _, err := d.callToExec(ctx, keyPair, d.bucketRevokeReaderPermMethodId, bucketId, reader) + return err +} diff --git a/contract/pkg/bucket/ddc_bucket_contract_errors.go b/contract/pkg/bucket/ddc_bucket_contract_errors.go index 2b9ee6e..e57f66b 100644 --- a/contract/pkg/bucket/ddc_bucket_contract_errors.go +++ b/contract/pkg/bucket/ddc_bucket_contract_errors.go @@ -3,31 +3,183 @@ package bucket import "errors" const ( - bucketDoesNotExist = iota - providerDoesNotExist - unauthorizedProvider + nodeDoesNotExist = iota + cdnNodeDoesNotExist + nodeAlreadyExists + cdnNodeAlreadyExists + accountDoesNotExist + paramsDoesNotExist + paramsSizeExceedsLimit + onlyOwner + onlyNodeProvider + onlyCdnNodeProvider + onlyClusterManager + onlyTrustedClusterManager + onlyValidator + onlySuperAdmin + onlyClusterManagerOrNodeProvider + onlyClusterManagerOrCdnNodeProvider + unauthorized + clusterDoesNotExist + clusterIsNotEmpty + topologyIsNotCreated + topologyAlreadyExists + nodesSizeExceedsLimit + cdnNodesSizeExceedsLimit + vNodesSizeExceedsLimit + accountsSizeExceedsLimit + nodeIsNotAddedToCluster + nodeIsAddedToCluster + cdnNodeIsNotAddedToCluster + cdnNodeIsAddedToCluster + vNodeDoesNotExistsInCluster + vNodeIsNotAssignedToNode + vNodeIsAlreadyAssignedToNode + atLeastOneVNodeHasToBeAssigned + nodeProviderIsNotSuperAdmin + cdnNodeOwnerIsNotSuperAdmin + bucketDoesNotExist + bondingPeriodNotFinished transferFailed + insufficientBalance + insufficientNodeResources + insufficientClusterResources + eraSettingFailed ) -//ToDo update error regarding latest contract +// ToDo update error regarding latest contract var ( - ErrBucketDoesNotExist = errors.New("bucket doesn't exist") - ErrProviderDoesNotExist = errors.New("provider doesn't exist") - ErrUnauthorizedProvider = errors.New("unauthorized provider") - ErrTransferFailed = errors.New("transfer failed") - ErrUndefined = errors.New("undefined error") + ErrBucketDoesNotExist = errors.New("bucket doesn't exist") + ErrTransferFailed = errors.New("transfer failed") + ErrUndefined = errors.New("undefined error") + ErrNodeDoesNotExist = errors.New("node does not exist") + ErrCdnNodeDoesNotExist = errors.New("cdn node does not exist") + ErrNodeAlreadyExists = errors.New("node already exists") + ErrCdnNodeAlreadyExists = errors.New("cdn node already exists") + ErrAccountDoesNotExist = errors.New("account does not exist") + ErrParamsDoesNotExist = errors.New("params does not exist") + ErrParamsSizeExceedsLimit = errors.New("params size exceeds limit") + ErrOnlyOwner = errors.New("only owner") + ErrOnlyNodeProvider = errors.New("only node provider") + ErrOnlyCdnNodeProvider = errors.New("only cdn node provider") + ErrOnlyClusterManager = errors.New("only cluster manager") + ErrOnlyTrustedClusterManager = errors.New("only trusted cluster manager") + ErrOnlyValidator = errors.New("only validator") + ErrOnlySuperAdmin = errors.New("only super admin") + ErrOnlyClusterManagerOrNodeProvider = errors.New("only cluster manager or node provider") + ErrOnlyClusterManagerOrCdnNodeProvider = errors.New("only cluster manager or cdn node provider") + ErrUnauthorized = errors.New("unauthorized") + ErrClusterDoesNotExist = errors.New("cluster does not exist") + ErrClusterIsNotEmpty = errors.New("cluster is not empty") + ErrTopologyIsNotCreated = errors.New("topology is not created") + ErrTopologyAlreadyExists = errors.New("topology already exists") + ErrNodesSizeExceedsLimit = errors.New("nodes size exceeds limit") + ErrCdnNodesSizeExceedsLimit = errors.New("cdn nodes size exceeds limit") + ErrVNodesSizeExceedsLimit = errors.New("vnodes size exceeds limit") + ErrAccountsSizeExceedsLimit = errors.New("accounts size exceeds limit") + ErrNodeIsNotAddedToCluster = errors.New("node is not added to cluster") + ErrNodeIsAddedToCluster = errors.New("node is added to cluster") + ErrCdnNodeIsNotAddedToCluster = errors.New("cdn node is not added to cluster") + ErrCdnNodeIsAddedToCluster = errors.New("cdn node is added to cluster") + ErrVNodeDoesNotExistsInCluster = errors.New("vnode does not exists in cluster") + ErrVNodeIsNotAssignedToNode = errors.New("vnode is not assigned to node") + ErrVNodeIsAlreadyAssignedToNode = errors.New("vnode is already assigned to node") + ErrAtLeastOneVNodeHasToBeAssigned = errors.New("at least one vnode has to be assigned") + ErrNodeProviderIsNotSuperAdmin = errors.New("node provider is not super admin") + ErrCdnNodeOwnerIsNotSuperAdmin = errors.New("cdn node owner is not super admin") + ErrBondingPeriodNotFinished = errors.New("bonding period is not finished") + ErrInsufficientBalance = errors.New("insufficient balance") + ErrInsufficientNodeResources = errors.New("insufficient node resources") + ErrInsufficientClusterResources = errors.New("insufficient cluster resources") + ErrEraSettingFailed = errors.New("era setting failed") ) func parseDdcBucketContractError(error uint8) error { switch error { case bucketDoesNotExist: return ErrBucketDoesNotExist - case providerDoesNotExist: - return ErrProviderDoesNotExist - case unauthorizedProvider: - return ErrUnauthorizedProvider case transferFailed: return ErrTransferFailed + case nodeDoesNotExist: + return ErrNodeDoesNotExist + case cdnNodeDoesNotExist: + return ErrCdnNodeDoesNotExist + case nodeAlreadyExists: + return ErrNodeAlreadyExists + case cdnNodeAlreadyExists: + return ErrCdnNodeAlreadyExists + case accountDoesNotExist: + return ErrAccountDoesNotExist + case paramsDoesNotExist: + return ErrParamsDoesNotExist + case paramsSizeExceedsLimit: + return ErrParamsSizeExceedsLimit + case onlyOwner: + return ErrOnlyOwner + case onlyNodeProvider: + return ErrOnlyNodeProvider + case onlyCdnNodeProvider: + return ErrOnlyCdnNodeProvider + case onlyClusterManager: + return ErrOnlyClusterManager + case onlyTrustedClusterManager: + return ErrOnlyTrustedClusterManager + case onlyValidator: + return ErrOnlyValidator + case onlySuperAdmin: + return ErrOnlySuperAdmin + case onlyClusterManagerOrNodeProvider: + return ErrOnlyClusterManagerOrNodeProvider + case onlyClusterManagerOrCdnNodeProvider: + return ErrOnlyClusterManagerOrCdnNodeProvider + case unauthorized: + return ErrUnauthorized + case clusterDoesNotExist: + return ErrClusterDoesNotExist + case clusterIsNotEmpty: + return ErrClusterIsNotEmpty + case topologyIsNotCreated: + return ErrTopologyIsNotCreated + case topologyAlreadyExists: + return ErrTopologyAlreadyExists + case nodesSizeExceedsLimit: + return ErrNodesSizeExceedsLimit + case cdnNodesSizeExceedsLimit: + return ErrCdnNodesSizeExceedsLimit + case vNodesSizeExceedsLimit: + return ErrVNodesSizeExceedsLimit + case accountsSizeExceedsLimit: + return ErrAccountsSizeExceedsLimit + case nodeIsNotAddedToCluster: + return ErrNodeIsNotAddedToCluster + case nodeIsAddedToCluster: + return ErrNodeIsAddedToCluster + case cdnNodeIsNotAddedToCluster: + return ErrCdnNodeIsNotAddedToCluster + case cdnNodeIsAddedToCluster: + return ErrCdnNodeIsAddedToCluster + case vNodeDoesNotExistsInCluster: + return ErrVNodeDoesNotExistsInCluster + case vNodeIsNotAssignedToNode: + return ErrVNodeIsNotAssignedToNode + case vNodeIsAlreadyAssignedToNode: + return ErrVNodeIsAlreadyAssignedToNode + case atLeastOneVNodeHasToBeAssigned: + return ErrAtLeastOneVNodeHasToBeAssigned + case nodeProviderIsNotSuperAdmin: + return ErrNodeProviderIsNotSuperAdmin + case cdnNodeOwnerIsNotSuperAdmin: + return ErrCdnNodeOwnerIsNotSuperAdmin + case bondingPeriodNotFinished: + return ErrBondingPeriodNotFinished + case insufficientBalance: + return ErrInsufficientBalance + case insufficientNodeResources: + return ErrInsufficientNodeResources + case insufficientClusterResources: + return ErrInsufficientClusterResources + case eraSettingFailed: + return ErrEraSettingFailed default: return ErrUndefined } diff --git a/contract/pkg/bucket/messages.go b/contract/pkg/bucket/messages.go index 9ca71ff..253d273 100644 --- a/contract/pkg/bucket/messages.go +++ b/contract/pkg/bucket/messages.go @@ -2,6 +2,7 @@ package bucket import ( "encoding/json" + "fmt" "math/big" "time" @@ -9,87 +10,109 @@ import ( ) type ( - Balance = types.U128 - Cash = Balance - Resource = uint32 - NodeId = uint32 - Token = uint64 - ClusterId = uint32 - AccountId = types.AccountID - ProviderId = AccountId - BucketId = uint32 - Params = string - BucketParams = Params - NodeState = byte + Balance = types.U128 + Cash = Balance + Resource = types.U32 + Token = types.U64 + ClusterId = types.U32 + AccountId = types.AccountID + ProviderId = AccountId + BucketId = types.U32 + Params = string + BucketParams = Params + NodeParams = Params + CdnNodeParams = Params + NodeStatusInCluster = uint8 + NodeKey = AccountId + CdnNodeKey = AccountId + Rent = Balance ) +type UsdPerCereInfo struct { + Balance Balance +} + const ( - UNKNOWN NodeState = iota + ADDING = iota ACTIVE - ADDING DELETING OFFLINE ) -var NodeTags = map[string]byte{ - "UNKNOWN": UNKNOWN, - "ACTIVE": ACTIVE, +const UNKNOWN_NODE_STATUS_IN_CLUSTER byte = 0xFF + +var NodeStatusesInClusterMap = map[string]byte{ "ADDING": ADDING, + "ACTIVE": ACTIVE, "DELETING": DELETING, "OFFLINE": OFFLINE, } type Cluster struct { ManagerId AccountId + Params Params + NodesKeys []NodeKey ResourcePerVNode Resource ResourceUsed Resource Revenues Cash - Nodes []NodeId - VNodes [][]Token TotalRent Balance + CdnNodesKeys []CdnNodeKey + CdnRevenues Cash + CdnUsdPerGb Balance } -type ClusterStatus struct { - ClusterId ClusterId - Cluster Cluster - Params Params +type NodeVNodesInfo struct { + NodeKey NodeKey + VNodes []Token } -type CDNCluster struct { - ManagerId AccountId - CDNNodes []NodeId - ResourceUsed Resource - Revenues Cash - UsdPerGb Balance +type ClusterInfo struct { + ClusterId ClusterId + Cluster Cluster + NodesVNodes []NodeVNodesInfo } -type CDNClusterStatus struct { - ClusterId ClusterId - CDNCluster CDNCluster +type ClusterListInfo struct { + Clusters []ClusterInfo + Total types.U32 } type Node struct { - ProviderId ProviderId - RentPerMonth Balance - FreeResources Resource - NodeState NodeState + ProviderId ProviderId + RentPerMonth Balance + FreeResources Resource + Params NodeParams + ClusterId types.OptionU32 + StatusInCluster types.OptionU8 } -type NodeStatus struct { - NodeId NodeId +type NodeInfo struct { + Key NodeKey Node Node - Params string + VNodes []Token +} + +type NodeListInfo struct { + Nodes []NodeInfo + Total types.U32 } -type CDNNode struct { +type CdnNode struct { ProviderId ProviderId UndistributedPayment Balance + Params CdnNodeParams + ClusterId types.OptionU32 + StatusInCluster types.OptionU8 +} + +type CdnNodeInfo struct { + Key CdnNodeKey + Node CdnNode } -type CDNNodeStatus struct { - NodeId NodeId - Node CDNNode - Params string +type CdnNodeListInfo struct { + Nodes []CdnNodeInfo + Total types.U32 } type Bucket struct { @@ -100,18 +123,28 @@ type Bucket struct { GasConsumptionCap Resource } +type Flow struct { + From AccountId + Schedule Schedule +} + type Schedule struct { Rate Balance Offset Balance } -type BucketStatus struct { +type BucketInfo struct { BucketId BucketId Bucket Bucket Params BucketParams WriterIds []AccountId ReaderIds []AccountId - RentCoveredUntilMs uint64 + RentCoveredUntilMs types.U64 +} + +type BucketListInfo struct { + Buckets []BucketInfo + Total types.U32 } type Account struct { @@ -119,7 +152,7 @@ type Account struct { Bonded Cash Negative Cash UnboundedAmount Cash - UnbondedTimestamp uint64 + UnbondedTimestamp types.U64 PayableSchedule Schedule } @@ -144,45 +177,97 @@ type BucketAvailabilityUpdatedEvent struct { PublicAvailability bool } +type BucketParamsSetEvent struct { + BucketId BucketId + BucketParams BucketParams +} + type ClusterCreatedEvent struct { ClusterId ClusterId AccountId AccountId ClusterParams Params } -type ClusterNodeReplacedEvent struct { - ClusterId ClusterId - NodeId NodeId +type ClusterParamsSetEvent struct { + ClusterId ClusterId + ClusterParams ClusterParams } -type ClusterReserveResourceEvent struct { +type ClusterRemovedEvent struct { ClusterId ClusterId - NodeId NodeId } -type ClusterDistributeRevenuesEvent struct { +type ClusterNodeStatusSetEvent struct { + ClusterId ClusterId + NodeKey NodeKey + NodeStatusInCluster NodeStatusInCluster +} + +type ClusterNodeAddedEvent struct { ClusterId ClusterId - AccountId AccountId + NodeKey NodeKey + VNodes []Token } -type CdnClusterCreatedEvent struct { +type ClusterNodeRemovedEvent struct { ClusterId ClusterId - AccountId AccountId + NodeKey NodeKey } -type CdnClusterDistributeRevenuesEvent struct { +type ClusterCdnNodeAddedEvent struct { ClusterId ClusterId - ProviderId AccountId + CdnNodeKey CdnNodeKey } -type CdnNodeCreatedEvent struct { - NodeId NodeId +type ClusterCdnNodeRemovedEvent struct { + ClusterId ClusterId + CdnNodeKey CdnNodeKey +} + +type CdnNodeRemovedEvent struct { + CdnNodeKey CdnNodeKey +} + +type NodeRemovedEvent struct { + NodeKey NodeKey +} + +type ClusterNodeResetEvent struct { + ClusterId ClusterId + NodeKey NodeKey + VNodes []Token +} + +type ClusterCdnNodeStatusSetEvent struct { + CdnNodeKey CdnNodeKey + ClusterId ClusterId + NodeStatusInCluster NodeStatusInCluster +} + +type ClusterNodeReplacedEvent struct { + ClusterId ClusterId + NodeKey NodeKey + VNodes []Token +} + +type ClusterReserveResourceEvent struct { + ClusterId ClusterId + NodeKey NodeKey +} + +type ClusterDistributeRevenuesEvent struct { + ClusterId ClusterId AccountId AccountId - Payment Balance +} + +type CdnNodeCreatedEvent struct { + CdnNodeKey CdnNodeKey + AccountId AccountId + Payment Balance } type NodeCreatedEvent struct { - NodeId NodeId + NodeKey NodeKey ProviderId AccountId RentPerMonth Balance NodeParams Params @@ -203,6 +288,41 @@ type RevokePermissionEvent struct { Permission byte } +type CdnNodeOwnershipTransferredEvent struct { + AccountId AccountId + CdnNodeKey CdnNodeKey +} + +type NodeOwnershipTransferredEvent struct { + AccountId AccountId + NodeKey NodeKey +} + +type PermissionRevokedEvent struct { + AccountId AccountId + Permission byte +} + +type PermissionGrantedEvent struct { + AccountId AccountId + Permission byte +} + +type CdnNodeParamsSetEvent struct { + CdnNodeKey CdnNodeKey + CdnNodeParams CdnNodeParams +} + +type NodeParamsSetEvent struct { + NodeKey NodeKey + NodeParams Params +} + +type ClusterDistributeCdnRevenuesEvent struct { + ClusterId ClusterId + ProviderId AccountId +} + func (a *Account) HasBalance() bool { return a.Bonded.Cmp(big.NewInt(0)) > 0 } @@ -211,9 +331,9 @@ type ClusterParams struct { ReplicationFactor FlexInt `json:"replicationFactor"` } -func (c *ClusterStatus) ReplicationFactor() uint { +func (c *ClusterInfo) ReplicationFactor() uint { params := &ClusterParams{} - err := json.Unmarshal([]byte(c.Params), params) + err := json.Unmarshal([]byte(c.Cluster.Params), params) if err != nil || params.ReplicationFactor <= 0 { return 0 } @@ -221,11 +341,11 @@ func (c *ClusterStatus) ReplicationFactor() uint { return uint(params.ReplicationFactor) } -func (b *BucketStatus) RentExpired() bool { - return b.RentCoveredUntilMs < uint64(time.Now().UnixMilli()) +func (b *BucketInfo) RentExpired() bool { + return b.RentCoveredUntilMs < types.U64(time.Now().UnixMilli()) } -func (b *BucketStatus) HasWriteAccess(publicKey []byte) bool { +func (b *BucketInfo) HasWriteAccess(publicKey []byte) bool { address, err := types.NewAddressFromAccountID(publicKey) if err != nil { return false @@ -234,7 +354,7 @@ func (b *BucketStatus) HasWriteAccess(publicKey []byte) bool { return b.isOwner(address) || b.isWriter(address) } -func (b *BucketStatus) HasReadAccess(publicKey []byte) bool { +func (b *BucketInfo) HasReadAccess(publicKey []byte) bool { address, err := types.NewAddressFromAccountID(publicKey) if err != nil { return false @@ -243,7 +363,7 @@ func (b *BucketStatus) HasReadAccess(publicKey []byte) bool { return b.isOwner(address) || b.isWriter(address) || b.isReader(address) } -func (b *BucketStatus) IsOwner(publicKey []byte) bool { +func (b *BucketInfo) IsOwner(publicKey []byte) bool { address, err := types.NewAddressFromAccountID(publicKey) if err != nil { return false @@ -252,11 +372,11 @@ func (b *BucketStatus) IsOwner(publicKey []byte) bool { return b.isOwner(address) } -func (b *BucketStatus) isOwner(address types.Address) bool { +func (b *BucketInfo) isOwner(address types.Address) bool { return b.Bucket.OwnerId == address.AsAccountID } -func (b *BucketStatus) isWriter(address types.Address) bool { +func (b *BucketInfo) isWriter(address types.Address) bool { for _, writerId := range b.WriterIds { if writerId == address.AsAccountID { return true @@ -266,7 +386,7 @@ func (b *BucketStatus) isWriter(address types.Address) bool { return false } -func (b *BucketStatus) isReader(address types.Address) bool { +func (b *BucketInfo) isReader(address types.Address) bool { for _, readerId := range b.ReaderIds { if readerId == address.AsAccountID { return true @@ -275,3 +395,29 @@ func (b *BucketStatus) isReader(address types.Address) bool { return false } + +func (n *Node) GetStatusInCluster() (NodeStatusInCluster, error) { + hasValue, val := n.StatusInCluster.Unwrap() + if !hasValue { + return UNKNOWN_NODE_STATUS_IN_CLUSTER, fmt.Errorf("unknown storage node status in cluster") + } else { + return uint8(val), nil + } +} + +func (n *CdnNode) GetStatusInCluster() (NodeStatusInCluster, error) { + hasValue, val := n.StatusInCluster.Unwrap() + if !hasValue { + return UNKNOWN_NODE_STATUS_IN_CLUSTER, fmt.Errorf("unknown cdn node status in cluster") + } else { + return uint8(val), nil + } +} + +func (n *NodeInfo) GetStatusInCluster() (NodeStatusInCluster, error) { + return n.Node.GetStatusInCluster() +} + +func (n *CdnNodeInfo) GetStatusInCluster() (NodeStatusInCluster, error) { + return n.Node.GetStatusInCluster() +} diff --git a/contract/pkg/bucket/messages_test.go b/contract/pkg/bucket/messages_test.go index df9dcc1..cd2a142 100644 --- a/contract/pkg/bucket/messages_test.go +++ b/contract/pkg/bucket/messages_test.go @@ -2,10 +2,11 @@ package bucket import ( "encoding/hex" - "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" "strings" "testing" + "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/stretchr/testify/assert" ) @@ -17,7 +18,7 @@ func TestBucketWriteAccess(t *testing.T) { publicKeyB, _ := hex.DecodeString(strings.TrimPrefix(publicKey, "0x")) accountID, _ := pkg.DecodeAccountIDFromSS58(ss58) - bucketStatus := &BucketStatus{WriterIds: []types.AccountID{accountID}} + bucketStatus := &BucketInfo{WriterIds: []types.AccountID{accountID}} //when hasWriteAccess := bucketStatus.HasWriteAccess(publicKeyB) @@ -28,9 +29,9 @@ func TestBucketWriteAccess(t *testing.T) { func TestClusterStatus_ReplicationFactor(t *testing.T) { type fields struct { - ClusterId ClusterId - Cluster Cluster - Params Params + ClusterId ClusterId + Cluster Cluster + NodesVNodes []NodeVNodesInfo } tests := []struct { name string @@ -41,8 +42,9 @@ func TestClusterStatus_ReplicationFactor(t *testing.T) { name: "ReplicationFactor as integer", fields: fields{ ClusterId: 1, - Params: `{"ReplicationFactor": 3}`, - Cluster: Cluster{}, + Cluster: Cluster{ + Params: `{"ReplicationFactor": 3}`, + }, }, want: 3, }, @@ -50,8 +52,9 @@ func TestClusterStatus_ReplicationFactor(t *testing.T) { name: "ReplicationFactor as string", fields: fields{ ClusterId: 1, - Params: `{"ReplicationFactor": "3"}`, - Cluster: Cluster{}, + Cluster: Cluster{ + Params: `{"ReplicationFactor": "3"}`, + }, }, want: 3, }, @@ -59,18 +62,19 @@ func TestClusterStatus_ReplicationFactor(t *testing.T) { name: "ReplicationFactor not set", fields: fields{ ClusterId: 1, - Params: `{}`, - Cluster: Cluster{}, + Cluster: Cluster{ + Params: `{}`, + }, }, want: 0, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - c := &ClusterStatus{ - ClusterId: tt.fields.ClusterId, - Cluster: tt.fields.Cluster, - Params: tt.fields.Params, + c := &ClusterInfo{ + ClusterId: tt.fields.ClusterId, + Cluster: tt.fields.Cluster, + NodesVNodes: tt.fields.NodesVNodes, } assert.Equalf(t, tt.want, c.ReplicationFactor(), "ReplicationFactor()") }) diff --git a/contract/pkg/bucket/result.go b/contract/pkg/bucket/result.go index 0dfef85..dddb8f2 100644 --- a/contract/pkg/bucket/result.go +++ b/contract/pkg/bucket/result.go @@ -19,6 +19,7 @@ type Result struct { } func (result *Result) decodeDdcBucketContract(encodedData string) error { + if strings.HasPrefix(encodedData, okPrefix) { encodedData = strings.TrimPrefix(encodedData, okPrefix) if err := codec.DecodeFromHex(encodedData, result.data); err != nil { diff --git a/contract/pkg/cache/ddc_bucket_contract_cache.go b/contract/pkg/cache/ddc_bucket_contract_cache.go index 991ed87..b660cae 100644 --- a/contract/pkg/cache/ddc_bucket_contract_cache.go +++ b/contract/pkg/cache/ddc_bucket_contract_cache.go @@ -1,10 +1,12 @@ package cache import ( + "context" "encoding/hex" "strconv" "time" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg/bucket" @@ -25,7 +27,7 @@ type ( ClearNodes() ClearBuckets() ClearAccounts() - ClearNodeById(id bucket.NodeId) + ClearNodeById(id bucket.NodeKey) ClearBucketById(id bucket.BucketId) ClearAccountById(id bucket.AccountId) bucket.DdcBucketContract @@ -94,42 +96,180 @@ func (d *ddcBucketContractCached) HookContractEvents() error { }); err != nil { return errors.Wrap(err, "Unable to hook event "+bucket.DepositEventId) } + + if err := d.ddcBucketContract.AddContractEventHandler(bucket.BucketCreatedEventId, func(raw interface{}) { + args := raw.(*bucket.BucketCreatedEvent) + d.ClearBucketById(args.BucketId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.BucketCreatedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.BucketParamsSetEventId, func(raw interface{}) { + args := raw.(*bucket.BucketParamsSetEvent) + d.ClearBucketById(args.BucketId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.BucketParamsSetEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterNodeAddedEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterNodeAddedEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterNodeAddedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterNodeRemovedEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterNodeRemovedEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterNodeRemovedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterCdnNodeAddedEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterCdnNodeAddedEvent) + d.ClearNodeByKey(args.CdnNodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterCdnNodeAddedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterCdnNodeRemovedEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterCdnNodeRemovedEvent) + d.ClearNodeByKey(args.CdnNodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterCdnNodeRemovedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterNodeStatusSetEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterNodeStatusSetEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterNodeStatusSetEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterCdnNodeStatusSetEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterCdnNodeStatusSetEvent) + d.ClearNodeByKey(args.CdnNodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterCdnNodeStatusSetEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterNodeReplacedEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterNodeReplacedEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterNodeReplacedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterNodeResetEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterNodeResetEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterNodeResetEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.CdnNodeCreatedEventId, func(raw interface{}) { + args := raw.(*bucket.CdnNodeCreatedEvent) + d.ClearNodeByKey(args.CdnNodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.CdnNodeCreatedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.CdnNodeRemovedEventId, func(raw interface{}) { + args := raw.(*bucket.CdnNodeRemovedEvent) + d.ClearNodeByKey(args.CdnNodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.CdnNodeRemovedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.CdnNodeParamsSetEventId, func(raw interface{}) { + args := raw.(*bucket.CdnNodeParamsSetEvent) + d.ClearNodeByKey(args.CdnNodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.CdnNodeParamsSetEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.NodeRemovedEventId, func(raw interface{}) { + args := raw.(*bucket.NodeRemovedEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.NodeRemovedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.NodeParamsSetEventId, func(raw interface{}) { + args := raw.(*bucket.NodeParamsSetEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.NodeParamsSetEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.NodeCreatedEventId, func(raw interface{}) { + args := raw.(*bucket.NodeCreatedEvent) + d.ClearNodeByKey(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.NodeCreatedEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.GrantPermissionEventId, func(raw interface{}) { + args := raw.(*bucket.GrantPermissionEvent) + d.ClearAccountById(args.AccountId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.GrantPermissionEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.RevokePermissionEventId, func(raw interface{}) { + args := raw.(*bucket.RevokePermissionEvent) + d.ClearAccountById(args.AccountId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.RevokePermissionEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.NodeOwnershipTransferredEventId, func(raw interface{}) { + args := raw.(*bucket.NodeOwnershipTransferredEvent) + d.ClearNodeById(args.NodeKey) + d.ClearAccountById(args.AccountId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.NodeOwnershipTransferredEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.CdnNodeOwnershipTransferredEventId, func(raw interface{}) { + args := raw.(*bucket.CdnNodeOwnershipTransferredEvent) + d.ClearNodeById(args.CdnNodeKey) + d.ClearAccountById(args.AccountId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.CdnNodeOwnershipTransferredEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterReserveResourceEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterReserveResourceEvent) + d.ClearNodeById(args.NodeKey) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterReserveResourceEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterDistributeRevenuesEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterDistributeRevenuesEvent) + d.ClearAccountById(args.AccountId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterDistributeRevenuesEventId) + } + if err := d.ddcBucketContract.AddContractEventHandler(bucket.ClusterDistributeCdnRevenuesEventId, func(raw interface{}) { + args := raw.(*bucket.ClusterDistributeCdnRevenuesEvent) + d.ClearAccountById(args.ProviderId) + }); err != nil { + return errors.Wrap(err, "Unable to hook event "+bucket.ClusterDistributeCdnRevenuesEventId) + } + return nil } -func (d *ddcBucketContractCached) ClusterGet(clusterId uint32) (*bucket.ClusterStatus, error) { +func (d *ddcBucketContractCached) ClusterGet(clusterId bucket.ClusterId) (*bucket.ClusterInfo, error) { return d.ddcBucketContract.ClusterGet(clusterId) } -func (d *ddcBucketContractCached) NodeGet(nodeId uint32) (*bucket.NodeStatus, error) { - key := toString(nodeId) - result, err := d.nodeSingleFlight.Do(key, func() (interface{}, error) { - if cached, ok := d.nodeCache.Get(key); ok { +func (d *ddcBucketContractCached) NodeGet(nodeKey bucket.NodeKey) (*bucket.NodeInfo, error) { + + result, err := d.nodeSingleFlight.Do(nodeKey.ToHexString(), func() (interface{}, error) { + if cached, ok := d.nodeCache.Get(nodeKey.ToHexString()); ok { return cached, nil } - value, err := d.ddcBucketContract.NodeGet(nodeId) + value, err := d.ddcBucketContract.NodeGet(nodeKey) if err != nil { return nil, err } - d.nodeCache.SetDefault(key, value) + d.nodeCache.SetDefault(nodeKey.ToHexString(), value) return value, nil }) - resp, _ := result.(*bucket.NodeStatus) + resp, _ := result.(*bucket.NodeInfo) return resp, err } -func (d *ddcBucketContractCached) CDNClusterGet(clusterId uint32) (*bucket.CDNClusterStatus, error) { - return d.ddcBucketContract.CDNClusterGet(clusterId) -} - -func (d *ddcBucketContractCached) CDNNodeGet(nodeId uint32) (*bucket.CDNNodeStatus, error) { - return d.ddcBucketContract.CDNNodeGet(nodeId) +func (d *ddcBucketContractCached) CdnNodeGet(nodeKey bucket.CdnNodeKey) (*bucket.CdnNodeInfo, error) { + return d.ddcBucketContract.CdnNodeGet(nodeKey) } -func (d *ddcBucketContractCached) BucketGet(bucketId uint32) (*bucket.BucketStatus, error) { +func (d *ddcBucketContractCached) BucketGet(bucketId bucket.BucketId) (*bucket.BucketInfo, error) { key := toString(bucketId) result, err := d.bucketSingleFlight.Do(key, func() (interface{}, error) { if cached, ok := d.bucketCache.Get(key); ok { @@ -145,7 +285,7 @@ func (d *ddcBucketContractCached) BucketGet(bucketId uint32) (*bucket.BucketStat return value, nil }) - resp, _ := result.(*bucket.BucketStatus) + resp, _ := result.(*bucket.BucketInfo) return resp, err } @@ -203,8 +343,12 @@ func (d *ddcBucketContractCached) ClearAccounts() { d.accountCache.Flush() } -func (d *ddcBucketContractCached) ClearNodeById(id bucket.NodeId) { //nolint:golint,unused - d.nodeCache.Delete(toString(id)) +func (d *ddcBucketContractCached) ClearNodeById(key bucket.NodeKey) { //nolint:golint,unused + d.nodeCache.Delete(key.ToHexString()) +} + +func (d *ddcBucketContractCached) ClearNodeByKey(nodeKey bucket.NodeKey) { + d.nodeCache.Delete(nodeKey.ToHexString()) } func (d *ddcBucketContractCached) ClearBucketById(id bucket.BucketId) { @@ -223,6 +367,525 @@ func cacheDurationOrDefault(duration time.Duration, defaultDuration time.Duratio return defaultDuration } -func toString(value uint32) string { +func isNodeKeyPresent(nodeKeys []bucket.NodeKey, nodeKey bucket.NodeKey) bool { + for _, key := range nodeKeys { + if key == nodeKey { + return true + } + } + return false +} + +func toString(value bucket.BucketId) string { return strconv.FormatUint(uint64(value), 10) } + +func validateCDNNodeParams(params bucket.CDNNodeParams) error { + if params.Url == "" { + return errors.New("Empty CDN node URL.") + } + if params.Size <= 0 { + return errors.New("Invalid CDN node size.") + } + if params.Location == "" { + return errors.New("Empty CDN node location.") + } + + return nil +} + +func (d *ddcBucketContractCached) ClusterCreate(ctx context.Context, keyPair signature.KeyringPair, params bucket.Params, resourcePerVNode bucket.Resource) (blockHash types.Hash, err error) { + blockHash, err = d.ddcBucketContract.ClusterCreate(ctx, keyPair, params, resourcePerVNode) + + if err != nil { + return types.Hash{}, err + } + + return blockHash, nil +} + +func (d *ddcBucketContractCached) ClusterAddNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, vNodes [][]bucket.Token) error { + if len(vNodes) == 0 { + return errors.New("No vNodes provided.") + } + + clusterStatus, responseError := d.ClusterGet(clusterId) + if responseError != nil { + return bucket.ErrClusterDoesNotExist + } + + if isNodeKeyPresent(clusterStatus.Cluster.NodesKeys, nodeKey) { + return bucket.ErrNodeAlreadyExists + } + + err := d.ddcBucketContract.ClusterAddNode(ctx, keyPair, clusterId, nodeKey, vNodes) + if err != nil { + return err + } + + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) ClusterRemoveNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey) error { + err := d.ddcBucketContract.ClusterRemoveNode(ctx, keyPair, clusterId, nodeKey) + if err != nil { + return err + } + + // If the node removal from the contract was successful, clear the cached node status.e + d.ClearNodeByKey(nodeKey) + + return nil +} + +func (d *ddcBucketContractCached) ClusterResetNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, vNodes [][]bucket.Token) error { + clusterStatus, err := d.ClusterGet(clusterId) + if err != nil { + return bucket.ErrClusterDoesNotExist + } + + if !isNodeKeyPresent(clusterStatus.Cluster.NodesKeys, nodeKey) { + return bucket.ErrNodeDoesNotExist + } + + responseError := d.ddcBucketContract.ClusterResetNode(ctx, keyPair, clusterId, nodeKey, vNodes) + + if responseError != nil { + return responseError + } + + d.ClearNodeByKey(nodeKey) + + return nil +} + +func (d *ddcBucketContractCached) ClusterReplaceNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, vNodes [][]bucket.Token, newNodeKey bucket.NodeKey) error { + if len(vNodes) == 0 { + return errors.New("No vNodes provided.") + } + + clusterStatus, clusterError := d.ClusterGet(clusterId) + if clusterError != nil { + return bucket.ErrClusterDoesNotExist + } + + if isNodeKeyPresent(clusterStatus.Cluster.NodesKeys, newNodeKey) { + return bucket.ErrNodeAlreadyExists + } + + err := d.ddcBucketContract.ClusterReplaceNode(ctx, keyPair, clusterId, vNodes, newNodeKey) + if err != nil { + return err + } + + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) ClusterAddCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey) error { + clusterStatus, responseError := d.ClusterGet(clusterId) + if responseError != nil { + return bucket.ErrClusterDoesNotExist + } + + if isNodeKeyPresent(clusterStatus.Cluster.CdnNodesKeys, cdnNodeKey) { + return bucket.ErrCdnNodeAlreadyExists + } + + err := d.ddcBucketContract.ClusterAddCdnNode(ctx, keyPair, clusterId, cdnNodeKey) + if err != nil { + return err + } + + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) ClusterRemoveCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey) error { + + clusterStatus, clusterError := d.ClusterGet(clusterId) + if clusterError != nil { + return bucket.ErrClusterDoesNotExist + } + + if !isNodeKeyPresent(clusterStatus.Cluster.CdnNodesKeys, cdnNodeKey) { + return bucket.ErrCdnNodeDoesNotExist + } + + err := d.ddcBucketContract.ClusterRemoveCdnNode(ctx, keyPair, clusterId, cdnNodeKey) + if err != nil { + return err + } + + d.ClearNodeByKey(cdnNodeKey) + + return nil +} + +func (d *ddcBucketContractCached) ClusterSetParams(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, params bucket.Params) error { + if params == "" { + return errors.New("Empty cluster parameters.") + } + + _, clusterError := d.ClusterGet(clusterId) + if clusterError != nil { + return bucket.ErrClusterDoesNotExist + } + + err := d.ddcBucketContract.ClusterSetParams(ctx, keyPair, clusterId, params) + if err != nil { + return err + } + + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) ClusterRemove(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId) error { + _, clusterError := d.ClusterGet(clusterId) + if clusterError != nil { + return bucket.ErrClusterDoesNotExist + } + + err := d.ddcBucketContract.ClusterRemove(ctx, keyPair, clusterId) + if err != nil { + return err + } + + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) ClusterSetNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, statusInCluster string) error { + if statusInCluster == "" { + return errors.New("Empty status in cluster.") + } + + clusterStatus, clusterError := d.ClusterGet(clusterId) + if clusterError != nil { + return bucket.ErrClusterDoesNotExist + } + + if !isNodeKeyPresent(clusterStatus.Cluster.NodesKeys, nodeKey) { + return bucket.ErrNodeDoesNotExist + } + + err := d.ddcBucketContract.ClusterSetNodeStatus(ctx, keyPair, clusterId, nodeKey, statusInCluster) + if err != nil { + return err + } + + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) ClusterSetCdnNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey, statusInCluster string) error { + if statusInCluster == "" { + return errors.New("Empty status in cluster.") + } + + clusterStatus, err := d.ClusterGet(clusterId) + if err != nil { + return bucket.ErrClusterDoesNotExist + } + + if !isNodeKeyPresent(clusterStatus.Cluster.CdnNodesKeys, cdnNodeKey) { + return bucket.ErrCdnNodeIsNotAddedToCluster + } + + err = d.ddcBucketContract.ClusterSetCdnNodeStatus(ctx, keyPair, clusterId, cdnNodeKey, statusInCluster) + if err != nil { + return err + } + + d.ClearNodeByKey(cdnNodeKey) + + return nil +} + +func (d *ddcBucketContractCached) ClusterList(offset types.U32, limit types.U32, filterManagerId types.OptionAccountID) (*bucket.ClusterListInfo, error) { + if limit == 0 { + return nil, errors.New("Invalid limit. Limit must be greater than zero.") + } + + clusters, err := d.ddcBucketContract.ClusterList(offset, limit, filterManagerId) + + if err != nil { + return nil, err + } + + d.ClearBuckets() + d.ClearNodes() + + return clusters, nil +} + +func (d *ddcBucketContractCached) NodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, params bucket.Params, capacity bucket.Resource, rent bucket.Rent) (blockHash types.Hash, err error) { + blockHash, err = d.ddcBucketContract.NodeCreate(ctx, keyPair, nodeKey, params, capacity, rent) + + d.ClearNodes() + + return blockHash, err +} + +func (d *ddcBucketContractCached) NodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey) error { + err := d.ddcBucketContract.NodeRemove(ctx, keyPair, nodeKey) + + if err != nil { + return err + } + + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) NodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, params bucket.Params) error { + err := d.ddcBucketContract.NodeSetParams(ctx, keyPair, nodeKey, params) + + if err != nil { + return err + } + + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) NodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*bucket.NodeListInfo, error) { + if limit == 0 { + return nil, errors.New("Invalid limit. Limit must be greater than zero.") + } + + nodes, err := d.ddcBucketContract.NodeList(offset, limit, filterProviderId) + if err != nil { + return nil, err + } + + return nodes, nil +} + +func (d *ddcBucketContractCached) CdnNodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey, params bucket.CDNNodeParams) error { + err := d.ddcBucketContract.CdnNodeCreate(ctx, keyPair, nodeKey, params) + + if err != nil { + return err + } + + d.ClearNodes() + + return err +} + +func (d *ddcBucketContractCached) CdnNodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey) error { + err := d.ddcBucketContract.CdnNodeRemove(ctx, keyPair, nodeKey) + if err != nil { + return err + } + + // Clear the corresponding cache since the CDN node data has been modified. + d.ClearBuckets() + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) CdnNodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey, params bucket.CDNNodeParams) error { + if err := validateCDNNodeParams(params); err != nil { + return errors.Wrap(err, "Invalid CDN node params.") + } + + err := d.ddcBucketContract.CdnNodeSetParams(ctx, keyPair, nodeKey, params) + if err != nil { + return err + } + + d.ClearNodes() + + return nil +} + +func (d *ddcBucketContractCached) CdnNodeList(offset types.U32, limit types.U32, filterManagerId types.OptionAccountID) (*bucket.CdnNodeListInfo, error) { + if limit == 0 { + return nil, errors.New("Invalid limit. Limit must be greater than zero.") + } + + nodes, err := d.ddcBucketContract.CdnNodeList(offset, limit, filterManagerId) + if err != nil { + return nil, err + } + + return nodes, nil +} + +func (d *ddcBucketContractCached) HasPermission(account types.AccountID, permission string) (bool, error) { + if permission == "" { + return false, errors.New("Empty permission string.") + } + + return d.ddcBucketContract.HasPermission(account, permission) +} + +func (d *ddcBucketContractCached) GrantTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId bucket.AccountId) error { + err := d.ddcBucketContract.GrantTrustedManagerPermission(ctx, keyPair, managerId) + + d.ClearBuckets() + d.ClearNodes() + + return err +} + +func (d *ddcBucketContractCached) RevokeTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId bucket.AccountId) error { + err := d.ddcBucketContract.RevokeTrustedManagerPermission(ctx, keyPair, managerId) + + d.ClearBuckets() + d.ClearNodes() + + return err +} + +func (d *ddcBucketContractCached) AdminGrantPermission(ctx context.Context, keyPair signature.KeyringPair, grantee bucket.AccountId, permission string) error { + if permission == "" { + return errors.New("Empty permission string.") + } + err := d.ddcBucketContract.AdminGrantPermission(ctx, keyPair, grantee, permission) + + d.ClearBuckets() + d.ClearNodes() + + return err +} + +func (d *ddcBucketContractCached) AdminRevokePermission(ctx context.Context, keyPair signature.KeyringPair, grantee bucket.AccountId, permission string) error { + if permission == "" { + return errors.New("Empty permission string.") + } + err := d.ddcBucketContract.AdminRevokePermission(ctx, keyPair, grantee, permission) + + d.ClearBuckets() + d.ClearNodes() + + return err +} + +func (d *ddcBucketContractCached) AdminTransferNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, newOwner bucket.AccountId) error { + err := d.ddcBucketContract.AdminTransferNodeOwnership(ctx, keyPair, nodeKey, newOwner) + + d.ClearBuckets() + d.ClearNodes() + + return err +} + +func (d *ddcBucketContractCached) AdminTransferCdnNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, cdnNodeKey bucket.CdnNodeKey, newOwner bucket.AccountId) error { + err := d.ddcBucketContract.AdminTransferCdnNodeOwnership(ctx, keyPair, cdnNodeKey, newOwner) + + d.ClearBuckets() + d.ClearNodes() + + return err +} + +// TODO implement caching for underlying methods +func (d *ddcBucketContractCached) AccountDeposit(ctx context.Context, keyPair signature.KeyringPair) error { + return d.ddcBucketContract.AccountDeposit(ctx, keyPair) +} + +func (d *ddcBucketContractCached) AccountBond(ctx context.Context, keyPair signature.KeyringPair, bondAmount bucket.Balance) error { + return d.ddcBucketContract.AccountBond(ctx, keyPair, bondAmount) +} + +func (d *ddcBucketContractCached) AccountUnbond(ctx context.Context, keyPair signature.KeyringPair, bondAmount bucket.Balance) error { + return d.ddcBucketContract.AccountUnbond(ctx, keyPair, bondAmount) +} + +func (d *ddcBucketContractCached) AccountGetUsdPerCere() (bucket.Balance, error) { + return d.ddcBucketContract.AccountGetUsdPerCere() +} + +func (d *ddcBucketContractCached) AccountSetUsdPerCere(ctx context.Context, keyPair signature.KeyringPair, usdPerCere bucket.Balance) error { + return d.ddcBucketContract.AccountSetUsdPerCere(ctx, keyPair, usdPerCere) +} + +func (d *ddcBucketContractCached) AccountWithdrawUnbonded(ctx context.Context, keyPair signature.KeyringPair) error { + return d.ddcBucketContract.AccountWithdrawUnbonded(ctx, keyPair) +} + +func (d *ddcBucketContractCached) GetAccounts() ([]types.AccountID, error) { + accounts, err := d.ddcBucketContract.GetAccounts() + return accounts, err +} + +func (d *ddcBucketContractCached) BucketCreate(ctx context.Context, keyPair signature.KeyringPair, bucketParams bucket.BucketParams, clusterId bucket.ClusterId, ownerId types.OptionAccountID) (blockHash types.Hash, err error) { + return d.ddcBucketContract.BucketCreate(ctx, keyPair, bucketParams, clusterId, ownerId) +} + +func (d *ddcBucketContractCached) BucketChangeOwner(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, ownerId bucket.AccountId) error { + return d.ddcBucketContract.BucketChangeOwner(ctx, keyPair, bucketId, ownerId) +} + +func (d *ddcBucketContractCached) BucketAllocIntoCluster(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, resource bucket.Resource) error { + return d.ddcBucketContract.BucketAllocIntoCluster(ctx, keyPair, bucketId, resource) +} + +func (d *ddcBucketContractCached) BucketSettlePayment(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) error { + return d.ddcBucketContract.BucketSettlePayment(ctx, keyPair, bucketId) +} + +func (d *ddcBucketContractCached) BucketChangeParams(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, bucketParams bucket.BucketParams) error { + return d.ddcBucketContract.BucketChangeParams(ctx, keyPair, bucketId, bucketParams) +} + +func (d *ddcBucketContractCached) BucketList(offset types.U32, limit types.U32, filterOwnerId types.OptionAccountID) (*bucket.BucketListInfo, error) { + return d.ddcBucketContract.BucketList(offset, limit, filterOwnerId) +} + +func (d *ddcBucketContractCached) BucketListForAccount(ownerId bucket.AccountId) ([]bucket.Bucket, error) { + return d.ddcBucketContract.BucketListForAccount(ownerId) +} + +func (d *ddcBucketContractCached) BucketSetAvailability(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, publicAvailability bool) error { + return d.ddcBucketContract.BucketSetAvailability(ctx, keyPair, bucketId, publicAvailability) +} + +func (d *ddcBucketContractCached) BucketSetResourceCap(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, newResourceCap bucket.Resource) error { + return d.ddcBucketContract.BucketSetResourceCap(ctx, keyPair, bucketId, newResourceCap) +} + +func (d *ddcBucketContractCached) GetBucketWriters(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) ([]bucket.AccountId, error) { + return d.ddcBucketContract.GetBucketWriters(ctx, keyPair, bucketId) +} + +func (d *ddcBucketContractCached) GetBucketReaders(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) ([]bucket.AccountId, error) { + return d.ddcBucketContract.GetBucketReaders(ctx, keyPair, bucketId) +} + +func (d *ddcBucketContractCached) BucketSetWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, writer bucket.AccountId) error { + return d.ddcBucketContract.BucketSetWriterPerm(ctx, keyPair, bucketId, writer) +} + +func (d *ddcBucketContractCached) BucketRevokeWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, writer bucket.AccountId) error { + return d.ddcBucketContract.BucketRevokeWriterPerm(ctx, keyPair, bucketId, writer) +} + +func (d *ddcBucketContractCached) BucketSetReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, reader bucket.AccountId) error { + return d.ddcBucketContract.BucketSetReaderPerm(ctx, keyPair, bucketId, reader) +} + +func (d *ddcBucketContractCached) BucketRevokeReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, reader bucket.AccountId) error { + return d.ddcBucketContract.BucketRevokeReaderPerm(ctx, keyPair, bucketId, reader) +} diff --git a/contract/pkg/cache/ddc_bucket_contract_cache_test.go b/contract/pkg/cache/ddc_bucket_contract_cache_test.go index c385b8e..c0fe27f 100644 --- a/contract/pkg/cache/ddc_bucket_contract_cache_test.go +++ b/contract/pkg/cache/ddc_bucket_contract_cache_test.go @@ -1,9 +1,11 @@ package cache import ( + "context" "testing" "time" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg/bucket" @@ -26,36 +28,45 @@ func (m *mockedDdcBucketContract) GetLastAccessTime() time.Time { return args.Get(0).(time.Time) } -func (m *mockedDdcBucketContract) ClusterGet(clusterId uint32) (*bucket.ClusterStatus, error) { +func (m *mockedDdcBucketContract) ClusterGet(clusterId bucket.ClusterId) (*bucket.ClusterInfo, error) { args := m.Called(clusterId) - return args.Get(0).(*bucket.ClusterStatus), args.Error(1) + return args.Get(0).(*bucket.ClusterInfo), args.Error(1) } -func (m *mockedDdcBucketContract) NodeGet(nodeId uint32) (*bucket.NodeStatus, error) { - args := m.Called(nodeId) - return args.Get(0).(*bucket.NodeStatus), args.Error(1) +func (m *mockedDdcBucketContract) NodeGet(nodeKey bucket.NodeKey) (*bucket.NodeInfo, error) { + args := m.Called(nodeKey) + return args.Get(0).(*bucket.NodeInfo), args.Error(1) } -func (m *mockedDdcBucketContract) CDNClusterGet(clusterId uint32) (*bucket.CDNClusterStatus, error) { - args := m.Called(clusterId) - return args.Get(0).(*bucket.CDNClusterStatus), args.Error(1) -} - -func (m *mockedDdcBucketContract) CDNNodeGet(nodeId uint32) (*bucket.CDNNodeStatus, error) { - args := m.Called(nodeId) - return args.Get(0).(*bucket.CDNNodeStatus), args.Error(1) +func (m *mockedDdcBucketContract) CdnNodeGet(nodeKey bucket.CdnNodeKey) (*bucket.CdnNodeInfo, error) { + args := m.Called(nodeKey) + return args.Get(0).(*bucket.CdnNodeInfo), args.Error(1) } -func (m *mockedDdcBucketContract) BucketGet(bucketId uint32) (*bucket.BucketStatus, error) { +func (m *mockedDdcBucketContract) BucketGet(bucketId bucket.BucketId) (*bucket.BucketInfo, error) { args := m.Called(bucketId) - return args.Get(0).(*bucket.BucketStatus), args.Error(1) + return args.Get(0).(*bucket.BucketInfo), args.Error(1) } -func (m *mockedDdcBucketContract) AccountGet(account types.AccountID) (*bucket.Account, error) { +func (m *mockedDdcBucketContract) AccountGet(account bucket.AccountId) (*bucket.Account, error) { args := m.Called(account) return args.Get(0).(*bucket.Account), args.Error(1) } +func (m *mockedDdcBucketContract) CdnNodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*bucket.CdnNodeListInfo, error) { + args := m.Called(offset, limit, filterProviderId) + return args.Get(0).(*bucket.CdnNodeListInfo), args.Error(1) +} + +func (m *mockedDdcBucketContract) NodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*bucket.NodeListInfo, error) { + args := m.Called(offset, limit, filterProviderId) + return args.Get(0).(*bucket.NodeListInfo), args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterCreate(ctx context.Context, keyPair signature.KeyringPair, params bucket.Params, resourcePerVNode bucket.Resource) (blockHash types.Hash, err error) { + return types.Hash{}, nil +} + func (d *mockedDdcBucketContract) AddContractEventHandler(event string, handler func(interface{})) error { return nil } @@ -64,15 +75,217 @@ func (d *mockedDdcBucketContract) GetEventDispatcher() map[types.Hash]pkg.Contra return nil } +func (m *mockedDdcBucketContract) AdminGrantPermission(ctx context.Context, keyPair signature.KeyringPair, grantee bucket.AccountId, permission string) error { + return nil +} + +func (m *mockedDdcBucketContract) AdminRevokePermission(ctx context.Context, keyPair signature.KeyringPair, grantee bucket.AccountId, permission string) error { + return nil +} + +func (m *mockedDdcBucketContract) AdminTransferCdnNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, cdnNodeKey bucket.CdnNodeKey, newOwner bucket.AccountId) error { + return nil +} + +func (m *mockedDdcBucketContract) AdminTransferNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, newOwner bucket.AccountId) error { + return nil +} + +func (m *mockedDdcBucketContract) CdnNodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, params bucket.CDNNodeParams) error { + return nil +} + +func (m *mockedDdcBucketContract) NodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, params bucket.Params, capacity bucket.Resource, rent bucket.Rent) (blockHash types.Hash, err error) { + return types.Hash{}, nil +} + +func (m *mockedDdcBucketContract) CdnNodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey) error { + args := m.Called(nodeKey) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) NodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey) error { + args := m.Called(nodeKey) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) CdnNodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey, params bucket.CDNNodeParams) error { + args := m.Called(nodeKey, params) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterAddCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey) error { + args := m.Called(clusterId, cdnNodeKey) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterAddNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, vNodes [][]bucket.Token) error { + args := m.Called(clusterId, nodeKey, vNodes) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterList(offset types.U32, limit types.U32, filterManagerId types.OptionAccountID) (*bucket.ClusterListInfo, error) { + args := m.Called(offset, limit, filterManagerId) + return args.Get(0).(*bucket.ClusterListInfo), args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterRemoveNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey) error { + args := m.Called(clusterId, nodeKey) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterRemove(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId) error { + args := m.Called(clusterId) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterRemoveCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey) error { + args := m.Called(clusterId, cdnNodeKey) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterReplaceNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, vNodes [][]bucket.Token, newNodeKey bucket.NodeKey) error { + args := m.Called(clusterId, vNodes, newNodeKey) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterResetNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, vNodes [][]bucket.Token) error { + args := m.Called(clusterId, nodeKey, vNodes) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterSetCdnNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey, statusInCluster string) error { + args := m.Called(clusterId, cdnNodeKey, statusInCluster) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterSetNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, statusInCluster string) error { + args := m.Called(clusterId, nodeKey, statusInCluster) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) ClusterSetParams(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, params bucket.Params) error { + args := m.Called(clusterId, params) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) GrantTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId bucket.AccountId) error { + args := m.Called(managerId) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) HasPermission(account bucket.AccountId, permission string) (bool, error) { + args := m.Called(account, permission) + return true, args.Error(1) +} + +func (m *mockedDdcBucketContract) NodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, params bucket.Params) error { + args := m.Called(nodeKey, params) + return args.Error(1) +} + +func (m *mockedDdcBucketContract) RevokeTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId bucket.AccountId) error { + args := m.Called(managerId) + return args.Error(1) +} + +// TODO: implement yhe underlying methods +func (m *mockedDdcBucketContract) AccountDeposit(ctx context.Context, keyPair signature.KeyringPair) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) AccountBond(ctx context.Context, keyPair signature.KeyringPair, bondAmount bucket.Balance) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) AccountUnbond(ctx context.Context, keyPair signature.KeyringPair, bondAmount bucket.Balance) error { + panic("implement me") +} +func (m *mockedDdcBucketContract) AccountGetUsdPerCere() (bucket.Balance, error) { + panic("implement me") +} + +func (m *mockedDdcBucketContract) AccountSetUsdPerCere(ctx context.Context, keyPair signature.KeyringPair, usdPerCere bucket.Balance) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) AccountWithdrawUnbonded(ctx context.Context, keyPair signature.KeyringPair) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) GetAccounts() ([]types.AccountID, error) { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketCreate(ctx context.Context, keyPair signature.KeyringPair, bucketParams bucket.BucketParams, clusterId bucket.ClusterId, ownerId types.OptionAccountID) (blockHash types.Hash, err error) { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketChangeOwner(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, ownerId bucket.AccountId) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketAllocIntoCluster(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, resource bucket.Resource) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketSetResourceCap(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, newResourceCap bucket.Resource) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketSettlePayment(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketChangeParams(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, bucketParams bucket.BucketParams) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketList(offset types.U32, limit types.U32, ownerId types.OptionAccountID) (*bucket.BucketListInfo, error) { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketListForAccount(ownerId bucket.AccountId) ([]bucket.Bucket, error) { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketSetAvailability(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, publicAvailability bool) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) GetBucketWriters(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) ([]types.AccountID, error) { + panic("implement me") +} + +func (m *mockedDdcBucketContract) GetBucketReaders(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) ([]types.AccountID, error) { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketSetWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, writer bucket.AccountId) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketRevokeWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, writer bucket.AccountId) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketSetReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, reader bucket.AccountId) error { + panic("implement me") +} + +func (m *mockedDdcBucketContract) BucketRevokeReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, reader bucket.AccountId) error { + panic("implement me") +} + func TestBucketGet(t *testing.T) { //given ddcBucketContract := &mockedDdcBucketContract{} testSubject := &ddcBucketContractCached{bucketCache: cache.New(defaultExpiration, cleanupInterval), ddcBucketContract: ddcBucketContract} - result := &bucket.BucketStatus{} - ddcBucketContract.On("BucketGet", uint32(1)).Return(result, nil).Once() + result := &bucket.BucketInfo{} + ddcBucketContract.On("BucketGet", types.NewU32(1)).Return(result, nil).Once() //when - bucket, err := testSubject.BucketGet(uint32(1)) + bucket, err := testSubject.BucketGet(types.NewU32(1)) //then assert.NoError(t, err) @@ -84,12 +297,12 @@ func TestBucketGetCached(t *testing.T) { //given ddcBucketContract := &mockedDdcBucketContract{} testSubject := &ddcBucketContractCached{bucketCache: cache.New(defaultExpiration, cleanupInterval), ddcBucketContract: ddcBucketContract} - result := &bucket.BucketStatus{BucketId: uint32(1)} - ddcBucketContract.On("BucketGet", uint32(1)).Return(result, nil).Once() - _, _ = testSubject.BucketGet(uint32(1)) + result := &bucket.BucketInfo{BucketId: types.NewU32(1)} + ddcBucketContract.On("BucketGet", types.NewU32(1)).Return(result, nil).Once() + _, _ = testSubject.BucketGet(types.NewU32(1)) //when - bucket, err := testSubject.BucketGet(uint32(1)) + bucket, err := testSubject.BucketGet(types.NewU32(1)) //then assert.NoError(t, err) @@ -97,3 +310,20 @@ func TestBucketGetCached(t *testing.T) { ddcBucketContract.AssertExpectations(t) ddcBucketContract.AssertNumberOfCalls(t, "BucketGet", 1) } + +// func TestCDNNodeList(t *testing.T) { +// //given +// ddcBucketContract := &mockedDdcBucketContract{} +// testSubject := &ddcBucketContractCached{bucketCache: cache.New(defaultExpiration, cleanupInterval), ddcBucketContract: ddcBucketContract} +// result := []*bucket.CdnNodeInfo{} +// ddcBucketContract.On("CdnNodeGet", 0, 1, "filterManagerId").Return(result, nil).Once() + +// //when +// nodes, err := testSubject.CdnNodeList(0, 1, "filterManagerId") + +// //then +// assert.NoError(t, err) +// assert.Equal(t, result, nodes) +// ddcBucketContract.AssertExpectations(t) +// } +// diff --git a/contract/pkg/chainevents/event_record.go b/contract/pkg/chainevents/event_record.go new file mode 100644 index 0000000..9b195e4 --- /dev/null +++ b/contract/pkg/chainevents/event_record.go @@ -0,0 +1,608 @@ +package chainevents + +import ( + "bytes" + "errors" + "fmt" + "io" + "reflect" + + "github.com/centrifuge/go-substrate-rpc-client/v4/scale" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" + "github.com/ethereum/go-ethereum/log" +) + +// EventRecordsRaw is a raw record for a set of events, represented as the raw bytes. It exists since +// decoding of events can only be done with metadata, so events can't follow the static way of decoding +// other types do. It exposes functions to decode events using metadata and targets. +// Be careful using this in your own structs – it only works as the last value in a struct since it will consume the +// remainder of the encoded data. The reason for this is that it does not contain any length encoding, so it would +// not know where to stop. +type EventRecordsRaw []byte + +// Encode implements encoding for Data, which just unwraps the bytes of Data +func (e EventRecordsRaw) Encode(encoder scale.Encoder) error { + return encoder.Write(e) +} + +// Decode implements decoding for Data, which just reads all the remaining bytes into Data +func (e *EventRecordsRaw) Decode(decoder scale.Decoder) error { + for i := 0; true; i++ { + b, err := decoder.ReadOneByte() + if err == io.EOF { + break + } + if err != nil { + return err + } + *e = append((*e)[:i], b) + } + return nil +} + +// EventRecords is a default set of possible event records that can be used as a target for +// `func (e EventRecordsRaw) Decode(...` +// Sources: +// https://github.com/polkadot-js/api/blob/master/packages/api-augment/src/substrate/events.ts +// https://github.com/polkadot-js/api/blob/master/packages/api-augment/src/polkadot/events.ts +// +//nolint:stylecheck,lll,revive +type EventRecords struct { + Auctions_AuctionStarted []EventAuctionsAuctionStarted `test-gen-blockchain:"polkadot"` + Auctions_AuctionClosed []EventAuctionsAuctionClosed `test-gen-blockchain:"polkadot"` + Auctions_Reserved []EventAuctionsReserved `test-gen-blockchain:"polkadot"` + Auctions_Unreserved []EventAuctionsUnreserved `test-gen-blockchain:"polkadot"` + Auctions_ReserveConfiscated []EventAuctionsReserveConfiscated `test-gen-blockchain:"polkadot"` + Auctions_BidAccepted []EventAuctionsBidAccepted `test-gen-blockchain:"polkadot"` + Auctions_WinningOffset []EventAuctionsWinningOffset `test-gen-blockchain:"polkadot"` + + Assets_Created []EventAssetCreated `test-gen-skip:"true"` + Assets_Issued []EventAssetIssued `test-gen-skip:"true"` + Assets_Transferred []EventAssetTransferred `test-gen-skip:"true"` + Assets_Burned []EventAssetBurned `test-gen-skip:"true"` + Assets_TeamChanged []EventAssetTeamChanged `test-gen-skip:"true"` + Assets_OwnerChanged []EventAssetOwnerChanged `test-gen-skip:"true"` + Assets_Frozen []EventAssetFrozen `test-gen-skip:"true"` + Assets_Thawed []EventAssetThawed `test-gen-skip:"true"` + Assets_AssetFrozen []EventAssetAssetFrozen `test-gen-skip:"true"` + Assets_AssetThawed []EventAssetAssetThawed `test-gen-skip:"true"` + Assets_Destroyed []EventAssetDestroyed `test-gen-skip:"true"` + Assets_ForceCreated []EventAssetForceCreated `test-gen-skip:"true"` + Assets_MetadataSet []EventAssetMetadataSet `test-gen-skip:"true"` + Assets_MetadataCleared []EventAssetMetadataCleared `test-gen-skip:"true"` + Assets_ApprovedTransfer []EventAssetApprovedTransfer `test-gen-skip:"true"` + Assets_ApprovalCancelled []EventAssetApprovalCancelled `test-gen-skip:"true"` + Assets_TransferredApproved []EventAssetTransferredApproved `test-gen-skip:"true"` + Assets_AssetStatusChanged []EventAssetAssetStatusChanged `test-gen-skip:"true"` + + BagsList_Rebagged []EventBagsListRebagged `test-gen-blockchain:"polkadot"` + + Balances_BalanceSet []EventBalancesBalanceSet `test-gen-blockchain:"centrifuge-parachain"` + Balances_Deposit []EventBalancesDeposit `test-gen-blockchain:"centrifuge-parachain"` + Balances_DustLost []EventBalancesDustLost `test-gen-blockchain:"centrifuge-parachain"` + Balances_Endowed []EventBalancesEndowed `test-gen-blockchain:"centrifuge-parachain"` + Balances_Reserved []EventBalancesReserved `test-gen-blockchain:"centrifuge-parachain"` + Balances_ReserveRepatriated []EventBalancesReserveRepatriated `test-gen-blockchain:"centrifuge-parachain"` + Balances_Slashed []EventBalancesSlashed `test-gen-blockchain:"centrifuge-parachain"` + Balances_Transfer []EventBalancesTransfer `test-gen-blockchain:"centrifuge-parachain"` + Balances_Unreserved []EventBalancesUnreserved `test-gen-blockchain:"centrifuge-parachain"` + Balances_Withdraw []EventBalancesWithdraw `test-gen-blockchain:"centrifuge-parachain"` + + Bounties_BountyProposed []EventBountiesBountyProposed `test-gen-blockchain:"polkadot"` + Bounties_BountyRejected []EventBountiesBountyRejected `test-gen-blockchain:"polkadot"` + Bounties_BountyBecameActive []EventBountiesBountyBecameActive `test-gen-blockchain:"polkadot"` + Bounties_BountyAwarded []EventBountiesBountyAwarded `test-gen-blockchain:"polkadot"` + Bounties_BountyClaimed []EventBountiesBountyClaimed `test-gen-blockchain:"polkadot"` + Bounties_BountyCanceled []EventBountiesBountyCanceled `test-gen-blockchain:"polkadot"` + Bounties_BountyExtended []EventBountiesBountyExtended `test-gen-blockchain:"polkadot"` + + ChildBounties_Added []EventChildBountiesAdded `test-gen-skip:"true"` + ChildBounties_Awarded []EventChildBountiesAwarded `test-gen-skip:"true"` + ChildBounties_Claimed []EventChildBountiesClaimed `test-gen-skip:"true"` + ChildBounties_Canceled []EventChildBountiesCanceled `test-gen-skip:"true"` + + Claims_Claimed []EventClaimsClaimed `test-gen-blockchain:"polkadot"` + + CollatorSelection_NewInvulnerables []EventCollatorSelectionNewInvulnerables `test-gen-blockchain:"altair"` + CollatorSelection_NewDesiredCandidates []EventCollatorSelectionNewDesiredCandidates `test-gen-blockchain:"altair"` + CollatorSelection_NewCandidacyBond []EventCollatorSelectionNewCandidacyBond `test-gen-blockchain:"altair"` + CollatorSelection_CandidateAdded []EventCollatorSelectionCandidateAdded `test-gen-blockchain:"altair"` + CollatorSelection_CandidateRemoved []EventCollatorSelectionCandidateRemoved `test-gen-blockchain:"altair"` + + Contracts_CodeRemoved []EventContractsCodeRemoved `test-gen-skip:"true"` + Contracts_CodeStored []EventContractsCodeStored `test-gen-skip:"true"` + Contracts_ContractCodeUpdated []EventContractsContractCodeUpdated `test-gen-skip:"true"` + Contracts_Called []EventContractsCalled `test-gen-skip:"true"` + Contracts_ContractEmitted []EventContractsContractEmitted `test-gen-skip:"true"` + Contracts_Instantiated []EventContractsInstantiated `test-gen-skip:"true"` + Contracts_Terminated []EventContractsTerminated `test-gen-skip:"true"` + + ConvictionVoting_Delegated []EventConvictionVotingDelegated `test-gen-skip:"true"` + ConvictionVoting_Undelegated []EventConvictionVotingUndelegated `test-gen-skip:"true"` + + Council_Approved []EventCouncilApproved `test-gen-blockchain:"centrifuge-parachain"` + Council_Closed []EventCouncilClosed `test-gen-blockchain:"centrifuge-parachain"` + Council_Disapproved []EventCouncilDisapproved `test-gen-blockchain:"centrifuge-parachain"` + Council_Executed []EventCouncilExecuted `test-gen-blockchain:"centrifuge-parachain"` + Council_MemberExecuted []EventCouncilMemberExecuted `test-gen-blockchain:"centrifuge-parachain"` + Council_Proposed []EventCouncilProposed `test-gen-blockchain:"centrifuge-parachain"` + Council_Voted []EventCouncilVoted `test-gen-blockchain:"centrifuge-parachain"` + + Crowdloan_Created []EventCrowdloanCreated `test-gen-blockchain:"polkadot"` + Crowdloan_Contributed []EventCrowdloanContributed `test-gen-blockchain:"polkadot"` + Crowdloan_Withdrew []EventCrowdloanWithdrew `test-gen-blockchain:"polkadot"` + Crowdloan_PartiallyRefunded []EventCrowdloanPartiallyRefunded `test-gen-blockchain:"polkadot"` + Crowdloan_AllRefunded []EventCrowdloanAllRefunded `test-gen-blockchain:"polkadot"` + Crowdloan_Dissolved []EventCrowdloanDissolved `test-gen-blockchain:"polkadot"` + Crowdloan_HandleBidResult []EventCrowdloanHandleBidResult `test-gen-blockchain:"polkadot"` + Crowdloan_Edited []EventCrowdloanEdited `test-gen-blockchain:"polkadot"` + Crowdloan_MemoUpdated []EventCrowdloanMemoUpdated `test-gen-blockchain:"polkadot"` + Crowdloan_AddedToNewRaise []EventCrowdloanAddedToNewRaise `test-gen-blockchain:"polkadot"` + + Democracy_Blacklisted []EventDemocracyBlacklisted `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Cancelled []EventDemocracyCancelled `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Delegated []EventDemocracyDelegated `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Executed []EventDemocracyExecuted `test-gen-blockchain:"centrifuge-parachain"` + Democracy_ExternalTabled []EventDemocracyExternalTabled `test-gen-blockchain:"centrifuge-parachain"` + Democracy_NotPassed []EventDemocracyNotPassed `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Passed []EventDemocracyPassed `test-gen-blockchain:"centrifuge-parachain"` + Democracy_PreimageInvalid []EventDemocracyPreimageInvalid `test-gen-blockchain:"centrifuge-parachain"` + Democracy_PreimageMissing []EventDemocracyPreimageMissing `test-gen-blockchain:"centrifuge-parachain"` + Democracy_PreimageNoted []EventDemocracyPreimageNoted `test-gen-blockchain:"centrifuge-parachain"` + Democracy_PreimageReaped []EventDemocracyPreimageReaped `test-gen-blockchain:"centrifuge-parachain"` + Democracy_PreimageUsed []EventDemocracyPreimageUsed `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Proposed []EventDemocracyProposed `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Seconded []EventDemocracySeconded `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Started []EventDemocracyStarted `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Tabled []EventDemocracyTabled `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Undelegated []EventDemocracyUndelegated `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Vetoed []EventDemocracyVetoed `test-gen-blockchain:"centrifuge-parachain"` + Democracy_Voted []EventDemocracyVoted `test-gen-blockchain:"centrifuge-parachain"` + + ElectionProviderMultiPhase_SolutionStored []EventElectionProviderMultiPhaseSolutionStored `test-gen-blockchain:"polkadot"` + ElectionProviderMultiPhase_ElectionFinalized []EventElectionProviderMultiPhaseElectionFinalized `test-gen-blockchain:"polkadot"` + ElectionProviderMultiPhase_Rewarded []EventElectionProviderMultiPhaseRewarded `test-gen-blockchain:"polkadot"` + ElectionProviderMultiPhase_Slashed []EventElectionProviderMultiPhaseSlashed `test-gen-blockchain:"polkadot"` + ElectionProviderMultiPhase_SignedPhaseStarted []EventElectionProviderMultiPhaseSignedPhaseStarted `test-gen-blockchain:"polkadot"` + ElectionProviderMultiPhase_UnsignedPhaseStarted []EventElectionProviderMultiPhaseUnsignedPhaseStarted `test-gen-blockchain:"polkadot"` + + Elections_CandidateSlashed []EventElectionsCandidateSlashed `test-gen-blockchain:"altair"` + Elections_ElectionError []EventElectionsElectionError `test-gen-blockchain:"altair"` + Elections_EmptyTerm []EventElectionsEmptyTerm `test-gen-blockchain:"altair"` + Elections_MemberKicked []EventElectionsMemberKicked `test-gen-blockchain:"altair"` + Elections_NewTerm []EventElectionsNewTerm `test-gen-blockchain:"altair"` + Elections_Renounced []EventElectionsRenounced `test-gen-blockchain:"altair"` + Elections_SeatHolderSlashed []EventElectionsSeatHolderSlashed `test-gen-blockchain:"altair"` + + Gilt_BidPlaced []EventGiltBidPlaced `test-gen-skip:"true"` + Gilt_BidRetracted []EventGiltBidRetracted `test-gen-skip:"true"` + Gilt_GiltIssued []EventGiltGiltIssued `test-gen-skip:"true"` + Gilt_GiltThawed []EventGiltGiltThawed `test-gen-skip:"true"` + + Grandpa_NewAuthorities []EventGrandpaNewAuthorities `test-gen-blockchain:"polkadot"` + Grandpa_Paused []EventGrandpaPaused `test-gen-blockchain:"polkadot"` + Grandpa_Resumed []EventGrandpaResumed `test-gen-blockchain:"polkadot"` + + Hrmp_OpenChannelRequested []EventHRMPOpenChannelRequested `test-gen-blockchain:"polkadot"` + Hrmp_OpenChannelCanceled []EventHRMPOpenChannelCanceled `test-gen-blockchain:"polkadot"` + Hrmp_OpenChannelAccepted []EventHRMPOpenChannelAccepted `test-gen-blockchain:"polkadot"` + Hrmp_ChannelClosed []EventHRMPChannelClosed `test-gen-blockchain:"polkadot"` + + Identity_IdentityCleared []EventIdentityCleared `test-gen-blockchain:"centrifuge-parachain"` + Identity_IdentityKilled []EventIdentityKilled `test-gen-blockchain:"centrifuge-parachain"` + Identity_IdentitySet []EventIdentitySet `test-gen-blockchain:"centrifuge-parachain"` + Identity_JudgementGiven []EventIdentityJudgementGiven `test-gen-blockchain:"centrifuge-parachain"` + Identity_JudgementRequested []EventIdentityJudgementRequested `test-gen-blockchain:"centrifuge-parachain"` + Identity_JudgementUnrequested []EventIdentityJudgementUnrequested `test-gen-blockchain:"centrifuge-parachain"` + Identity_RegistrarAdded []EventIdentityRegistrarAdded `test-gen-blockchain:"centrifuge-parachain"` + Identity_SubIdentityAdded []EventIdentitySubIdentityAdded `test-gen-blockchain:"centrifuge-parachain"` + Identity_SubIdentityRemoved []EventIdentitySubIdentityRemoved `test-gen-blockchain:"centrifuge-parachain"` + Identity_SubIdentityRevoked []EventIdentitySubIdentityRevoked `test-gen-blockchain:"centrifuge-parachain"` + + ImOnline_AllGood []EventImOnlineAllGood `test-gen-blockchain:"polkadot"` + ImOnline_HeartbeatReceived []EventImOnlineHeartbeatReceived `test-gen-blockchain:"polkadot"` + ImOnline_SomeOffline []EventImOnlineSomeOffline `test-gen-blockchain:"polkadot"` + + Indices_IndexAssigned []EventIndicesIndexAssigned `test-gen-blockchain:"polkadot"` + Indices_IndexFreed []EventIndicesIndexFreed `test-gen-blockchain:"polkadot"` + Indices_IndexFrozen []EventIndicesIndexFrozen `test-gen-blockchain:"polkadot"` + + Lottery_LotteryStarted []EventLotteryLotteryStarted `test-gen-skip:"true"` + Lottery_CallsUpdated []EventLotteryCallsUpdated `test-gen-skip:"true"` + Lottery_Winner []EventLotteryWinner `test-gen-skip:"true"` + Lottery_TicketBought []EventLotteryTicketBought `test-gen-skip:"true"` + + Multisig_MultisigApproval []EventMultisigApproval `test-gen-blockchain:"altair"` + Multisig_MultisigCancelled []EventMultisigCancelled `test-gen-blockchain:"altair"` + Multisig_MultisigExecuted []EventMultisigExecuted `test-gen-blockchain:"altair"` + Multisig_NewMultisig []EventMultisigNewMultisig `test-gen-blockchain:"altair"` + + NftSales_ForSale []EventNftSalesForSale `test-gen-blockchain:"altair"` + NftSales_Removed []EventNftSalesRemoved `test-gen-blockchain:"altair"` + NftSales_Sold []EventNftSalesSold `test-gen-blockchain:"altair"` + + Offences_Offence []EventOffencesOffence `test-gen-blockchain:"polkadot"` + + Paras_CurrentCodeUpdated []EventParasCurrentCodeUpdated `test-gen-blockchain:"polkadot"` + Paras_CurrentHeadUpdated []EventParasCurrentHeadUpdated `test-gen-blockchain:"polkadot"` + Paras_CodeUpgradeScheduled []EventParasCodeUpgradeScheduled `test-gen-blockchain:"polkadot"` + Paras_NewHeadNoted []EventParasNewHeadNoted `test-gen-blockchain:"polkadot"` + Paras_ActionQueued []EventParasActionQueued `test-gen-blockchain:"polkadot"` + Paras_PvfCheckStarted []EventParasPvfCheckStarted `test-gen-blockchain:"polkadot"` + Paras_PvfCheckAccepted []EventParasPvfCheckAccepted `test-gen-blockchain:"polkadot"` + Paras_PvfCheckRejected []EventParasPvfCheckRejected `test-gen-blockchain:"polkadot"` + + ParasDisputes_DisputeInitiated []EventParasDisputesDisputeInitiated `test-gen-skip:"true"` + ParasDisputes_DisputeConcluded []EventParasDisputesDisputeConcluded `test-gen-skip:"true"` + ParasDisputes_DisputeTimedOut []EventParasDisputesDisputeTimedOut `test-gen-skip:"true"` + ParasDisputes_Revert []EventParasDisputesRevert `test-gen-skip:"true"` + + ParaInclusion_CandidateBacked []EventParaInclusionCandidateBacked `test-gen-blockchain:"polkadot"` + ParaInclusion_CandidateIncluded []EventParaInclusionCandidateIncluded `test-gen-blockchain:"polkadot"` + ParaInclusion_CandidateTimedOut []EventParaInclusionCandidateTimedOut `test-gen-blockchain:"polkadot"` + + ParachainSystem_ValidationFunctionStored []EventParachainSystemValidationFunctionStored `test-gen-blockchain:"centrifuge-parachain"` + ParachainSystem_ValidationFunctionApplied []EventParachainSystemValidationFunctionApplied `test-gen-blockchain:"centrifuge-parachain"` + ParachainSystem_ValidationFunctionDiscarded []EventParachainSystemValidationFunctionDiscarded `test-gen-blockchain:"centrifuge-parachain"` + ParachainSystem_UpgradeAuthorized []EventParachainSystemUpgradeAuthorized `test-gen-blockchain:"centrifuge-parachain"` + ParachainSystem_DownwardMessagesReceived []EventParachainSystemDownwardMessagesReceived `test-gen-blockchain:"centrifuge-parachain"` + ParachainSystem_DownwardMessagesProcessed []EventParachainSystemDownwardMessagesProcessed `test-gen-blockchain:"centrifuge-parachain"` + + Preimage_Cleared []EventPreimageCleared `test-gen-skip:"true"` + Preimage_Noted []EventPreimageNoted `test-gen-skip:"true"` + Preimage_Requested []EventPreimageRequested `test-gen-skip:"true"` + + Proxy_Announced []EventProxyAnnounced `test-gen-blockchain:"centrifuge-parachain"` + Proxy_AnonymousCreated []EventProxyAnonymousCreated `test-gen-blockchain:"centrifuge-parachain"` + Proxy_ProxyAdded []EventProxyProxyAdded `test-gen-blockchain:"centrifuge-parachain"` + Proxy_ProxyExecuted []EventProxyProxyExecuted `test-gen-blockchain:"centrifuge-parachain"` + Proxy_ProxyRemoved []EventProxyProxyRemoved `test-gen-blockchain:"centrifuge-parachain"` + + Recovery_AccountRecovered []EventRecoveryAccountRecovered `test-gen-skip:"true"` + Recovery_RecoveryClosed []EventRecoveryClosed `test-gen-skip:"true"` + Recovery_RecoveryCreated []EventRecoveryCreated `test-gen-skip:"true"` + Recovery_RecoveryInitiated []EventRecoveryInitiated `test-gen-skip:"true"` + Recovery_RecoveryRemoved []EventRecoveryRemoved `test-gen-skip:"true"` + Recovery_RecoveryVouched []EventRecoveryVouched `test-gen-skip:"true"` + + Registrar_Registered []EventRegistrarRegistered `test-gen-skip:"true"` + Registrar_Deregistered []EventRegistrarDeregistered `test-gen-skip:"true"` + Registrar_Reserved []EventRegistrarReserved `test-gen-skip:"true"` + + Referenda_Submitted []EventReferendaSubmitted `test-gen-skip:"true"` + Referenda_DecisionDepositPlaced []EventReferendaDecisionDepositPlaced `test-gen-skip:"true"` + Referenda_DecisionDepositRefunded []EventReferendaDecisionDepositRefunded `test-gen-skip:"true"` + Referenda_DepositSlashed []EventReferendaDecisionSlashed `test-gen-skip:"true"` + Referenda_DecisionStarted []EventReferendaDecisionStarted `test-gen-skip:"true"` + Referenda_ConfirmStarted []EventReferendaConfirmStarted `test-gen-skip:"true"` + Referenda_ConfirmAborted []EventReferendaConfirmAborted `test-gen-skip:"true"` + Referenda_Confirmed []EventReferendaConfirmed `test-gen-skip:"true"` + Referenda_Approved []EventReferendaApproved `test-gen-skip:"true"` + Referenda_Rejected []EventReferendaRejected `test-gen-skip:"true"` + Referenda_TimedOut []EventReferendaTimedOut `test-gen-skip:"true"` + Referenda_Cancelled []EventReferendaCancelled `test-gen-skip:"true"` + Referenda_Killed []EventReferendaKilled `test-gen-skip:"true"` + + Scheduler_CallLookupFailed []EventSchedulerCallLookupFailed `test-gen-blockchain:"polkadot"` + Scheduler_Canceled []EventSchedulerCanceled `test-gen-blockchain:"polkadot"` + Scheduler_Dispatched []EventSchedulerDispatched `test-gen-blockchain:"polkadot"` + Scheduler_Scheduled []EventSchedulerScheduled `test-gen-blockchain:"polkadot"` + + Session_NewSession []EventSessionNewSession `test-gen-blockchain:"centrifuge-parachain"` + + Slots_NewLeasePeriod []EventSlotsNewLeasePeriod `test-gen-blockchain:"polkadot"` + Slots_Leased []EventSlotsLeased `test-gen-blockchain:"polkadot"` + + Society_AutoUnbid []EventSocietyAutoUnbid `test-gen-skip:"true"` + Society_Bid []EventSocietyBid `test-gen-skip:"true"` + Society_CandidateSuspended []EventSocietyCandidateSuspended `test-gen-skip:"true"` + Society_Challenged []EventSocietyChallenged `test-gen-skip:"true"` + Society_DefenderVote []EventSocietyDefenderVote `test-gen-skip:"true"` + Society_Deposit []EventSocietyDeposit `test-gen-skip:"true"` + Society_Founded []EventSocietyFounded `test-gen-skip:"true"` + Society_Inducted []EventSocietyInducted `test-gen-skip:"true"` + Society_MemberSuspended []EventSocietyMemberSuspended `test-gen-skip:"true"` + Society_NewMaxMembers []EventSocietyNewMaxMembers `test-gen-skip:"true"` + Society_SuspendedMemberJudgement []EventSocietySuspendedMemberJudgement `test-gen-skip:"true"` + Society_Unbid []EventSocietyUnbid `test-gen-skip:"true"` + Society_Unfounded []EventSocietyUnfounded `test-gen-skip:"true"` + Society_Unvouch []EventSocietyUnvouch `test-gen-skip:"true"` + Society_Vote []EventSocietyVote `test-gen-skip:"true"` + Society_Vouch []EventSocietyVouch `test-gen-skip:"true"` + + Staking_Bonded []EventStakingBonded `test-gen-blockchain:"polkadot"` + Staking_Chilled []EventStakingChilled `test-gen-blockchain:"polkadot"` + Staking_EraPaid []EventStakingEraPaid `test-gen-blockchain:"polkadot"` + Staking_Kicked []EventStakingKicked `test-gen-blockchain:"polkadot"` + Staking_OldSlashingReportDiscarded []EventStakingOldSlashingReportDiscarded `test-gen-blockchain:"polkadot"` + Staking_PayoutStarted []EventStakingPayoutStarted `test-gen-blockchain:"polkadot"` + Staking_Rewarded []EventStakingRewarded `test-gen-blockchain:"polkadot"` + Staking_Slashed []EventStakingSlashed `test-gen-blockchain:"polkadot"` + Staking_StakersElected []EventStakingStakersElected `test-gen-blockchain:"polkadot"` + Staking_StakingElectionFailed []EventStakingStakingElectionFailed `test-gen-blockchain:"polkadot"` + Staking_Unbonded []EventStakingUnbonded `test-gen-blockchain:"polkadot"` + Staking_Withdrawn []EventStakingWithdrawn `test-gen-blockchain:"polkadot"` + + StateTrieMigration_Migrated []EventStateTrieMigrationMigrated `test-gen-skip:"true"` + StateTrieMigration_Slashed []EventStateTrieMigrationSlashed `test-gen-skip:"true"` + StateTrieMigration_AutoMigrationFinished []EventStateTrieMigrationAutoMigrationFinished `test-gen-skip:"true"` + StateTrieMigration_Halted []EventStateTrieMigrationHalted `test-gen-skip:"true"` + + Sudo_KeyChanged []EventSudoKeyChanged `test-gen-skip:"true"` + Sudo_Sudid []EventSudoSudid `test-gen-skip:"true"` + Sudo_SudoAsDone []EventSudoAsDone `test-gen-skip:"true"` + + System_CodeUpdated []EventSystemCodeUpdated `test-gen-blockchain:"centrifuge-parachain"` + System_ExtrinsicFailed []EventSystemExtrinsicFailed `test-gen-blockchain:"centrifuge-parachain"` + System_ExtrinsicSuccess []EventSystemExtrinsicSuccess `test-gen-blockchain:"centrifuge-parachain"` + System_KilledAccount []EventSystemKilledAccount `test-gen-blockchain:"centrifuge-parachain"` + System_NewAccount []EventSystemNewAccount `test-gen-blockchain:"centrifuge-parachain"` + System_Remarked []EventSystemRemarked `test-gen-blockchain:"centrifuge-parachain"` + + TechnicalCommittee_Approved []EventTechnicalCommitteeApproved `test-gen-blockchain:"polkadot"` + TechnicalCommittee_Closed []EventTechnicalCommitteeClosed `test-gen-blockchain:"polkadot"` + TechnicalCommittee_Disapproved []EventTechnicalCommitteeDisapproved `test-gen-blockchain:"polkadot"` + TechnicalCommittee_Executed []EventTechnicalCommitteeExecuted `test-gen-blockchain:"polkadot"` + TechnicalCommittee_MemberExecuted []EventTechnicalCommitteeMemberExecuted `test-gen-blockchain:"polkadot"` + TechnicalCommittee_Proposed []EventTechnicalCommitteeProposed `test-gen-blockchain:"polkadot"` + TechnicalCommittee_Voted []EventTechnicalCommitteeVoted `test-gen-blockchain:"polkadot"` + + TechnicalMembership_Dummy []EventTechnicalMembershipDummy `test-gen-blockchain:"polkadot"` + TechnicalMembership_KeyChanged []EventTechnicalMembershipKeyChanged `test-gen-blockchain:"polkadot"` + TechnicalMembership_MemberAdded []EventTechnicalMembershipMemberAdded `test-gen-blockchain:"polkadot"` + TechnicalMembership_MemberRemoved []EventTechnicalMembershipMemberRemoved `test-gen-blockchain:"polkadot"` + TechnicalMembership_MembersReset []EventTechnicalMembershipMembersReset `test-gen-blockchain:"polkadot"` + TechnicalMembership_MembersSwapped []EventTechnicalMembershipMembersSwapped `test-gen-blockchain:"polkadot"` + + Tips_NewTip []EventTipsNewTip `test-gen-blockchain:"polkadot"` + Tips_TipClosed []EventTipsTipClosed `test-gen-blockchain:"polkadot"` + Tips_TipClosing []EventTipsTipClosing `test-gen-blockchain:"polkadot"` + Tips_TipRetracted []EventTipsTipRetracted `test-gen-blockchain:"polkadot"` + Tips_TipSlashed []EventTipsTipSlashed `test-gen-blockchain:"polkadot"` + + TransactionStorage_Stored []EventTransactionStorageStored `test-gen-skip:"true"` + TransactionStorage_Renewed []EventTransactionStorageRenewed `test-gen-skip:"true"` + TransactionStorage_ProofChecked []EventTransactionStorageProofChecked `test-gen-skip:"true"` + + TransactionPayment_TransactionFeePaid []EventTransactionPaymentTransactionFeePaid `test-gen-blockchain:"westend"` + + Treasury_Awarded []EventTreasuryAwarded `test-gen-blockchain:"altair"` + Treasury_Burnt []EventTreasuryBurnt `test-gen-blockchain:"altair"` + Treasury_Deposit []EventTreasuryDeposit `test-gen-blockchain:"altair"` + Treasury_Proposed []EventTreasuryProposed `test-gen-blockchain:"altair"` + Treasury_Rejected []EventTreasuryRejected `test-gen-blockchain:"altair"` + Treasury_Rollover []EventTreasuryRollover `test-gen-blockchain:"altair"` + Treasury_Spending []EventTreasurySpending `test-gen-blockchain:"altair"` + + Uniques_ApprovalCancelled []EventUniquesApprovalCancelled `test-gen-blockchain:"altair"` + Uniques_ApprovedTransfer []EventUniquesApprovedTransfer `test-gen-blockchain:"altair"` + Uniques_AssetStatusChanged []EventUniquesAssetStatusChanged `test-gen-blockchain:"altair"` + Uniques_AttributeCleared []EventUniquesAttributeCleared `test-gen-blockchain:"altair"` + Uniques_AttributeSet []EventUniquesAttributeSet `test-gen-blockchain:"altair"` + Uniques_Burned []EventUniquesBurned `test-gen-blockchain:"altair"` + Uniques_ClassFrozen []EventUniquesClassFrozen `test-gen-blockchain:"altair"` + Uniques_ClassMetadataCleared []EventUniquesClassMetadataCleared `test-gen-blockchain:"altair"` + Uniques_ClassMetadataSet []EventUniquesClassMetadataSet `test-gen-blockchain:"altair"` + Uniques_ClassThawed []EventUniquesClassThawed `test-gen-blockchain:"altair"` + Uniques_Created []EventUniquesCreated `test-gen-blockchain:"altair"` + Uniques_Destroyed []EventUniquesDestroyed `test-gen-blockchain:"altair"` + Uniques_ForceCreated []EventUniquesForceCreated `test-gen-blockchain:"altair"` + Uniques_Frozen []EventUniquesFrozen `test-gen-blockchain:"altair"` + Uniques_Issued []EventUniquesIssued `test-gen-blockchain:"altair"` + Uniques_MetadataCleared []EventUniquesMetadataCleared `test-gen-blockchain:"altair"` + Uniques_MetadataSet []EventUniquesMetadataSet `test-gen-blockchain:"altair"` + Uniques_OwnerChanged []EventUniquesOwnerChanged `test-gen-blockchain:"altair"` + Uniques_Redeposited []EventUniquesRedeposited `test-gen-blockchain:"altair"` + Uniques_TeamChanged []EventUniquesTeamChanged `test-gen-blockchain:"altair"` + Uniques_Thawed []EventUniquesThawed `test-gen-blockchain:"altair"` + Uniques_Transferred []EventUniquesTransferred `test-gen-blockchain:"altair"` + + Ump_InvalidFormat []EventUMPInvalidFormat `test-gen-blockchain:"polkadot"` + Ump_UnsupportedVersion []EventUMPUnsupportedVersion `test-gen-blockchain:"polkadot"` + Ump_ExecutedUpward []EventUMPExecutedUpward `test-gen-blockchain:"polkadot"` + Ump_WeightExhausted []EventUMPWeightExhausted `test-gen-blockchain:"polkadot"` + Ump_UpwardMessagesReceived []EventUMPUpwardMessagesReceived `test-gen-blockchain:"polkadot"` + Ump_OverweightEnqueued []EventUMPOverweightEnqueued `test-gen-blockchain:"polkadot"` + Ump_OverweightServiced []EventUMPOverweightServiced `test-gen-blockchain:"polkadot"` + + Utility_BatchCompleted []EventUtilityBatchCompleted `test-gen-blockchain:"centrifuge-parachain"` + Utility_BatchInterrupted []EventUtilityBatchInterrupted `test-gen-blockchain:"centrifuge-parachain"` + Utility_DispatchedAs []EventUtilityBatchInterrupted `test-gen-blockchain:"centrifuge-parachain"` + Utility_ItemCompleted []EventUtilityItemCompleted `test-gen-blockchain:"centrifuge-parachain"` + + Vesting_VestingCompleted []EventVestingVestingCompleted `test-gen-blockchain:"centrifuge-parachain"` + Vesting_VestingUpdated []EventVestingVestingUpdated `test-gen-blockchain:"centrifuge-parachain"` + + VoterList_Rebagged []EventVoterListRebagged `test-gen-blockchain:"polkadot"` + VoterList_ScoreUpdated []EventVoterListScoreUpdated `test-gen-blockchain:"polkadot"` + + Whitelist_CallWhitelisted []EventWhitelistCallWhitelisted `test-gen-skip:"true"` + Whitelist_WhitelistedCallRemoved []EventWhitelistWhitelistedCallRemoved `test-gen-skip:"true"` + Whitelist_WhitelistedCallDispatched []EventWhitelistWhitelistedCallRemoved `test-gen-skip:"true"` + + XcmPallet_Attempted []EventXcmPalletAttempted `test-gen-blockchain:"polkadot"` + XcmPallet_Sent []EventXcmPalletSent `test-gen-blockchain:"polkadot"` + XcmPallet_UnexpectedResponse []EventXcmPalletUnexpectedResponse `test-gen-blockchain:"polkadot"` + XcmPallet_ResponseReady []EventXcmPalletResponseReady `test-gen-blockchain:"polkadot"` + XcmPallet_Notified []EventXcmPalletNotified `test-gen-blockchain:"polkadot"` + XcmPallet_NotifyOverweight []EventXcmPalletNotifyOverweight `test-gen-blockchain:"polkadot"` + XcmPallet_NotifyDispatchError []EventXcmPalletNotifyDispatchError `test-gen-blockchain:"polkadot"` + XcmPallet_NotifyDecodeFailed []EventXcmPalletNotifyDecodeFailed `test-gen-blockchain:"polkadot"` + XcmPallet_InvalidResponder []EventXcmPalletInvalidResponder `test-gen-blockchain:"polkadot"` + XcmPallet_InvalidResponderVersion []EventXcmPalletInvalidResponderVersion `test-gen-blockchain:"polkadot"` + XcmPallet_ResponseTaken []EventXcmPalletResponseTaken `test-gen-blockchain:"polkadot"` + XcmPallet_AssetsTrapped []EventXcmPalletAssetsTrapped `test-gen-blockchain:"polkadot"` + XcmPallet_VersionChangeNotified []EventXcmPalletVersionChangeNotified `test-gen-blockchain:"polkadot"` + XcmPallet_SupportedVersionChanged []EventXcmPalletSupportedVersionChanged `test-gen-blockchain:"polkadot"` + XcmPallet_NotifyTargetSendFail []EventXcmPalletNotifyTargetSendFail `test-gen-blockchain:"polkadot"` + XcmPallet_NotifyTargetMigrationFail []EventXcmPalletNotifyTargetMigrationFail `test-gen-blockchain:"polkadot"` +} + +// DecodeEventRecords decodes the events records from an EventRecordRaw into a target t using the given Metadata m +// If this method returns an error like `unable to decode Phase for event #x: EOF`, it is likely that you have defined +// a custom event record with a wrong type. For example your custom event record has a field with a length prefixed +// type, such as types.Bytes, where your event in reallity contains a fixed width type, such as a types.U32. +func (e EventRecordsRaw) DecodeEventRecords(m *types.Metadata, t interface{}) error { //nolint:funlen + log.Debug(fmt.Sprintf("will decode event records from raw hex: %#x", e)) + + // ensure t is a pointer + ttyp := reflect.TypeOf(t) + if ttyp.Kind() != reflect.Ptr { + return errors.New("target must be a pointer, but is " + fmt.Sprint(ttyp)) + } + // ensure t is not a nil pointer + tval := reflect.ValueOf(t) + if tval.IsNil() { + return errors.New("target is a nil pointer") + } + val := tval.Elem() + typ := val.Type() + // ensure val can be set + if !val.CanSet() { + return fmt.Errorf("unsettable value %v", typ) + } + // ensure val points to a struct + if val.Kind() != reflect.Struct { + return fmt.Errorf("target must point to a struct, but is " + fmt.Sprint(typ)) + } + + decoder := scale.NewDecoder(bytes.NewReader(e)) + + // determine number of events + n, err := decoder.DecodeUintCompact() + if err != nil { + return err + } + + log.Debug(fmt.Sprintf("found %v events", n)) + + // iterate over events + for i := uint64(0); i < n.Uint64(); i++ { + log.Debug(fmt.Sprintf("decoding event #%v", i)) + + // decode Phase + phase := Phase{} + err := decoder.Decode(&phase) + if err != nil { + return fmt.Errorf("unable to decode Phase for event #%v: %v", i, err) + } + + // decode EventID + id := types.EventID{} + err = decoder.Decode(&id) + if err != nil { + return fmt.Errorf("unable to decode EventID for event #%v: %v", i, err) + } + + log.Debug(fmt.Sprintf("event #%v has EventID %v", i, id)) + + // ask metadata for method & event name for event + moduleName, eventName, err := m.FindEventNamesForEventID(id) + // moduleName, eventName, err := "System", "ExtrinsicSuccess", nil + if err != nil { + return fmt.Errorf("unable to find event with EventID %v in metadata for event #%v: %s", id, i, err) + } + + log.Debug(fmt.Sprintf("event #%v is in module %v with event name %v", i, moduleName, eventName)) + + // check whether name for eventID exists in t + field := val.FieldByName(fmt.Sprintf("%v_%v", moduleName, eventName)) + if !field.IsValid() { + return fmt.Errorf("unable to find field %v_%v for event #%v with EventID %v", moduleName, eventName, i, id) + } + + // create a pointer to with the correct type that will hold the decoded event + holder := reflect.New(field.Type().Elem()) + + // ensure first field is for Phase, last field is for Topics + numFields := holder.Elem().NumField() + if numFields < 2 { + return fmt.Errorf("expected event #%v with EventID %v, field %v_%v to have at least 2 fields "+ + "(for Phase and Topics), but has %v fields", i, id, moduleName, eventName, numFields) + } + phaseField := holder.Elem().FieldByIndex([]int{0}) + if phaseField.Type() != reflect.TypeOf(phase) { + return fmt.Errorf("expected the first field of event #%v with EventID %v, field %v_%v to be of type "+ + "types.Phase, but got %v", i, id, moduleName, eventName, phaseField.Type()) + } + topicsField := holder.Elem().FieldByIndex([]int{numFields - 1}) + if topicsField.Type() != reflect.TypeOf([]types.Hash{}) { + return fmt.Errorf("expected the last field of event #%v with EventID %v, field %v_%v to be of type "+ + "[]types.Hash for Topics, but got %v", i, id, moduleName, eventName, topicsField.Type()) + } + + // set the phase we decoded earlier + phaseField.Set(reflect.ValueOf(phase)) + + // set the remaining fields + for j := 1; j < numFields; j++ { + err = decoder.Decode(holder.Elem().FieldByIndex([]int{j}).Addr().Interface()) + if err != nil { + return fmt.Errorf("unable to decode field %v event #%v with EventID %v, field %v_%v: %v", j, i, id, moduleName, + eventName, err) + } + } + + // add the decoded event to the slice + field.Set(reflect.Append(field, holder.Elem())) + + log.Debug(fmt.Sprintf("decoded event #%v", i)) + } + return nil +} + +// Phase is an enum describing the current phase of the event (applying the extrinsic or finalized) +type Phase struct { + IsApplyExtrinsic bool + AsApplyExtrinsic uint32 + IsFinalization bool + IsInitialization bool +} + +func (p *Phase) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + if err != nil { + return err + } + + switch b { + case 0: + p.IsApplyExtrinsic = true + err = decoder.Decode(&p.AsApplyExtrinsic) + case 1: + p.IsFinalization = true + case 2: + p.IsInitialization = true + } + + if err != nil { + return err + } + + return nil +} + +func (p Phase) Encode(encoder scale.Encoder) error { + var err1, err2 error + + switch { + case p.IsApplyExtrinsic: + err1 = encoder.PushByte(0) + err2 = encoder.Encode(p.AsApplyExtrinsic) + case p.IsFinalization: + err1 = encoder.PushByte(1) + case p.IsInitialization: + err1 = encoder.PushByte(2) + } + + if err1 != nil { + return err1 + } + if err2 != nil { + return err2 + } + + return nil +} + +type EventID [2]byte diff --git a/contract/pkg/chainevents/events.go b/contract/pkg/chainevents/events.go new file mode 100644 index 0000000..3e897b4 --- /dev/null +++ b/contract/pkg/chainevents/events.go @@ -0,0 +1,3175 @@ +package chainevents + +import ( + "fmt" + + "github.com/centrifuge/go-substrate-rpc-client/v4/scale" + "github.com/centrifuge/go-substrate-rpc-client/v4/types" +) + +type Weight = types.U64 + +// EventClaimsClaimed is emitted when an account claims some DOTs +type EventClaimsClaimed struct { + Phase Phase + Who types.AccountID + EthereumAddress types.H160 + Amount types.U128 + Topics []types.Hash +} + +// EventBalancesEndowed is emitted when an account is created with some free balance +type EventBalancesEndowed struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventDustLost is emitted when an account is removed with a balance that is +// non-zero but below ExistentialDeposit, resulting in a loss. +type EventBalancesDustLost struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventBalancesTransfer is emitted when a transfer succeeded (from, to, value) +type EventBalancesTransfer struct { + Phase Phase + From types.AccountID + To types.AccountID + Value types.U128 + Topics []types.Hash +} + +// EventBalanceSet is emitted when a balance is set by root +type EventBalancesBalanceSet struct { + Phase Phase + Who types.AccountID + Free types.U128 + Reserved types.U128 + Topics []types.Hash +} + +// EventDeposit is emitted when an account receives some free balance +type EventBalancesDeposit struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventBalancesReserved is emitted when some balance was reserved (moved from free to reserved) +type EventBalancesReserved struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventBalancesUnreserved is emitted when some balance was unreserved (moved from reserved to free) +type EventBalancesUnreserved struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventBalancesReserveRepatriated is emitted when some balance was moved from the reserve of the first account to the +// second account. +type EventBalancesReserveRepatriated struct { + Phase Phase + From types.AccountID + To types.AccountID + Balance types.U128 + DestinationStatus types.BalanceStatus + Topics []types.Hash +} + +// EventBalancesWithdraw is emitted when some amount was withdrawn from the account (e.g. for transaction fees) +type EventBalancesWithdraw struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventBalancesSlashed is emitted when some amount was removed from the account (e.g. for misbehavior) +type EventBalancesSlashed struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventGrandpaNewAuthorities is emitted when a new authority set has been applied +type EventGrandpaNewAuthorities struct { + Phase Phase + NewAuthorities []struct { + AuthorityID types.AuthorityID + AuthorityWeight types.U64 + } + Topics []types.Hash +} + +// EventGrandpaPaused is emitted when the current authority set has been paused +type EventGrandpaPaused struct { + Phase Phase + Topics []types.Hash +} + +// EventGrandpaResumed is emitted when the current authority set has been resumed +type EventGrandpaResumed struct { + Phase Phase + Topics []types.Hash +} + +// EventHRMPOpenChannelRequested is emitted when an open HRMP channel is requested. +type EventHRMPOpenChannelRequested struct { + Phase Phase + Sender ParachainID + Recipient ParachainID + ProposedMaxCapacity types.U32 + ProposedMaxMessageSize types.U32 + Topics []types.Hash +} + +// EventHRMPOpenChannelCanceled is emitted when an HRMP channel request +// sent by the receiver was canceled by either party. +type EventHRMPOpenChannelCanceled struct { + Phase Phase + ByParachain ParachainID + ChannelID types.HRMPChannelID + Topics []types.Hash +} + +// EventHRMPOpenChannelAccepted is emitted when an open HRMP channel is accepted. +type EventHRMPOpenChannelAccepted struct { + Phase Phase + Sender ParachainID + Recipient ParachainID + Topics []types.Hash +} + +// EventHRMPChannelClosed is emitted when an HRMP channel is closed. +type EventHRMPChannelClosed struct { + Phase Phase + ByParachain ParachainID + ChannelID types.HRMPChannelID + Topics []types.Hash +} + +// EventImOnlineHeartbeatReceived is emitted when a new heartbeat was received from AuthorityId +type EventImOnlineHeartbeatReceived struct { + Phase Phase + AuthorityID types.AuthorityID + Topics []types.Hash +} + +// EventImOnlineAllGood is emitted when at the end of the session, no offence was committed +type EventImOnlineAllGood struct { + Phase Phase + Topics []types.Hash +} + +// Exposure lists the own and nominated stake of a validator +type Exposure struct { + Total types.UCompact + Own types.UCompact + Others []IndividualExposure +} + +// IndividualExposure contains the nominated stake by one specific third party +type IndividualExposure struct { + Who types.AccountID + Value types.UCompact +} + +// EventImOnlineSomeOffline is emitted when the end of the session, at least once validator was found to be offline +type EventImOnlineSomeOffline struct { + Phase Phase + IdentificationTuples []struct { + ValidatorID types.AccountID + FullIdentification Exposure + } + Topics []types.Hash +} + +// EventIndicesIndexAssigned is emitted when an index is assigned to an AccountID. +type EventIndicesIndexAssigned struct { + Phase Phase + AccountID types.AccountID + AccountIndex types.AccountIndex + Topics []types.Hash +} + +// EventIndicesIndexFreed is emitted when an index is unassigned. +type EventIndicesIndexFreed struct { + Phase Phase + AccountIndex types.AccountIndex + Topics []types.Hash +} + +// EventIndicesIndexFrozen is emitted when an index is frozen to its current account ID. +type EventIndicesIndexFrozen struct { + Phase Phase + AccountIndex types.AccountIndex + AccountID types.AccountID + Topics []types.Hash +} + +// EventLotteryLotteryStarted is emitted when a lottery has been started. +type EventLotteryLotteryStarted struct { + Phase Phase + Topics []types.Hash +} + +// EventLotteryCallsUpdated is emitted when a new set of calls has been set. +type EventLotteryCallsUpdated struct { + Phase Phase + Topics []types.Hash +} + +// EventLotteryWinner is emitted when a winner has been chosen. +type EventLotteryWinner struct { + Phase Phase + Winner types.AccountID + LotteryBalance types.U128 + Topics []types.Hash +} + +// EventLotteryTicketBought is emitted when a ticket has been bought. +type EventLotteryTicketBought struct { + Phase Phase + Who types.AccountID + CallIndex types.LotteryCallIndex + Topics []types.Hash +} + +// EventOffencesOffence is emitted when there is an offence reported of the given kind happened at the session_index +// and (kind-specific) time slot. This event is not deposited for duplicate slashes +type EventOffencesOffence struct { + Phase Phase + Kind types.Bytes16 + OpaqueTimeSlot types.Bytes + Topics []types.Hash +} + +// EventParasCurrentCodeUpdated is emitted when the current code has been updated for a Para. +type EventParasCurrentCodeUpdated struct { + Phase Phase + ParachainID ParachainID + Topics []types.Hash +} + +// EventParasCurrentHeadUpdated is emitted when the current head has been updated for a Para. +type EventParasCurrentHeadUpdated struct { + Phase Phase + ParachainID ParachainID + Topics []types.Hash +} + +// EventParasCodeUpgradeScheduled is emitted when a code upgrade has been scheduled for a Para. +type EventParasCodeUpgradeScheduled struct { + Phase Phase + ParachainID ParachainID + Topics []types.Hash +} + +// EventParasNewHeadNoted is emitted when a new head has been noted for a Para. +type EventParasNewHeadNoted struct { + Phase Phase + ParachainID ParachainID + Topics []types.Hash +} + +// EventParasActionQueued is emitted when a para has been queued to execute pending actions. +type EventParasActionQueued struct { + Phase Phase + ParachainID ParachainID + SessionIndex types.U32 + Topics []types.Hash +} + +// EventParasPvfCheckStarted is emitted when the given para either initiated or subscribed to a PVF +// check for the given validation code. +type EventParasPvfCheckStarted struct { + Phase Phase + CodeHash types.Hash + ParachainID ParachainID + Topics []types.Hash +} + +// EventParasPvfCheckAccepted is emitted when the given validation code was accepted by the PVF pre-checking vote. +type EventParasPvfCheckAccepted struct { + Phase Phase + CodeHash types.Hash + ParachainID ParachainID + Topics []types.Hash +} + +// EventParasPvfCheckRejected is emitted when the given validation code was rejected by the PVF pre-checking vote. +type EventParasPvfCheckRejected struct { + Phase Phase + CodeHash types.Hash + ParachainID ParachainID + Topics []types.Hash +} + +// EventParasDisputesDisputeInitiated is emitted when a dispute has been initiated. +type EventParasDisputesDisputeInitiated struct { + Phase Phase + CandidateHash types.Hash + DisputeLocation types.DisputeLocation + Topics []types.Hash +} + +// EventParasDisputesDisputeConcluded is emitted when a dispute has concluded for or against a candidate. +type EventParasDisputesDisputeConcluded struct { + Phase Phase + CandidateHash types.Hash + DisputeLocation types.DisputeResult + Topics []types.Hash +} + +// EventParasDisputesDisputeTimedOut is emitted when a dispute has timed out due to insufficient participation. +type EventParasDisputesDisputeTimedOut struct { + Phase Phase + CandidateHash types.Hash + Topics []types.Hash +} + +// EventParasDisputesRevert is emitted when a dispute has concluded with supermajority against a candidate. +// Block authors should no longer build on top of this head and should +// instead revert the block at the given height. This should be the +// number of the child of the last known valid block in the chain. +type EventParasDisputesRevert struct { + Phase Phase + BlockNumber types.U32 + Topics []types.Hash +} + +type HeadData []types.U8 + +type CoreIndex types.U32 + +type GroupIndex types.U32 + +// EventParaInclusionCandidateBacked is emitted when a candidate was backed. +type EventParaInclusionCandidateBacked struct { + Phase Phase + CandidateReceipt types.CandidateReceipt + HeadData HeadData + CoreIndex CoreIndex + GroupIndex GroupIndex + Topics []types.Hash +} + +// EventParaInclusionCandidateIncluded is emitted when a candidate was included. +type EventParaInclusionCandidateIncluded struct { + Phase Phase + CandidateReceipt types.CandidateReceipt + HeadData HeadData + CoreIndex CoreIndex + GroupIndex GroupIndex + Topics []types.Hash +} + +// EventParaInclusionCandidateTimedOut is emitted when a candidate timed out. +type EventParaInclusionCandidateTimedOut struct { + Phase Phase + CandidateReceipt types.CandidateReceipt + HeadData HeadData + CoreIndex CoreIndex + Topics []types.Hash +} + +// EventParachainSystemValidationFunctionStored is emitted when the validation function has been scheduled to apply. +type EventParachainSystemValidationFunctionStored struct { + Phase Phase + Topics []types.Hash +} + +// EventParachainSystemValidationFunctionApplied is emitted when the validation function was applied +// as of the contained relay chain block number. +type EventParachainSystemValidationFunctionApplied struct { + Phase Phase + RelayChainBlockNumber types.U32 + Topics []types.Hash +} + +// EventParachainSystemValidationFunctionDiscarded is emitted when the relay-chain aborted the upgrade process. +type EventParachainSystemValidationFunctionDiscarded struct { + Phase Phase + Topics []types.Hash +} + +// EventParachainSystemUpgradeAuthorized is emitted when an upgrade has been authorized. +type EventParachainSystemUpgradeAuthorized struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +// EventParachainSystemDownwardMessagesReceived is emitted when some downward messages +// have been received and will be processed. +type EventParachainSystemDownwardMessagesReceived struct { + Phase Phase + Count types.U32 + Topics []types.Hash +} + +// EventParachainSystemDownwardMessagesProcessed is emitted when downward messages +// were processed using the given weight. +type EventParachainSystemDownwardMessagesProcessed struct { + Phase Phase + Weight Weight + ResultMqcHead types.Hash + Topics []types.Hash +} + +// EventSessionNewSession is emitted when a new session has happened. Note that the argument is the session index, +// not the block number as the type might suggest +type EventSessionNewSession struct { + Phase Phase + SessionIndex types.U32 + Topics []types.Hash +} + +// EventSlotsNewLeasePeriod is emitted when a new `[lease_period]` is beginning. +type EventSlotsNewLeasePeriod struct { + Phase Phase + LeasePeriod types.U32 + Topics []types.Hash +} + +type ParachainID types.U32 + +// EventSlotsLeased is emitted when a para has won the right to a continuous set of lease periods as a parachain. +// First balance is any extra amount reserved on top of the para's existing deposit. +// Second balance is the total amount reserved. +type EventSlotsLeased struct { + Phase Phase + ParachainID ParachainID + Leaser types.AccountID + PeriodBegin types.U32 + PeriodCount types.U32 + ExtraReserved types.U128 + TotalAmount types.U128 + Topics []types.Hash +} + +// EventStakingEraPaid is emitted when the era payout has been set; +type EventStakingEraPaid struct { + Phase Phase + EraIndex types.U32 + ValidatorPayout types.U128 + Remainder types.U128 + Topics []types.Hash +} + +// EventStakingRewarded is emitted when the staker has been rewarded by this amount. +type EventStakingRewarded struct { + Phase Phase + Stash types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventStakingSlashed is emitted when one validator (and its nominators) has been slashed by the given amount +type EventStakingSlashed struct { + Phase Phase + AccountID types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventStakingOldSlashingReportDiscarded is emitted when an old slashing report from a prior era was discarded because +// it could not be processed +type EventStakingOldSlashingReportDiscarded struct { + Phase Phase + SessionIndex types.U32 + Topics []types.Hash +} + +// EventStakingStakersElected is emitted when a new set of stakers was elected +type EventStakingStakersElected struct { + Phase Phase + Topics []types.Hash +} + +// EventStakingStakingElectionFailed is emitted when the election failed. No new era is planned. +type EventStakingStakingElectionFailed struct { + Phase Phase + Topics []types.Hash +} + +// EventStakingSolutionStored is emitted when a new solution for the upcoming election has been stored +type EventStakingSolutionStored struct { + Phase Phase + Compute types.ElectionCompute + Topics []types.Hash +} + +// EventStakingBonded is emitted when an account has bonded this amount +type EventStakingBonded struct { + Phase Phase + Stash types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventStakingChilled is emitted when an account has stopped participating as either a validator or nominator +type EventStakingChilled struct { + Phase Phase + Stash types.AccountID + Topics []types.Hash +} + +// EventStakingKicked is emitted when a nominator has been kicked from a validator. +type EventStakingKicked struct { + Phase Phase + Nominator types.AccountID + Stash types.AccountID + Topics []types.Hash +} + +// EventStakingPayoutStarted is emitted when the stakers' rewards are getting paid +type EventStakingPayoutStarted struct { + Phase Phase + EraIndex types.U32 + Stash types.AccountID + Topics []types.Hash +} + +// EventStakingUnbonded is emitted when an account has unbonded this amount +type EventStakingUnbonded struct { + Phase Phase + Stash types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventStakingWithdrawn is emitted when an account has called `withdraw_unbonded` and removed unbonding chunks +// worth `Balance` from the unlocking queue. +type EventStakingWithdrawn struct { + Phase Phase + Stash types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventStateTrieMigrationMigrated is emitted when the given number of `(top, child)` keys were migrated respectively, +// with the given `compute`. +type EventStateTrieMigrationMigrated struct { + Phase Phase + Top types.U32 + Child types.U32 + Compute types.MigrationCompute + Topics []types.Hash +} + +// EventStateTrieMigrationSlashed is emitted when some account got slashed by the given amount. +type EventStateTrieMigrationSlashed struct { + Phase Phase + Who types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventStateTrieMigrationAutoMigrationFinished is emitted when the auto migration task has finished. +type EventStateTrieMigrationAutoMigrationFinished struct { + Phase Phase + Topics []types.Hash +} + +// EventStateTrieMigrationHalted is emitted when the migration got halted. +type EventStateTrieMigrationHalted struct { + Phase Phase + Topics []types.Hash +} + +// EventSystemExtrinsicSuccessV8 is emitted when an extrinsic completed successfully +// +// Deprecated: EventSystemExtrinsicSuccessV8 exists to allow users to simply implement their own EventRecords struct if +// they are on metadata version 8 or below. Use EventSystemExtrinsicSuccess otherwise +type EventSystemExtrinsicSuccessV8 struct { + Phase Phase + Topics []types.Hash +} + +// EventSystemExtrinsicSuccess is emitted when an extrinsic completed successfully +type EventSystemExtrinsicSuccess struct { + Phase Phase + DispatchInfo DispatchInfo + Topics []types.Hash +} + +type Pays struct { + IsYes bool + IsNo bool +} + +func (p *Pays) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + if err != nil { + return err + } + + switch b { + case 0: + p.IsYes = true + case 1: + p.IsNo = true + } + + return nil +} + +func (p Pays) Encode(encoder scale.Encoder) error { + var err error + if p.IsYes { + err = encoder.PushByte(0) + } else if p.IsNo { + err = encoder.PushByte(1) + } + return err +} + +// DispatchInfo contains a bundle of static information collected from the `#[weight = $x]` attributes. +type DispatchInfo struct { + // Weight of this transaction + Weight Weight + // Class of this transaction + Class DispatchClass + // PaysFee indicates whether this transaction pays fees + PaysFee Pays +} + +func (d *DispatchInfo) Decode(decoder scale.Decoder) error { + if err := decoder.Decode(&d.Weight); err != nil { + return err + } + + if err := decoder.Decode(&d.Class); err != nil { + return err + } + + return decoder.Decode(&d.PaysFee) +} + +// DispatchClass is a generalized group of dispatch types. This is only distinguishing normal, user-triggered +// transactions (`Normal`) and anything beyond which serves a higher purpose to the system (`Operational`). +type DispatchClass struct { + // A normal dispatch + IsNormal bool + // An operational dispatch + IsOperational bool + // A mandatory dispatch + IsMandatory bool +} + +func (d *DispatchClass) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + if err != nil { + return err + } + + switch b { + case 0: + d.IsNormal = true + case 1: + d.IsOperational = true + case 2: + d.IsMandatory = true + } + + return nil +} + +func (d DispatchClass) Encode(encoder scale.Encoder) error { + switch { + case d.IsNormal: + return encoder.PushByte(0) + case d.IsOperational: + return encoder.PushByte(1) + case d.IsMandatory: + return encoder.PushByte(2) + } + + return nil +} + +// EventSystemExtrinsicFailedV8 is emitted when an extrinsic failed +// +// Deprecated: EventSystemExtrinsicFailedV8 exists to allow users to simply implement their own EventRecords struct if +// they are on metadata version 8 or below. Use EventSystemExtrinsicFailed otherwise +type EventSystemExtrinsicFailedV8 struct { + Phase Phase + DispatchError types.DispatchError + Topics []types.Hash +} + +// EventSystemExtrinsicFailed is emitted when an extrinsic failed +type EventSystemExtrinsicFailed struct { + Phase Phase + DispatchError types.DispatchError + DispatchInfo DispatchInfo + Topics []types.Hash +} + +// EventSystemCodeUpdated is emitted when the runtime code (`:code`) is updated +type EventSystemCodeUpdated struct { + Phase Phase + Topics []types.Hash +} + +// EventSystemNewAccount is emitted when a new account was created +type EventSystemNewAccount struct { + Phase Phase + Who types.AccountID + Topics []types.Hash +} + +// EventSystemRemarked is emitted when an on-chain remark happened +type EventSystemRemarked struct { + Phase Phase + Who types.AccountID + Hash types.Hash + Topics []types.Hash +} + +// EventSystemKilledAccount is emitted when an account is reaped +type EventSystemKilledAccount struct { + Phase Phase + Who types.AccountID + Topics []types.Hash +} + +// EventAssetIssued is emitted when an asset is issued. +type EventAssetIssued struct { + Phase Phase + AssetID types.U32 + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventAssetCreated is emitted when an asset is created. +type EventAssetCreated struct { + Phase Phase + AssetID types.U32 + Creator types.AccountID + Owner types.AccountID + Topics []types.Hash +} + +// EventAssetTransferred is emitted when an asset is transferred. +type EventAssetTransferred struct { + Phase Phase + AssetID types.U32 + To types.AccountID + From types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventAssetBurned is emitted when an asset is destroyed. +type EventAssetBurned struct { + Phase Phase + AssetID types.U32 + Owner types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventAssetTeamChanged is emitted when the management team changed. +type EventAssetTeamChanged struct { + Phase Phase + AssetID types.U32 + Issuer types.AccountID + Admin types.AccountID + Freezer types.AccountID + Topics []types.Hash +} + +// EventAssetOwnerChanged is emitted when the owner changed. +type EventAssetOwnerChanged struct { + Phase Phase + AssetID types.U32 + Owner types.AccountID + Topics []types.Hash +} + +// EventAssetFrozen is emitted when some account `who` was frozen. +type EventAssetFrozen struct { + Phase Phase + AssetID types.U32 + Who types.AccountID + Topics []types.Hash +} + +// EventAssetThawed is emitted when some account `who` was thawed. +type EventAssetThawed struct { + Phase Phase + AssetID types.U32 + Who types.AccountID + Topics []types.Hash +} + +// EventAssetAssetFrozen is emitted when some asset `asset_id` was frozen. +type EventAssetAssetFrozen struct { + Phase Phase + AssetID types.U32 + Topics []types.Hash +} + +// EventAssetAssetThawed is emitted when some asset `asset_id` was thawed. +type EventAssetAssetThawed struct { + Phase Phase + AssetID types.U32 + Topics []types.Hash +} + +// EventAssetDestroyed is emitted when an asset class is destroyed. +type EventAssetDestroyed struct { + Phase Phase + AssetID types.U32 + Topics []types.Hash +} + +// EventAssetForceCreated is emitted when some asset class was force-created. +type EventAssetForceCreated struct { + Phase Phase + AssetID types.U32 + Owner types.AccountID + Topics []types.Hash +} + +type MetadataSetName []byte +type MetadataSetSymbol []byte + +// EventAssetMetadataSet is emitted when new metadata has been set for an asset. +type EventAssetMetadataSet struct { + Phase Phase + AssetID types.U32 + Name MetadataSetName + Symbol MetadataSetSymbol + Decimals types.U8 + IsFrozen bool + Topics []types.Hash +} + +// EventAssetMetadataCleared is emitted when metadata has been cleared for an asset. +type EventAssetMetadataCleared struct { + Phase Phase + AssetID types.U32 + Topics []types.Hash +} + +// EventAssetApprovedTransfer is emitted when (additional) funds have been approved +// for transfer to a destination account. +type EventAssetApprovedTransfer struct { + Phase Phase + AssetID types.U32 + Source types.AccountID + Delegate types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventAssetApprovalCancelled is emitted when an approval for account `delegate` was cancelled by `owner`. +type EventAssetApprovalCancelled struct { + Phase Phase + AssetID types.U32 + Owner types.AccountID + Delegate types.AccountID + Topics []types.Hash +} + +// EventAssetTransferredApproved is emitted when an `amount` was transferred in its +// entirety from `owner` to `destination` by the approved `delegate`. +type EventAssetTransferredApproved struct { + Phase Phase + AssetID types.U32 + Owner types.AccountID + Delegate types.AccountID + Destination types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventAssetAssetStatusChanged is emitted when an asset has had its attributes changed by the `Force` origin. +type EventAssetAssetStatusChanged struct { + Phase Phase + AssetID types.U32 + Topics []types.Hash +} + +// EventAuctionsAuctionStarted is emitted when an auction started. Provides its index and the block number +// where it will begin to close and the first lease period of the quadruplet that is auctioned. +type EventAuctionsAuctionStarted struct { + Phase Phase + AuctionIndex types.U32 + LeasePeriod types.U32 + Ending types.U32 + Topics []types.Hash +} + +// EventAuctionsAuctionClosed is emitted when an auction ended. All funds become unreserved. +type EventAuctionsAuctionClosed struct { + Phase Phase + AuctionIndex types.U32 + Topics []types.Hash +} + +// EventAuctionsReserved is emitted when funds were reserved for a winning bid. +// First balance is the extra amount reserved. Second is the total. +type EventAuctionsReserved struct { + Phase Phase + Bidder types.AccountID + ExtraReserved types.U128 + TotalAmount types.U128 + Topics []types.Hash +} + +// EventAuctionsUnreserved is emitted when funds were unreserved since bidder is no longer active. +type EventAuctionsUnreserved struct { + Phase Phase + Bidder types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventAuctionsReserveConfiscated is emitted when someone attempted to lease the same slot twice for a parachain. +// The amount is held in reserve but no parachain slot has been leased. +type EventAuctionsReserveConfiscated struct { + Phase Phase + ParachainID ParachainID + Leaser types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventAuctionsBidAccepted is emitted when a new bid has been accepted as the current winner. +type EventAuctionsBidAccepted struct { + Phase Phase + Who types.AccountID + ParachainID ParachainID + Amount types.U128 + FirstSlot types.U32 + LastSlot types.U32 + Topics []types.Hash +} + +// EventAuctionsWinningOffset is emitted when the winning offset was chosen for an auction. +// This will map into the `Winning` storage map. +type EventAuctionsWinningOffset struct { + Phase Phase + AuctionIndex types.U32 + BlockNumber types.U32 + Topics []types.Hash +} + +// EventBagsListRebagged is emitted when an account was moved from one bag to another. +type EventBagsListRebagged struct { + Phase Phase + Who types.AccountID + From types.U64 + To types.U64 + Topics []types.Hash +} + +// EventDemocracyProposed is emitted when a motion has been proposed by a public account. +type EventDemocracyProposed struct { + Phase Phase + ProposalIndex types.U32 + Balance types.U128 + Topics []types.Hash +} + +// EventDemocracyTabled is emitted when a public proposal has been tabled for referendum vote. +type EventDemocracyTabled struct { + Phase Phase + ProposalIndex types.U32 + Balance types.U128 + Accounts []types.AccountID + Topics []types.Hash +} + +// EventDemocracyExternalTabled is emitted when an external proposal has been tabled. +type EventDemocracyExternalTabled struct { + Phase Phase + Topics []types.Hash +} + +// VoteThreshold is a means of determining if a vote is past pass threshold. +type VoteThreshold byte + +const ( + // SuperMajorityApprove require super majority of approvals is needed to pass this vote. + SuperMajorityApprove VoteThreshold = 0 + // SuperMajorityAgainst require super majority of rejects is needed to fail this vote. + SuperMajorityAgainst VoteThreshold = 1 + // SimpleMajority require simple majority of approvals is needed to pass this vote. + SimpleMajority VoteThreshold = 2 +) + +func (v *VoteThreshold) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + vb := VoteThreshold(b) + switch vb { + case SuperMajorityApprove, SuperMajorityAgainst, SimpleMajority: + *v = vb + default: + return fmt.Errorf("unknown VoteThreshold enum: %v", vb) + } + return err +} + +func (v VoteThreshold) Encode(encoder scale.Encoder) error { + return encoder.PushByte(byte(v)) +} + +type DemocracyConviction byte + +const ( + // None 0.1x votes, unlocked + None = 0 + // Locked1x votes, locked for an enactment period following a successful vote. + Locked1x = 1 + // Locked2x votes, locked for 2x enactment periods following a successful vote. + Locked2x = 2 + // Locked3x votes, locked for 4x... + Locked3x = 3 + // Locked4x votes, locked for 8x... + Locked4x = 4 + // Locked5x votes, locked for 16x... + Locked5x = 5 + // Locked6x votes, locked for 32x... + Locked6x = 6 +) + +func (dc *DemocracyConviction) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + vb := DemocracyConviction(b) + switch vb { + case None, Locked1x, Locked2x, Locked3x, Locked4x, Locked5x, Locked6x: + *dc = vb + default: + return fmt.Errorf("unknown DemocracyConviction enum: %v", vb) + } + return err +} + +func (dc DemocracyConviction) Encode(encoder scale.Encoder) error { + return encoder.PushByte(byte(dc)) +} + +type DemocracyVote struct { + Aye bool + Conviction DemocracyConviction +} + +const ( + aye uint8 = 1 << 7 +) + +//nolint:lll +func (d *DemocracyVote) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + + if err != nil { + return err + } + + // As per: + // https://github.com/paritytech/substrate/blob/6a946fc36d68b89599d7ca1ab03803d10c78468c/frame/democracy/src/vote.rs#L44 + + d.Aye = (b & aye) == aye + d.Conviction = DemocracyConviction(b & (aye - 1)) + + return nil +} + +//nolint:lll +func (d DemocracyVote) Encode(encoder scale.Encoder) error { + // As per: + // https://github.com/paritytech/substrate/blob/6a946fc36d68b89599d7ca1ab03803d10c78468c/frame/democracy/src/vote.rs#L37 + + var val uint8 + + if d.Aye { + val = aye + } + + return encoder.PushByte(uint8(d.Conviction) | val) +} + +type VoteAccountVoteAsStandard struct { + Vote DemocracyVote + Balance types.U128 +} + +func (v *VoteAccountVoteAsStandard) Decode(decoder scale.Decoder) error { + if err := decoder.Decode(&v.Vote); err != nil { + return err + } + + return decoder.Decode(&v.Balance) +} + +func (v VoteAccountVoteAsStandard) Encode(encoder scale.Encoder) error { + if err := encoder.Encode(v.Vote); err != nil { + return err + } + + return encoder.Encode(v.Balance) +} + +type VoteAccountVoteAsSplit struct { + Aye types.U128 + Nay types.U128 +} + +type VoteAccountVote struct { + IsStandard bool + AsStandard VoteAccountVoteAsStandard + IsSplit bool + AsSplit VoteAccountVoteAsSplit +} + +func (vv *VoteAccountVote) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + + if err != nil { + return err + } + + switch b { + case 0: + vv.IsStandard = true + + return decoder.Decode(&vv.AsStandard) + case 1: + vv.IsSplit = true + + return decoder.Decode(&vv.AsSplit) + } + + return nil +} + +func (vv VoteAccountVote) Encode(encoder scale.Encoder) error { + switch { + case vv.IsStandard: + if err := encoder.PushByte(0); err != nil { + return err + } + + return encoder.Encode(vv.AsStandard) + case vv.IsSplit: + if err := encoder.PushByte(1); err != nil { + return err + } + + return encoder.Encode(vv.AsSplit) + } + + return nil +} + +// EventDemocracyStarted is emitted when a referendum has begun. +type EventDemocracyStarted struct { + Phase Phase + ReferendumIndex types.U32 + VoteThreshold VoteThreshold + Topics []types.Hash +} + +// EventDemocracyPassed is emitted when a proposal has been approved by referendum. +type EventDemocracyPassed struct { + Phase Phase + ReferendumIndex types.U32 + Topics []types.Hash +} + +// EventDemocracyNotPassed is emitted when a proposal has been rejected by referendum. +type EventDemocracyNotPassed struct { + Phase Phase + ReferendumIndex types.U32 + Topics []types.Hash +} + +// EventDemocracyCancelled is emitted when a referendum has been cancelled. +type EventDemocracyCancelled struct { + Phase Phase + ReferendumIndex types.U32 + Topics []types.Hash +} + +// EventDemocracyExecuted is emitted when a proposal has been enacted. +type EventDemocracyExecuted struct { + Phase Phase + ReferendumIndex types.U32 + Result DispatchResult + Topics []types.Hash +} + +// EventDemocracyDelegated is emitted when an account has delegated their vote to another account. +type EventDemocracyDelegated struct { + Phase Phase + Who types.AccountID + Target types.AccountID + Topics []types.Hash +} + +// EventDemocracyUndelegated is emitted when an account has cancelled a previous delegation operation. +type EventDemocracyUndelegated struct { + Phase Phase + Target types.AccountID + Topics []types.Hash +} + +// EventDemocracyVetoed is emitted when an external proposal has been vetoed. +type EventDemocracyVetoed struct { + Phase Phase + Who types.AccountID + Hash types.Hash + BlockNumber types.U32 + Topics []types.Hash +} + +// EventDemocracyVoted is emitted when an account has voted in a referendum. +type EventDemocracyVoted struct { + Phase Phase + Who types.AccountID + ReferendumIndex types.U32 + Vote VoteAccountVote + Topics []types.Hash +} + +// EventElectionProviderMultiPhaseSolutionStored is emitted when a solution was stored with the given compute. +// +// If the solution is signed, this means that it hasn't yet been processed. If the +// solution is unsigned, this means that it has also been processed. +// +// The `bool` is `true` when a previous solution was ejected to make room for this one. +type EventElectionProviderMultiPhaseSolutionStored struct { + Phase Phase + ElectionCompute types.ElectionCompute + PrevEjected bool + Topics []types.Hash +} + +// EventElectionProviderMultiPhaseElectionFinalized is emitted when the election has been finalized, +// with `Some` of the given computation, or else if the election failed, `None`. +type EventElectionProviderMultiPhaseElectionFinalized struct { + Phase Phase + ElectionCompute types.OptionElectionCompute + Topics []types.Hash +} + +// EventElectionProviderMultiPhaseRewarded is emitted when an account has been rewarded for their +// signed submission being finalized. +type EventElectionProviderMultiPhaseRewarded struct { + Phase Phase + Account types.AccountID + Value types.U128 + Topics []types.Hash +} + +// EventElectionProviderMultiPhaseSlashed is emitted when an account has been slashed for +// submitting an invalid signed submission. +type EventElectionProviderMultiPhaseSlashed struct { + Phase Phase + Account types.AccountID + Value types.U128 + Topics []types.Hash +} + +// EventElectionProviderMultiPhaseSignedPhaseStarted is emitted when the signed phase of the given round has started. +type EventElectionProviderMultiPhaseSignedPhaseStarted struct { + Phase Phase + Round types.U32 + Topics []types.Hash +} + +// EventElectionProviderMultiPhaseUnsignedPhaseStarted is emitted when the unsigned phase of +// the given round has started. +type EventElectionProviderMultiPhaseUnsignedPhaseStarted struct { + Phase Phase + Round types.U32 + Topics []types.Hash +} + +// EventDemocracyPreimageNoted is emitted when a proposal's preimage was noted, and the deposit taken. +type EventDemocracyPreimageNoted struct { + Phase Phase + Hash types.Hash + AccountID types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventDemocracyPreimageUsed is emitted when a proposal preimage was removed and used (the deposit was returned). +type EventDemocracyPreimageUsed struct { + Phase Phase + Hash types.Hash + AccountID types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventDemocracyPreimageInvalid is emitted when a proposal could not be executed because its preimage was invalid. +type EventDemocracyPreimageInvalid struct { + Phase Phase + Hash types.Hash + ReferendumIndex types.U32 + Topics []types.Hash +} + +// EventDemocracyPreimageMissing is emitted when a proposal could not be executed because its preimage was missing. +type EventDemocracyPreimageMissing struct { + Phase Phase + Hash types.Hash + ReferendumIndex types.U32 + Topics []types.Hash +} + +// EventDemocracyPreimageReaped is emitted when a registered preimage was removed +// and the deposit collected by the reaper (last item). +type EventDemocracyPreimageReaped struct { + Phase Phase + Hash types.Hash + Provider types.AccountID + Balance types.U128 + Who types.AccountID + Topics []types.Hash +} + +// EventDemocracySeconded is emitted when an account has seconded a proposal. +type EventDemocracySeconded struct { + Phase Phase + AccountID types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventDemocracyBlacklisted is emitted when A proposal has been blacklisted permanently +type EventDemocracyBlacklisted struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +// EventCouncilProposed is emitted when a motion (given hash) has been proposed (by given account) +// with a threshold (given `MemberCount`). +type EventCouncilProposed struct { + Phase Phase + Who types.AccountID + ProposalIndex types.U32 + Proposal types.Hash + MemberCount types.U32 + Topics []types.Hash +} + +// EventCollectiveVote is emitted when a motion (given hash) has been voted on by given account, leaving +// a tally (yes votes and no votes given respectively as `MemberCount`). +type EventCouncilVoted struct { + Phase Phase + Who types.AccountID + Proposal types.Hash + Approve bool + YesCount types.U32 + NoCount types.U32 + Topics []types.Hash +} + +// EventCrowdloanCreated is emitted when a new crowdloaning campaign is created. +type EventCrowdloanCreated struct { + Phase Phase + FundIndex types.U32 + Topics []types.Hash +} + +// EventCrowdloanContributed is emitted when `who` contributed to a crowd sale. +type EventCrowdloanContributed struct { + Phase Phase + Who types.AccountID + FundIndex types.U32 + Amount types.U128 + Topics []types.Hash +} + +// EventCrowdloanWithdrew is emitted when the full balance of a contributor was withdrawn. +type EventCrowdloanWithdrew struct { + Phase Phase + Who types.AccountID + FundIndex types.U32 + Amount types.U128 + Topics []types.Hash +} + +// EventCrowdloanPartiallyRefunded is emitted when the loans in a fund have been partially dissolved, i.e. +// there are some left over child keys that still need to be killed. +type EventCrowdloanPartiallyRefunded struct { + Phase Phase + FundIndex types.U32 + Topics []types.Hash +} + +// EventCrowdloanAllRefunded is emitted when all loans in a fund have been refunded. +type EventCrowdloanAllRefunded struct { + Phase Phase + FundIndex types.U32 + Topics []types.Hash +} + +// EventCrowdloanDissolved is emitted when the fund is dissolved. +type EventCrowdloanDissolved struct { + Phase Phase + FundIndex types.U32 + Topics []types.Hash +} + +// EventCrowdloanHandleBidResult is emitted when trying to submit a new bid to the Slots pallet. +type EventCrowdloanHandleBidResult struct { + Phase Phase + FundIndex types.U32 + DispatchResult DispatchResult + Topics []types.Hash +} + +// EventCrowdloanEdited is emitted when the configuration to a crowdloan has been edited. +type EventCrowdloanEdited struct { + Phase Phase + FundIndex types.U32 + Topics []types.Hash +} + +type CrowloadMemo []byte + +// EventCrowdloanMemoUpdated is emitted when a memo has been updated. +type EventCrowdloanMemoUpdated struct { + Phase Phase + Who types.AccountID + FundIndex types.U32 + Memo CrowloadMemo + Topics []types.Hash +} + +// EventCrowdloanAddedToNewRaise is emitted when a parachain has been moved to `NewRaise`. +type EventCrowdloanAddedToNewRaise struct { + Phase Phase + FundIndex types.U32 + Topics []types.Hash +} + +// EventCouncilAptypes.proved is emitted when a motion was approved by the required threshold. +type EventCouncilApproved struct { + Phase Phase + Proposal types.Hash + Topics []types.Hash +} + +// EventCouncilDisapproved is emitted when a motion was not approved by the required threshold. +type EventCouncilDisapproved struct { + Phase Phase + Proposal types.Hash + Topics []types.Hash +} + +// EventCouncilExecuted is emitted when a motion was executed; `result` is true if returned without error. +type EventCouncilExecuted struct { + Phase Phase + Proposal types.Hash + Result DispatchResult + Topics []types.Hash +} + +// EventCouncilMemberExecuted is emitted when a single member did some action; +// `result` is true if returned without error. +type EventCouncilMemberExecuted struct { + Phase Phase + Proposal types.Hash + Result DispatchResult + Topics []types.Hash +} + +// EventCouncilClosed is emitted when a proposal was closed after its duration was up. +type EventCouncilClosed struct { + Phase Phase + Proposal types.Hash + YesCount types.U32 + NoCount types.U32 + Topics []types.Hash +} + +// EventTechnicalCommitteeProposed is emitted when a motion (given hash) has been proposed (by given account) +// with a threshold (given, `MemberCount`) +type EventTechnicalCommitteeProposed struct { + Phase Phase + Account types.AccountID + ProposalIndex types.U32 + Proposal types.Hash + Threshold types.U32 + Topics []types.Hash +} + +// EventTechnicalCommitteeVoted is emitted when a motion (given hash) has been voted on by given account, leaving, +// a tally (yes votes and no votes given respectively as `MemberCount`). +type EventTechnicalCommitteeVoted struct { + Phase Phase + Account types.AccountID + Proposal types.Hash + Voted bool + YesCount types.U32 + NoCount types.U32 + Topics []types.Hash +} + +// EventTechnicalCommitteeApproved is emitted when a motion was approved by the required threshold. +type EventTechnicalCommitteeApproved struct { + Phase Phase + Proposal types.Hash + Topics []types.Hash +} + +// EventTechnicalCommitteeDisapproved is emitted when a motion was not approved by the required threshold. +type EventTechnicalCommitteeDisapproved struct { + Phase Phase + Proposal types.Hash + Topics []types.Hash +} + +// EventTechnicalCommitteeExecuted is emitted when a motion was executed; +// result will be `Ok` if it returned without error. +type EventTechnicalCommitteeExecuted struct { + Phase Phase + Proposal types.Hash + Result DispatchResult + Topics []types.Hash +} + +// EventTechnicalCommitteeMemberExecuted is emitted when a single member did some action; +// result will be `Ok` if it returned without error +type EventTechnicalCommitteeMemberExecuted struct { + Phase Phase + Proposal types.Hash + Result DispatchResult + Topics []types.Hash +} + +// EventTechnicalCommitteeClosed is emitted when A proposal was closed because its threshold was reached +// or after its duration was up +type EventTechnicalCommitteeClosed struct { + Phase Phase + Proposal types.Hash + YesCount types.U32 + NoCount types.U32 + Topics []types.Hash +} + +// EventTechnicalMembershipMemberAdded is emitted when the given member was added; see the transaction for who +type EventTechnicalMembershipMemberAdded struct { + Phase Phase + Topics []types.Hash +} + +// EventTechnicalMembershipMemberRemoved is emitted when the given member was removed; see the transaction for who +type EventTechnicalMembershipMemberRemoved struct { + Phase Phase + Topics []types.Hash +} + +// EventTechnicalMembershipMembersSwapped is emitted when two members were swapped;; see the transaction for who +type EventTechnicalMembershipMembersSwapped struct { + Phase Phase + Topics []types.Hash +} + +// EventTechnicalMembershipMembersReset is emitted when the membership was reset; +// see the transaction for who the new set is. +type EventTechnicalMembershipMembersReset struct { + Phase Phase + Topics []types.Hash +} + +// EventTechnicalMembershipKeyChanged is emitted when one of the members' keys changed. +type EventTechnicalMembershipKeyChanged struct { + Phase Phase + Topics []types.Hash +} + +// EventTechnicalMembershipKeyChanged is emitted when - phantom member, never used. +type EventTechnicalMembershipDummy struct { + Phase Phase + Topics []types.Hash +} + +// EventElectionsNewTerm is emitted when a new term with new members. +// This indicates that enough candidates existed, not that enough have has been elected. +// The inner value must be examined for this purpose. +type EventElectionsNewTerm struct { + Phase Phase + NewMembers []struct { + Member types.AccountID + Balance types.U128 + } + Topics []types.Hash +} + +// EventElectionsCandidateSlashed is emitted when a candidate was slashed by amount due to failing to obtain a seat +// as member or runner-up. Note that old members and runners-up are also candidates. +type EventElectionsCandidateSlashed struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventElectionsEmptyTerm is emitted when No (or not enough) candidates existed for this round. +type EventElectionsEmptyTerm struct { + Phase Phase + Topics []types.Hash +} + +// EventElectionsElectionError is emitted when an internal error happened while trying to perform election +type EventElectionsElectionError struct { + Phase Phase + Topics []types.Hash +} + +// EventElectionsMemberKicked is emitted when a member has been removed. +// This should always be followed by either `NewTerm` or `EmptyTerm`. +type EventElectionsMemberKicked struct { + Phase Phase + Member types.AccountID + Topics []types.Hash +} + +// EventElectionsRenounced is emitted when a member has renounced their candidacy. +type EventElectionsRenounced struct { + Phase Phase + Member types.AccountID + Topics []types.Hash +} + +// EventElectionsSeatHolderSlashed is emitted when a seat holder was slashed by amount +// by being forcefully removed from the set +type EventElectionsSeatHolderSlashed struct { + Phase Phase + Who types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventGiltBidPlaced is emitted when a bid was successfully placed. +type EventGiltBidPlaced struct { + Phase Phase + Who types.AccountID + Amount types.U128 + Duration types.U32 + Topics []types.Hash +} + +// EventGiltBidRetracted is emitted when a bid was successfully removed (before being accepted as a gilt). +type EventGiltBidRetracted struct { + Phase Phase + Who types.AccountID + Amount types.U128 + Duration types.U32 + Topics []types.Hash +} + +// EventGiltGiltIssued is emitted when a bid was accepted as a gilt. The balance may not be released until expiry. +type EventGiltGiltIssued struct { + Phase Phase + Index types.U32 + Expiry types.U32 + Who types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventGiltGiltThawed is emitted when an expired gilt has been thawed. +type EventGiltGiltThawed struct { + Phase Phase + Index types.U32 + Who types.AccountID + OriginalAmount types.U128 + AdditionalAmount types.U128 + Topics []types.Hash +} + +// A name was set or reset (which will remove all judgements). +type EventIdentitySet struct { + Phase Phase + Identity types.AccountID + Topics []types.Hash +} + +// A name was cleared, and the given balance returned. +type EventIdentityCleared struct { + Phase Phase + Identity types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// A name was removed and the given balance slashed. +type EventIdentityKilled struct { + Phase Phase + Identity types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// A judgement was asked from a registrar. +type EventIdentityJudgementRequested struct { + Phase Phase + Sender types.AccountID + RegistrarIndex types.U32 + Topics []types.Hash +} + +// A judgement request was retracted. +type EventIdentityJudgementUnrequested struct { + Phase Phase + Sender types.AccountID + RegistrarIndex types.U32 + Topics []types.Hash +} + +// A judgement was given by a registrar. +type EventIdentityJudgementGiven struct { + Phase Phase + Target types.AccountID + RegistrarIndex types.U32 + Topics []types.Hash +} + +// A registrar was added. +type EventIdentityRegistrarAdded struct { + Phase Phase + RegistrarIndex types.U32 + Topics []types.Hash +} + +// EventIdentitySubIdentityAdded is emitted when a sub-identity was added to an identity and the deposit paid +type EventIdentitySubIdentityAdded struct { + Phase Phase + Sub types.AccountID + Main types.AccountID + Deposit types.U128 + Topics []types.Hash +} + +// EventIdentitySubIdentityRemoved is emitted when a sub-identity was removed from an identity and the deposit freed +type EventIdentitySubIdentityRemoved struct { + Phase Phase + Sub types.AccountID + Main types.AccountID + Deposit types.U128 + Topics []types.Hash +} + +// EventIdentitySubIdentityRevoked is emitted when a sub-identity was cleared, and the given deposit repatriated from +// the main identity account to the sub-identity account. +type EventIdentitySubIdentityRevoked struct { + Phase Phase + Sub types.AccountID + Main types.AccountID + Deposit types.U128 + Topics []types.Hash +} + +// EventSocietyFounded is emitted when the society is founded by the given identity +type EventSocietyFounded struct { + Phase Phase + Founder types.AccountID + Topics []types.Hash +} + +// EventSocietyBid is emitted when a membership bid just happened. The given account is the candidate's ID +// and their offer is the second +type EventSocietyBid struct { + Phase Phase + Candidate types.AccountID + Offer types.U128 + Topics []types.Hash +} + +// EventSocietyVouch is emitted when a membership bid just happened by vouching. +// The given account is the candidate's ID and, their offer is the second. The vouching party is the third. +type EventSocietyVouch struct { + Phase Phase + Candidate types.AccountID + Offer types.U128 + Vouching types.AccountID + Topics []types.Hash +} + +// EventSocietyAutoUnbid is emitted when a [candidate] was dropped (due to an excess of bids in the system) +type EventSocietyAutoUnbid struct { + Phase Phase + Candidate types.AccountID + Topics []types.Hash +} + +// EventSocietyUnbid is emitted when a [candidate] was dropped (by their request) +type EventSocietyUnbid struct { + Phase Phase + Candidate types.AccountID + Topics []types.Hash +} + +// EventSocietyUnvouch is emitted when a [candidate] was dropped (by request of who vouched for them) +type EventSocietyUnvouch struct { + Phase Phase + Candidate types.AccountID + Topics []types.Hash +} + +// EventSocietyInducted is emitted when a group of candidates have been inducted. +// The batch's primary is the first value, the batch in full is the second. +type EventSocietyInducted struct { + Phase Phase + Primary types.AccountID + Candidates []types.AccountID + Topics []types.Hash +} + +// EventSocietySuspendedMemberJudgement is emitted when a suspended member has been judged +type EventSocietySuspendedMemberJudgement struct { + Phase Phase + Who types.AccountID + Judged bool + Topics []types.Hash +} + +// EventSocietyCandidateSuspended is emitted when a [candidate] has been suspended +type EventSocietyCandidateSuspended struct { + Phase Phase + Candidate types.AccountID + Topics []types.Hash +} + +// EventSocietyMemberSuspended is emitted when a [member] has been suspended +type EventSocietyMemberSuspended struct { + Phase Phase + Member types.AccountID + Topics []types.Hash +} + +// EventSocietyChallenged is emitted when a [member] has been challenged +type EventSocietyChallenged struct { + Phase Phase + Member types.AccountID + Topics []types.Hash +} + +// EventSocietyVote is emitted when a vote has been placed +type EventSocietyVote struct { + Phase Phase + Candidate types.AccountID + Voter types.AccountID + Vote bool + Topics []types.Hash +} + +// EventSocietyDefenderVote is emitted when a vote has been placed for a defending member +type EventSocietyDefenderVote struct { + Phase Phase + Voter types.AccountID + Vote bool + Topics []types.Hash +} + +// EventSocietyNewMaxMembers is emitted when a new [max] member count has been set +type EventSocietyNewMaxMembers struct { + Phase Phase + Max types.U32 + Topics []types.Hash +} + +// EventSocietyUnfounded is emitted when society is unfounded +type EventSocietyUnfounded struct { + Phase Phase + Founder types.AccountID + Topics []types.Hash +} + +// EventSocietyDeposit is emitted when some funds were deposited into the society account +type EventSocietyDeposit struct { + Phase Phase + Value types.U128 + Topics []types.Hash +} + +// EventRecoveryCreated is emitted when a recovery process has been set up for an account +type EventRecoveryCreated struct { + Phase Phase + Who types.AccountID + Topics []types.Hash +} + +// EventRecoveryInitiated is emitted when a recovery process has been initiated for account_1 by account_2 +type EventRecoveryInitiated struct { + Phase Phase + Account types.AccountID + Who types.AccountID + Topics []types.Hash +} + +// EventRecoveryVouched is emitted when a recovery process for account_1 by account_2 has been vouched for by account_3 +type EventRecoveryVouched struct { + Phase Phase + Lost types.AccountID + Rescuer types.AccountID + Who types.AccountID + Topics []types.Hash +} + +// EventRegistrarRegistered is emitted when a parachain is registered. +type EventRegistrarRegistered struct { + Phase Phase + ParachainID ParachainID + Account types.AccountID + Topics []types.Hash +} + +// EventRegistrarDeregistered is emitted when a parachain is deregistered. +type EventRegistrarDeregistered struct { + Phase Phase + ParachainID ParachainID + Topics []types.Hash +} + +// EventRegistrarReserved is emitted when a parachain slot is reserved. +type EventRegistrarReserved struct { + Phase Phase + ParachainID ParachainID + Account types.AccountID + Topics []types.Hash +} + +// EventReferendaSubmitted is emitted when a referendum has been submitted. +type EventReferendaSubmitted struct { + Phase Phase + Index types.U32 + Track types.U8 + ProposalHash types.Hash + Topics []types.Hash +} + +// EventReferendaDecisionDepositPlaced is emitted when the decision deposit has been placed. +type EventReferendaDecisionDepositPlaced struct { + Phase Phase + Index types.U32 + Who types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventReferendaDecisionDepositRefunded is emitted when the decision deposit has been refunded. +type EventReferendaDecisionDepositRefunded struct { + Phase Phase + Index types.U32 + Who types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventReferendaDecisionSlashed is emitted when a deposit has been slashed. +type EventReferendaDecisionSlashed struct { + Phase Phase + Who types.AccountID + Amount types.U128 + Topics []types.Hash +} + +// EventReferendaDecisionStarted is emitted when a referendum has moved into the deciding phase. +type EventReferendaDecisionStarted struct { + Phase Phase + Index types.U32 + Track types.U8 + ProposalHash types.Hash + Tally types.Tally + Topics []types.Hash +} + +// EventReferendaConfirmStarted is emitted when a referendum has been started. +type EventReferendaConfirmStarted struct { + Phase Phase + Index types.U32 + Topics []types.Hash +} + +// EventReferendaConfirmAborted is emitted when a referendum has been aborted. +type EventReferendaConfirmAborted struct { + Phase Phase + Index types.U32 + Topics []types.Hash +} + +// EventReferendaConfirmed is emitted when a referendum has ended its confirmation phase and is ready for approval. +type EventReferendaConfirmed struct { + Phase Phase + Index types.U32 + Tally types.Tally + Topics []types.Hash +} + +// EventReferendaApproved is emitted when a referendum has been approved and its proposal has been scheduled. +type EventReferendaApproved struct { + Phase Phase + Index types.U32 + Topics []types.Hash +} + +// EventReferendaRejected is emitted when a proposal has been rejected by referendum. +type EventReferendaRejected struct { + Phase Phase + Index types.U32 + Tally types.Tally + Topics []types.Hash +} + +// EventReferendaTimedOut is emitted when a referendum has been timed out without being decided. +type EventReferendaTimedOut struct { + Phase Phase + Index types.U32 + Tally types.Tally + Topics []types.Hash +} + +// EventReferendaCancelled is emitted when a referendum has been cancelled. +type EventReferendaCancelled struct { + Phase Phase + Index types.U32 + Tally types.Tally + Topics []types.Hash +} + +// EventReferendaKilled is emitted when a referendum has been killed. +type EventReferendaKilled struct { + Phase Phase + Index types.U32 + Tally types.Tally + Topics []types.Hash +} + +// EventRecoveryClosed is emitted when a recovery process for account_1 by account_2 has been closed +type EventRecoveryClosed struct { + Phase Phase + Who types.AccountID + Rescuer types.AccountID + Topics []types.Hash +} + +// EventRecoveryAccountRecovered is emitted when account_1 has been successfully recovered by account_2 +type EventRecoveryAccountRecovered struct { + Phase Phase + Who types.AccountID + Rescuer types.AccountID + Topics []types.Hash +} + +// EventRecoveryRemoved is emitted when a recovery process has been removed for an account +type EventRecoveryRemoved struct { + Phase Phase + Who types.AccountID + Topics []types.Hash +} + +// EventVestingVestingUpdated is emitted when the amount vested has been updated. +// This could indicate more funds are available. +// The balance given is the amount which is left unvested (and thus locked) +type EventVestingVestingUpdated struct { + Phase Phase + Account types.AccountID + Unvested types.U128 + Topics []types.Hash +} + +// EventVoterListRebagged is emitted when an account is moved from one bag to another. +type EventVoterListRebagged struct { + Phase Phase + Who types.AccountID + From types.U64 + To types.U64 + Topics []types.Hash +} + +// EventVoterListScoreUpdated is emitted when the score of an account is updated to the given amount. +type EventVoterListScoreUpdated struct { + Phase Phase + Who types.AccountID + NewScore types.U64 + Topics []types.Hash +} + +// EventWhitelistCallWhitelisted is emitted when a call has been whitelisted. +type EventWhitelistCallWhitelisted struct { + Phase Phase + CallHash types.Hash + Topics []types.Hash +} + +// EventWhitelistWhitelistedCallRemoved is emitted when a whitelisted call has been removed. +type EventWhitelistWhitelistedCallRemoved struct { + Phase Phase + CallHash types.Hash + Topics []types.Hash +} + +// EventWhitelistWhitelistedCallDispatched is emitted when a whitelisted call has been dispatched. +type EventWhitelistWhitelistedCallDispatched struct { + Phase Phase + CallHash types.Hash + Result DispatchResult + Topics []types.Hash +} + +// EventXcmPalletAttempted is emitted when the execution of an XCM message was attempted. +type EventXcmPalletAttempted struct { + Phase Phase + Outcome types.Outcome + Topics []types.Hash +} + +// EventXcmPalletSent is emitted when an XCM message was sent. +type EventXcmPalletSent struct { + Phase Phase + Origin types.MultiLocationV1 + Destination types.MultiLocationV1 + Message []types.Instruction + Topics []types.Hash +} + +// EventXcmPalletUnexpectedResponse is emitted when a query response which does not match a registered query +// is received. +// This may be because a matching query was never registered, it may be because it is a duplicate response, or +// because the query timed out. +type EventXcmPalletUnexpectedResponse struct { + Phase Phase + OriginLocation types.MultiLocationV1 + QueryID types.U64 + Topics []types.Hash +} + +// EventXcmPalletResponseReady is emitted when a query response has been received and is ready for +// taking with `take_response`. There is no registered notification call. +type EventXcmPalletResponseReady struct { + Phase Phase + QueryID types.U64 + Response types.Response + Topics []types.Hash +} + +// EventXcmPalletNotified is emitted when a query response has been received and query is removed. +// The registered notification has been dispatched and executed successfully. +type EventXcmPalletNotified struct { + Phase Phase + QueryID types.U64 + PalletIndex types.U8 + CallIndex types.U8 + Topics []types.Hash +} + +// EventXcmPalletNotifyOverweight is emitted when a query response has been received and query is removed. +// The registered notification could not be dispatched because the dispatch weight is greater than +// the maximum weight originally budgeted by this runtime for the query result. +type EventXcmPalletNotifyOverweight struct { + Phase Phase + QueryID types.U64 + PalletIndex types.U8 + CallIndex types.U8 + ActualWeight Weight + MaxBudgetedWeight Weight + Topics []types.Hash +} + +// EventXcmPalletNotifyDispatchError is emitted when a query response has been received and query is removed. +// There was a general error with dispatching the notification call. +type EventXcmPalletNotifyDispatchError struct { + Phase Phase + QueryID types.U64 + PalletIndex types.U8 + CallIndex types.U8 + Topics []types.Hash +} + +// EventXcmPalletNotifyDecodeFailed is emitted when a query response has been received and query is removed. +// The dispatch was unable to be decoded into a `Call`; this might be due to dispatch function having a signature +// which is not `(origin, QueryId, Response)`. +type EventXcmPalletNotifyDecodeFailed struct { + Phase Phase + QueryID types.U64 + PalletIndex types.U8 + CallIndex types.U8 + Topics []types.Hash +} + +// EventXcmPalletInvalidResponder is emitted when the expected query response +// has been received but the origin location of the response does not match that expected. +// The query remains registered for a later, valid, response to be received and acted upon. +type EventXcmPalletInvalidResponder struct { + Phase Phase + OriginLocation types.MultiLocationV1 + QueryID types.U64 + ExpectedLocation types.OptionMultiLocationV1 + Topics []types.Hash +} + +// EventXcmPalletInvalidResponderVersion is emitted when the expected query response +// has been received but the expected origin location placed in storage by this runtime +// previously cannot be decoded. The query remains registered. +// This is unexpected (since a location placed in storage in a previously executing +// runtime should be readable prior to query timeout) and dangerous since the possibly +// valid response will be dropped. Manual governance intervention is probably going to be +// needed. +type EventXcmPalletInvalidResponderVersion struct { + Phase Phase + OriginLocation types.MultiLocationV1 + QueryID types.U64 + Topics []types.Hash +} + +// EventXcmPalletResponseTaken is emitted when the received query response has been read and removed. +type EventXcmPalletResponseTaken struct { + Phase Phase + QueryID types.U64 + Topics []types.Hash +} + +// EventXcmPalletAssetsTrapped is emitted when some assets have been placed in an asset trap. +type EventXcmPalletAssetsTrapped struct { + Phase Phase + Hash types.H256 + Origin types.MultiLocationV1 + Assets types.VersionedMultiAssets + Topics []types.Hash +} + +type XcmVersion types.U32 + +// EventXcmPalletVersionChangeNotified is emitted when an XCM version change notification +// message has been attempted to be sent. +type EventXcmPalletVersionChangeNotified struct { + Phase Phase + Destination types.MultiLocationV1 + Result XcmVersion + Topics []types.Hash +} + +// EventXcmPalletSupportedVersionChanged is emitted when the supported version of a location has been changed. +// This might be through an automatic notification or a manual intervention. +type EventXcmPalletSupportedVersionChanged struct { + Phase Phase + Location types.MultiLocationV1 + XcmVersion XcmVersion + Topics []types.Hash +} + +// EventXcmPalletNotifyTargetSendFail is emitted when a given location which had a version change +// subscription was dropped owing to an error sending the notification to it. +type EventXcmPalletNotifyTargetSendFail struct { + Phase Phase + Location types.MultiLocationV1 + QueryID types.U64 + XcmError types.XCMError + Topics []types.Hash +} + +// EventXcmPalletNotifyTargetMigrationFail is emitted when a given location which had a +// version change subscription was dropped owing to an error migrating the location to our new XCM format. +type EventXcmPalletNotifyTargetMigrationFail struct { + Phase Phase + Location types.VersionedMultiLocation + QueryID types.U64 + Topics []types.Hash +} + +// EventVestingVestingCompleted is emitted when an [account] has become fully vested. No further vesting can happen +type EventVestingVestingCompleted struct { + Phase Phase + Account types.AccountID + Topics []types.Hash +} + +// EventSchedulerScheduled is emitted when scheduled some task +type EventSchedulerScheduled struct { + Phase Phase + When types.U32 + Index types.U32 + Topics []types.Hash +} + +// EventSchedulerCanceled is emitted when canceled some task +type EventSchedulerCanceled struct { + Phase Phase + When types.U32 + Index types.U32 + Topics []types.Hash +} + +// EventSchedulerDispatched is emitted when dispatched some task +type EventSchedulerDispatched struct { + Phase Phase + Task TaskAddress + ID types.OptionBytes + Result DispatchResult + Topics []types.Hash +} + +type SchedulerLookupError byte + +const ( + // Unknown A call of this hash was not known. + Unknown = 0 + // BadFormat The preimage for this hash was known but could not be decoded into a Call. + BadFormat = 1 +) + +func (sle *SchedulerLookupError) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + vb := SchedulerLookupError(b) + switch vb { + case Unknown, BadFormat: + *sle = vb + default: + return fmt.Errorf("unknown SchedulerLookupError enum: %v", vb) + } + return err +} + +func (sle SchedulerLookupError) Encode(encoder scale.Encoder) error { + return encoder.PushByte(byte(sle)) +} + +// EventSchedulerCallLookupFailed is emitted when the call for the provided hash was not found +// so the task has been aborted. +type EventSchedulerCallLookupFailed struct { + Phase Phase + Task TaskAddress + ID types.OptionBytes + Error SchedulerLookupError + Topics []types.Hash +} + +// EventPreimageCleared is emitted when a preimage has been cleared +type EventPreimageCleared struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +// EventPreimageNoted is emitted when a preimage has been noted +type EventPreimageNoted struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +// EventPreimageRequested is emitted when a preimage has been requested +type EventPreimageRequested struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +// EventProxyProxyExecuted is emitted when a proxy was executed correctly, with the given [result] +type EventProxyProxyExecuted struct { + Phase Phase + Result DispatchResult + Topics []types.Hash +} + +// EventProxyAnonymousCreated is emitted when an anonymous account has been created by new proxy with given, +// disambiguation index and proxy type. +type EventProxyAnonymousCreated struct { + Phase Phase + Anonymous types.AccountID + Who types.AccountID + ProxyType types.U8 + DisambiguationIndex types.U16 + Topics []types.Hash +} + +// EventProxyProxyAdded is emitted when a proxy was added. +type EventProxyProxyAdded struct { + Phase Phase + Delegator types.AccountID + Delegatee types.AccountID + ProxyType types.U8 + Delay types.U32 + Topics []types.Hash +} + +// EventProxyProxyRemoved is emitted when a proxy was removed. +type EventProxyProxyRemoved struct { + Phase Phase + Delegator types.AccountID + Delegatee types.AccountID + ProxyType types.U8 + BlockNumber types.U32 + Topics []types.Hash +} + +// EventProxyAnnounced is emitted when an announcement was placed to make a call in the future +type EventProxyAnnounced struct { + Phase Phase + Real types.AccountID + Proxy types.AccountID + CallHash types.Hash + Topics []types.Hash +} + +// EventSudoSudid is emitted when a sudo just took place. +type EventSudoSudid struct { + Phase Phase + Result DispatchResult + Topics []types.Hash +} + +// EventSudoKeyChanged is emitted when the sudoer just switched identity; the old key is supplied. +type EventSudoKeyChanged struct { + Phase Phase + AccountID types.AccountID + Topics []types.Hash +} + +// A sudo just took place. +type EventSudoAsDone struct { + Phase Phase + Done bool + Topics []types.Hash +} + +// EventTreasuryProposed is emitted when New proposal. +type EventTreasuryProposed struct { + Phase Phase + ProposalIndex types.U32 + Topics []types.Hash +} + +// EventTreasurySpending is emitted when we have ended a spend period and will now allocate funds. +type EventTreasurySpending struct { + Phase Phase + BudgetRemaining types.U128 + Topics []types.Hash +} + +// EventTreasuryAwarded is emitted when some funds have been allocated. +type EventTreasuryAwarded struct { + Phase Phase + ProposalIndex types.U32 + Amount types.U128 + Beneficiary types.AccountID + Topics []types.Hash +} + +// EventTreasuryRejected is emitted when s proposal was rejected; funds were slashed. +type EventTreasuryRejected struct { + Phase Phase + ProposalIndex types.U32 + Amount types.U128 + Topics []types.Hash +} + +// EventTreasuryBurnt is emitted when some of our funds have been burnt. +type EventTreasuryBurnt struct { + Phase Phase + Burn types.U128 + Topics []types.Hash +} + +// EventTreasuryRollover is emitted when spending has finished; this is the amount that rolls over until next spend. +type EventTreasuryRollover struct { + Phase Phase + BudgetRemaining types.U128 + Topics []types.Hash +} + +// EventTreasuryDeposit is emitted when some funds have been deposited. +type EventTreasuryDeposit struct { + Phase Phase + Deposited types.U128 + Topics []types.Hash +} + +// EventTipsNewTip is emitted when a new tip suggestion has been opened. +type EventTipsNewTip struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +// EventTipsTipClosing is emitted when a tip suggestion has reached threshold and is closing. +type EventTipsTipClosing struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +// EventTipsTipClosed is emitted when a tip suggestion has been closed. +type EventTipsTipClosed struct { + Phase Phase + Hash types.Hash + AccountID types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventTipsTipSlashed is emitted when a tip suggestion has been slashed. +type EventTipsTipSlashed struct { + Phase Phase + Hash types.Hash + AccountID types.AccountID + Balance types.U128 + Topics []types.Hash +} + +// EventTransactionStorageStored is emitted when data is stored under a specific index. +type EventTransactionStorageStored struct { + Phase Phase + Index types.U32 + Topics []types.Hash +} + +// EventTransactionStorageRenewed is emitted when data is renewed under a specific index. +type EventTransactionStorageRenewed struct { + Phase Phase + Index types.U32 + Topics []types.Hash +} + +// EventTransactionStorageProofChecked is emitted when storage proof was successfully checked. +type EventTransactionStorageProofChecked struct { + Phase Phase + Topics []types.Hash +} + +type EventTransactionPaymentTransactionFeePaid struct { + Phase Phase + Who types.AccountID + ActualFee types.U128 + Tip types.U128 + Topics []types.Hash +} + +// EventTipsTipRetracted is emitted when a tip suggestion has been retracted. +type EventTipsTipRetracted struct { + Phase Phase + Hash types.Hash + Topics []types.Hash +} + +type BountyIndex types.U32 + +// EventBountiesBountyProposed is emitted for a new bounty proposal. +type EventBountiesBountyProposed struct { + Phase Phase + ProposalIndex BountyIndex + Topics []types.Hash +} + +// EventBountiesBountyRejected is emitted when a bounty proposal was rejected; funds were slashed. +type EventBountiesBountyRejected struct { + Phase Phase + ProposalIndex BountyIndex + Bond types.U128 + Topics []types.Hash +} + +// EventBountiesBountyBecameActive is emitted when a bounty proposal is funded and became active +type EventBountiesBountyBecameActive struct { + Phase Phase + Index BountyIndex + Topics []types.Hash +} + +// EventBountiesBountyAwarded is emitted when a bounty is awarded to a beneficiary +type EventBountiesBountyAwarded struct { + Phase Phase + Index BountyIndex + Beneficiary types.AccountID + Topics []types.Hash +} + +// EventBountiesBountyClaimed is emitted when a bounty is claimed by beneficiary +type EventBountiesBountyClaimed struct { + Phase Phase + Index BountyIndex + Payout types.U128 + Beneficiary types.AccountID + Topics []types.Hash +} + +// EventBountiesBountyCanceled is emitted when a bounty is cancelled. +type EventBountiesBountyCanceled struct { + Phase Phase + Index BountyIndex + Topics []types.Hash +} + +// EventBountiesBountyExtended is emitted when a bounty is extended. +type EventBountiesBountyExtended struct { + Phase Phase + Index BountyIndex + Topics []types.Hash +} + +// EventChildBountiesAdded is emitted when a child-bounty is added. +type EventChildBountiesAdded struct { + Phase Phase + Index BountyIndex + ChildIndex BountyIndex + Topics []types.Hash +} + +// EventChildBountiesAwarded is emitted when a child-bounty is awarded to a beneficiary. +type EventChildBountiesAwarded struct { + Phase Phase + Index BountyIndex + ChildIndex BountyIndex + Beneficiary types.AccountID + Topics []types.Hash +} + +// EventChildBountiesClaimed is emitted when a child-bounty is claimed by a beneficiary. +type EventChildBountiesClaimed struct { + Phase Phase + Index BountyIndex + ChildIndex BountyIndex + Payout types.U128 + Beneficiary types.AccountID + Topics []types.Hash +} + +// EventChildBountiesCanceled is emitted when a child-bounty is canceled. +type EventChildBountiesCanceled struct { + Phase Phase + Index BountyIndex + ChildIndex BountyIndex + Topics []types.Hash +} + +// EventUniquesApprovalCancelled is emitted when an approval for a delegate account to transfer the instance of +// an asset class was cancelled by its owner +type EventUniquesApprovalCancelled struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Owner types.AccountID + Delegate types.AccountID + Topics []types.Hash +} + +// EventUniquesApprovedTransfer is emitted when an `instance` of an asset `class` has been approved by the `owner` +// for transfer by a `delegate`. +type EventUniquesApprovedTransfer struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Owner types.AccountID + Delegate types.AccountID + Topics []types.Hash +} + +// EventUniquesAssetStatusChanged is emitted when an asset `class` has had its attributes changed by the `Force` origin +type EventUniquesAssetStatusChanged struct { + Phase Phase + CollectionID types.U64 + Topics []types.Hash +} + +// EventUniquesAttributeCleared is emitted when an attribute metadata has been cleared for an asset class or instance +type EventUniquesAttributeCleared struct { + Phase Phase + CollectionID types.U64 + MaybeItem types.Option[types.U128] + Key types.Bytes + Topics []types.Hash +} + +// EventUniquesAttributeSet is emitted when a new attribute metadata has been set for an asset class or instance +type EventUniquesAttributeSet struct { + Phase Phase + CollectionID types.U64 + MaybeItem types.Option[types.U128] + Key types.Bytes + Value types.Bytes + Topics []types.Hash +} + +// EventUniquesBurned is emitted when an asset `instance` was destroyed +type EventUniquesBurned struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Owner types.AccountID + Topics []types.Hash +} + +// EventUniquesClassFrozen is emitted when some asset `class` was frozen +type EventUniquesClassFrozen struct { + Phase Phase + CollectionID types.U64 + Topics []types.Hash +} + +// EventUniquesClassMetadataCleared is emitted when metadata has been cleared for an asset class +type EventUniquesClassMetadataCleared struct { + Phase Phase + CollectionID types.U64 + Topics []types.Hash +} + +// EventUniquesClassMetadataSet is emitted when new metadata has been set for an asset class +type EventUniquesClassMetadataSet struct { + Phase Phase + CollectionID types.U64 + Data types.Bytes + IsFrozen types.Bool + Topics []types.Hash +} + +// EventUniquesClassThawed is emitted when some asset `class` was thawed +type EventUniquesClassThawed struct { + Phase Phase + CollectionID types.U64 + Topics []types.Hash +} + +// EventUniquesCreated is emitted when an asset class was created +type EventUniquesCreated struct { + Phase Phase + CollectionID types.U64 + Creator types.AccountID + Owner types.AccountID + Topics []types.Hash +} + +// EventUniquesDestroyed is emitted when an asset `class` was destroyed +type EventUniquesDestroyed struct { + Phase Phase + CollectionID types.U64 + Topics []types.Hash +} + +// EventUniquesForceCreated is emitted when an asset class was force-created +type EventUniquesForceCreated struct { + Phase Phase + CollectionID types.U64 + Owner types.AccountID + Topics []types.Hash +} + +// EventUniquesFrozen is emitted when some asset `instance` was frozen +type EventUniquesFrozen struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Topics []types.Hash +} + +// EventUniquesIssued is emitted when an asset instance was issued +type EventUniquesIssued struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Owner types.AccountID + Topics []types.Hash +} + +// EventUniquesMetadataCleared is emitted when metadata has been cleared for an asset instance +type EventUniquesMetadataCleared struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Topics []types.Hash +} + +// EventUniquesMetadataSet is emitted when metadata has been set for an asset instance +type EventUniquesMetadataSet struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Data types.Bytes + IsFrozen types.Bool + Topics []types.Hash +} + +// EventUniquesOwnerChanged is emitted when the owner changed +type EventUniquesOwnerChanged struct { + Phase Phase + CollectionID types.U64 + NewOwner types.AccountID + Topics []types.Hash +} + +// EventUniquesRedeposited is emitted when metadata has been cleared for an asset instance +type EventUniquesRedeposited struct { + Phase Phase + CollectionID types.U64 + SuccessfulItems []types.U128 + Topics []types.Hash +} + +// EventUniquesTeamChanged is emitted when the management team changed +type EventUniquesTeamChanged struct { + Phase Phase + CollectionID types.U64 + Issuer types.AccountID + Admin types.AccountID + Freezer types.AccountID + Topics []types.Hash +} + +// EventUniquesThawed is emitted when some asset instance was thawed +type EventUniquesThawed struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + Topics []types.Hash +} + +// EventUniquesTransferred is emitted when some asset instance was transferred +type EventUniquesTransferred struct { + Phase Phase + CollectionID types.U64 + ItemID types.U128 + From types.AccountID + To types.AccountID + Topics []types.Hash +} + +// EventUMPInvalidFormat is emitted when the upward message is invalid XCM. +type EventUMPInvalidFormat struct { + Phase Phase + MessageID [32]types.U8 + Topics []types.Hash +} + +// EventUMPUnsupportedVersion is emitted when the upward message is unsupported version of XCM. +type EventUMPUnsupportedVersion struct { + Phase Phase + MessageID [32]types.U8 + Topics []types.Hash +} + +// EventUMPExecutedUpward is emitted when the upward message executed with the given outcome. +type EventUMPExecutedUpward struct { + Phase Phase + MessageID [32]types.U8 + Outcome types.Outcome + Topics []types.Hash +} + +// EventUMPWeightExhausted is emitted when the weight limit for handling upward messages was reached. +type EventUMPWeightExhausted struct { + Phase Phase + MessageID [32]types.U8 + Remaining Weight + Required Weight + Topics []types.Hash +} + +// EventUMPUpwardMessagesReceived is emitted when some upward messages have been received and will be processed. +type EventUMPUpwardMessagesReceived struct { + Phase Phase + ParachainID ParachainID + Count types.U32 + Size types.U32 + Topics []types.Hash +} + +// EventUMPOverweightEnqueued is emitted when the weight budget was exceeded for an individual upward message. +// This message can be later dispatched manually using `service_overweight` dispatchable using +// the assigned `overweight_index`. +type EventUMPOverweightEnqueued struct { + Phase Phase + ParachainID ParachainID + MessageID [32]types.U8 + OverweightIndex types.U64 + RequiredWeight Weight + Topics []types.Hash +} + +// EventUMPOverweightServiced is emitted when the upward message from the +// overweight queue was executed with the given actual weight used. +type EventUMPOverweightServiced struct { + Phase Phase + OverweightIndex types.U64 + Used Weight + Topics []types.Hash +} + +// EventContractsInstantiated is emitted when a contract is deployed by address at the specified address +type EventContractsInstantiated struct { + Phase Phase + Deployer types.AccountID + Contract types.AccountID + Topics []types.Hash +} + +// EventContractsTerminated The only way for a contract to be removed and emitting this event is by calling +// `seal_terminate` +type EventContractsTerminated struct { + Phase Phase + Contract types.AccountID + Beneficiary types.AccountID + Topics []types.Hash +} + +// EventConvictionVotingDelegated is emitted when an account has delegated their vote to another account. +type EventConvictionVotingDelegated struct { + Phase Phase + Who types.AccountID + Target types.AccountID + Topics []types.Hash +} + +// EventConvictionVotingUndelegated is emitted when an account has delegated their vote to another account. +type EventConvictionVotingUndelegated struct { + Phase Phase + Who types.AccountID + Target types.AccountID + Topics []types.Hash +} + +// EventContractsContractEmitted is emitted when a custom event emitted by the contract +type EventContractsContractEmitted struct { + Phase Phase + Contract types.AccountID + Data types.Bytes + Topics []types.Hash +} + +// EventContractsCalled is emitted when a contract is called +type EventContractsCalled struct { + Phase Phase + Caller types.AccountID + Contract types.AccountID + Topics []types.Hash +} + +// EventContractsContractCodeUpdated is emitted when a contract's code was updated +type EventContractsContractCodeUpdated struct { + Phase Phase + Contract types.AccountID + NewCodeHash types.Hash + OldCodeHash types.Hash + Topics []types.Hash +} + +type EventCollatorSelectionNewInvulnerables struct { + Phase Phase + NewInvulnerables []types.AccountID + Topics []types.Hash +} + +type EventCollatorSelectionNewDesiredCandidates struct { + Phase Phase + NewDesiredCandidates types.U32 + Topics []types.Hash +} + +type EventCollatorSelectionNewCandidacyBond struct { + Phase Phase + NewCandidacyBond types.U128 + Topics []types.Hash +} + +type EventCollatorSelectionCandidateAdded struct { + Phase Phase + CandidateAdded types.AccountID + Bond types.U128 + Topics []types.Hash +} + +type EventCollatorSelectionCandidateRemoved struct { + Phase Phase + CandidateRemoved types.AccountID + Topics []types.Hash +} + +// EventContractsCodeRemoved is emitted when code with the specified hash was removed +type EventContractsCodeRemoved struct { + Phase Phase + CodeHash types.Hash + Topics []types.Hash +} + +// EventContractsCodeStored is emitted when code with the specified hash has been stored +type EventContractsCodeStored struct { + Phase Phase + CodeHash types.Hash + Topics []types.Hash +} + +// EventContractsScheduleUpdated is triggered when the current [schedule] is updated +type EventContractsScheduleUpdated struct { + Phase Phase + Schedule types.U32 + Topics []types.Hash +} + +// EventContractsContractExecution is triggered when an event deposited upon execution of a contract from the account +type EventContractsContractExecution struct { + Phase Phase + Account types.AccountID + Data types.Bytes + Topics []types.Hash +} + +// EventUtilityBatchInterrupted is emitted when a batch of dispatches did not complete fully. +// Index of first failing dispatch given, as well as the error. +type EventUtilityBatchInterrupted struct { + Phase Phase + Index types.U32 + DispatchError types.DispatchError + Topics []types.Hash +} + +// EventUtilityBatchCompleted is emitted when a batch of dispatches completed fully with no error. +type EventUtilityBatchCompleted struct { + Phase Phase + Topics []types.Hash +} + +// EventUtilityDispatchedAs is emitted when a call was dispatched +type EventUtilityDispatchedAs struct { + Phase Phase + Index types.U32 + Result DispatchResult + Topics []types.Hash +} + +// EventUtilityItemCompleted is emitted when a single item within a Batch of dispatches has completed with no error +type EventUtilityItemCompleted struct { + Phase Phase + Topics []types.Hash +} + +// EventUtilityNewMultisig is emitted when a new multisig operation has begun. +// First param is the account that is approving, second is the multisig account, third is hash of the call. +type EventMultisigNewMultisig struct { + Phase Phase + Who, ID types.AccountID + CallHash types.Hash + Topics []types.Hash +} + +// EventNftSalesForSale is emitted when an NFT is out for sale. +type EventNftSalesForSale struct { + Phase Phase + ClassID types.U64 + InstanceID types.U128 + Sale types.Sale + Topics []types.Hash +} + +// EventNftSalesRemoved is emitted when an NFT is removed. +type EventNftSalesRemoved struct { + Phase Phase + ClassID types.U64 + InstanceID types.U128 + Topics []types.Hash +} + +// EventNftSalesSold is emitted when an NFT is sold. +type EventNftSalesSold struct { + Phase Phase + ClassID types.U64 + InstanceID types.U128 + Sale types.Sale + Buyer types.AccountID + Topics []types.Hash +} + +// TimePoint is a global extrinsic index, formed as the extrinsic index within a block, +// together with that block's height. +type TimePoint struct { + Height types.U32 + Index types.U32 +} + +// TaskAddress holds the location of a scheduled task that can be used to remove it +type TaskAddress struct { + When types.U32 + Index types.U32 +} + +// EventUtility is emitted when a multisig operation has been approved by someone. First param is the account that is +// approving, third is the multisig account, fourth is hash of the call. +type EventMultisigApproval struct { + Phase Phase + Who types.AccountID + TimePoint TimePoint + ID types.AccountID + CallHash types.Hash + Topics []types.Hash +} + +// DispatchResult can be returned from dispatchable functions +type DispatchResult struct { + Ok bool + Error types.DispatchError +} + +func (d *DispatchResult) Decode(decoder scale.Decoder) error { + b, err := decoder.ReadOneByte() + if err != nil { + return err + } + + switch b { + case 0: + d.Ok = true + return nil + default: + return decoder.Decode(&d.Error) + } +} + +func (d DispatchResult) Encode(encoder scale.Encoder) error { + if d.Ok { + return encoder.PushByte(0) + } + + if err := encoder.PushByte(1); err != nil { + return err + } + + return encoder.Encode(d.Error) +} + +// EventUtility is emitted when a multisig operation has been executed. First param is the account that is +// approving, third is the multisig account, fourth is hash of the call to be executed. +type EventMultisigExecuted struct { + Phase Phase + Who types.AccountID + TimePoint TimePoint + ID types.AccountID + CallHash types.Hash + Result DispatchResult + Topics []types.Hash +} + +// EventUtility is emitted when a multisig operation has been cancelled. First param is the account that is +// cancelling, third is the multisig account, fourth is hash of the call. +type EventMultisigCancelled struct { + Phase Phase + Who types.AccountID + TimePoint TimePoint + ID types.AccountID + CallHash types.Hash + Topics []types.Hash +} diff --git a/contract/pkg/client.go b/contract/pkg/client.go index 490155c..a7dd2a6 100644 --- a/contract/pkg/client.go +++ b/contract/pkg/client.go @@ -13,12 +13,14 @@ import ( "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/centrifuge/go-substrate-rpc-client/v4/types/codec" + "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg/chainevents" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) const ( CERE = 10_000_000_000 + MGAS = 1_000_000 ) type ( @@ -41,8 +43,8 @@ type ( ContractAddress types.AccountID ContractAddressSS58 string From signature.KeyringPair - Value float64 - GasLimit float64 + Value uint64 + GasLimit uint64 Method []byte Args []interface{} } @@ -51,8 +53,8 @@ type ( Code []byte Salt []byte From signature.KeyringPair - Value float64 - GasLimit float64 + Value uint64 + GasLimit uint64 Method []byte Args []interface{} } @@ -166,8 +168,8 @@ func (b *blockchainClient) listenContractEvents() error { continue } - events := types.EventRecords{} - err = types.EventRecordsRaw(chng.StorageData).DecodeEventRecords(meta, &events) + events := chainevents.EventRecords{} + err = chainevents.EventRecordsRaw(chng.StorageData).DecodeEventRecords(meta, &events) if err != nil { log.WithError(err).Warnf("Error parsing event %x", chng.StorageData[:]) continue @@ -231,6 +233,7 @@ func (b *blockchainClient) CallToReadEncoded(contractAddressSS58 string, fromAdd } func (b *blockchainClient) callToRead(contractAddressSS58 string, fromAddress string, data []byte) (Response, error) { + params := Request{ Origin: fromAddress, Dest: contractAddressSS58, @@ -255,21 +258,13 @@ func (b *blockchainClient) CallToExec(ctx context.Context, contractCall Contract return types.Hash{}, err } - valueRaw := types.NewUCompactFromUInt(uint64(contractCall.Value * CERE)) - var gasLimitRaw types.UCompact - if contractCall.GasLimit > 0 { - gasLimitRaw = types.NewUCompactFromUInt(uint64(contractCall.GasLimit * CERE)) - } else { - resp, err := b.callToRead(contractCall.ContractAddressSS58, contractCall.From.Address, data) - if err != nil { - return types.Hash{}, err - } - gasLimitRaw = types.NewUCompactFromUInt(uint64(resp.GasConsumed)) - } + dest := types.MultiAddress{IsID: true, AsID: contractCall.ContractAddress} + value := types.NewUCompactFromUInt(contractCall.Value) + gasLimit := types.NewUCompactFromUInt(contractCall.GasLimit) + storageDepositLimit := types.NewOptionBoolEmpty() - multiAddress := types.MultiAddress{IsID: true, AsID: contractCall.ContractAddress} extrinsic, err := withRetryOnClosedNetwork(b, func() (types.Extrinsic, error) { - return b.createExtrinsic("Contracts.call", contractCall.From, multiAddress, valueRaw, gasLimitRaw, types.NewOptionBoolEmpty(), data) + return b.createExtrinsic("Contracts.call", contractCall.From, dest, value, gasLimit, storageDepositLimit, data) }) if err != nil { return types.Hash{}, err @@ -341,8 +336,8 @@ func (b *blockchainClient) grabContractInstantiated(hash types.Hash, deployer *t for _, st := range storage { for _, chng := range st.Changes { - events := types.EventRecords{} - err = types.EventRecordsRaw(chng.StorageData).DecodeEventRecords(meta, &events) + events := chainevents.EventRecords{} + err = chainevents.EventRecordsRaw(chng.StorageData).DecodeEventRecords(meta, &events) if err != nil { log.WithError(err).Warnf("Error parsing event %x", chng.StorageData[:]) continue @@ -422,7 +417,7 @@ func (b *blockchainClient) submitAndWaitExtrinsic(ctx context.Context, extrinsic for { select { case status := <-sub.Chan(): - if status.IsInBlock { + if status.IsInBlock || status.IsFinalized { return status.AsInBlock, nil } case err := <-sub.Err(): diff --git a/contract/pkg/mock/ddc_bucket_contract_mock.go b/contract/pkg/mock/ddc_bucket_contract_mock.go index e9f6f52..d582aac 100644 --- a/contract/pkg/mock/ddc_bucket_contract_mock.go +++ b/contract/pkg/mock/ddc_bucket_contract_mock.go @@ -1,12 +1,16 @@ package mock import ( + "context" "encoding/json" "errors" + "fmt" "math" "math/big" + "strings" "time" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg/bucket" @@ -29,33 +33,31 @@ var writerIds = getAccountIDs(accounts) type ( Node struct { - Id uint32 - Url string - Tag string + Key string + Url string + StatusInCluster string } Cluster struct { - Id uint32 - VNodes [][]uint64 - Nodes []uint32 - Params string + Id uint32 + NodesVNodes []NodeVNodes + Params string } - CDNNode struct { - Id uint32 `json:"id"` - Params CDNNodeParams `json:"params"` + NodeVNodes struct { + NodeKey string + VNodes []uint64 } - CDNNodeParams struct { - Url string `json:"url"` - Size int `json:"size"` - Location string `json:"location"` - PublicKey string `json:"publicKey"` + CdnNode struct { + Key string `json:"key"` + Params CDNNodeParams `json:"params"` } - CDNCluster struct { - Id uint32 - Nodes []uint32 + CDNNodeParams struct { + Url string `json:"url"` + Size int `json:"size"` + Location string `json:"location"` } ddcBucketContractMock struct { @@ -64,30 +66,52 @@ type ( lastAccessTime time.Time nodes []Node clusters []Cluster - cdnNodes []CDNNode - cdnClusters []CDNCluster + cdnNodes []CdnNode } ) -func CreateDdcBucketContractMock(apiUrl string, accountId string, nodes []Node, clusters []Cluster, cdnNodes []CDNNode, cdnClusters []CDNCluster) bucket.DdcBucketContract { +func MapTestNodesVNodes(nodes []NodeVNodes) []bucket.NodeVNodesInfo { + var nodesVNodes []bucket.NodeVNodesInfo + for _, node := range nodes { + nodeKey, err := types.NewAccountIDFromHexString(node.NodeKey) + if err != nil { + log.Printf("ERROR DECODING THE ACCOUNT ID err: %v", err) + } + nodeVNodes := bucket.NodeVNodesInfo{ + NodeKey: *nodeKey, + VNodes: MapTokens(node.VNodes), + } + nodesVNodes = append(nodesVNodes, nodeVNodes) + } + return nodesVNodes +} + +func MapTokens(tokens []uint64) []bucket.Token { + var result []bucket.Token + for _, token := range tokens { + result = append(result, types.NewU64(token)) + } + return result +} + +func CreateDdcBucketContractMock(apiUrl string, accountId string, nodes []Node, clusters []Cluster, cdnNodes []CdnNode) bucket.DdcBucketContract { log.Info("DDC Bucket contract configured [MOCK]") return &ddcBucketContractMock{ accountId: accountId, apiUrl: apiUrl, nodes: nodes, clusters: clusters, - cdnClusters: cdnClusters, cdnNodes: cdnNodes, lastAccessTime: time.Now(), } } -func (d *ddcBucketContractMock) BucketGet(bucketId uint32) (*bucket.BucketStatus, error) { +func (d *ddcBucketContractMock) BucketGet(bucketId bucket.BucketId) (*bucket.BucketInfo, error) { if bucketId == 0 || len(d.clusters)*2 < int(bucketId) { return nil, errors.New("unknown bucket") } - clusterId := bucketId + clusterId := uint32(bucketId) if int(bucketId) > len(d.clusters) { clusterId -= uint32(len(d.clusters)) } @@ -95,80 +119,70 @@ func (d *ddcBucketContractMock) BucketGet(bucketId uint32) (*bucket.BucketStatus return CreateBucket(bucketId, clusterId, "", writerIds), nil } -func (d *ddcBucketContractMock) ClusterGet(clusterId uint32) (*bucket.ClusterStatus, error) { +func (d *ddcBucketContractMock) ClusterGet(clusterId bucket.ClusterId) (*bucket.ClusterInfo, error) { for _, cluster := range d.clusters { - if cluster.Id == clusterId { - return &bucket.ClusterStatus{ + if cluster.Id == uint32(clusterId) { + return &bucket.ClusterInfo{ ClusterId: clusterId, Cluster: bucket.Cluster{ ManagerId: types.AccountID{}, - Nodes: cluster.Nodes, - VNodes: cluster.VNodes, + Params: cluster.Params, ResourcePerVNode: 32, ResourceUsed: 0, Revenues: types.NewU128(*big.NewInt(1)), TotalRent: types.NewU128(*big.NewInt(1)), }, - Params: cluster.Params, + NodesVNodes: MapTestNodesVNodes(cluster.NodesVNodes), }, nil } } - return nil, errors.New("unknown cluster") + available := []uint32{} + for _, cluster := range d.clusters { + available = append(available, cluster.Id) + } + + return nil, fmt.Errorf("unknown cluster with id %v | available clusters are: %v", clusterId, available) } -func (d *ddcBucketContractMock) NodeGet(nodeId uint32) (*bucket.NodeStatus, error) { +func (d *ddcBucketContractMock) NodeGet(nodeKey bucket.NodeKey) (*bucket.NodeInfo, error) { for _, node := range d.nodes { - if node.Id == nodeId { - return &bucket.NodeStatus{ - NodeId: nodeId, + if strings.TrimPrefix(node.Key, "0x") == strings.TrimPrefix(nodeKey.ToHexString(), "0x") { + return &bucket.NodeInfo{ + Key: nodeKey, Node: bucket.Node{ - ProviderId: types.AccountID{}, - RentPerMonth: types.NewU128(*big.NewInt(1)), - NodeState: bucket.NodeTags[node.Tag], - FreeResources: 100, + ProviderId: types.AccountID{}, + RentPerMonth: types.NewU128(*big.NewInt(1)), + Params: `{"url":"` + node.Url + `"}`, + StatusInCluster: types.NewOptionU8(types.NewU8((bucket.NodeStatusesInClusterMap[node.StatusInCluster]))), //types.NewOptionBytes([]byte{bucket.NodeStatusesInClusterMap[node.StatusInCluster]}), + FreeResources: 100, }, - Params: `{"url":"` + node.Url + `"}`, }, nil } } - return nil, errors.New("unknown node") -} - -func (d *ddcBucketContractMock) CDNClusterGet(clusterId uint32) (*bucket.CDNClusterStatus, error) { - for _, cluster := range d.cdnClusters { - if cluster.Id == clusterId { - return &bucket.CDNClusterStatus{ - ClusterId: clusterId, - CDNCluster: bucket.CDNCluster{ - ManagerId: types.AccountID{}, - CDNNodes: cluster.Nodes, - ResourceUsed: 0, - Revenues: types.NewU128(*big.NewInt(1)), - UsdPerGb: types.NewU128(*big.NewInt(1)), - }, - }, nil - } + available := []string{} + for _, node := range d.nodes { + available = append(available, node.Key) } - return nil, errors.New("unknown cluster") + return nil, fmt.Errorf("unknown node with key %v | available nodes are: %v", nodeKey, available) } -func (d *ddcBucketContractMock) CDNNodeGet(nodeId uint32) (*bucket.CDNNodeStatus, error) { +func (d *ddcBucketContractMock) CdnNodeGet(nodeKey bucket.CdnNodeKey) (*bucket.CdnNodeInfo, error) { for _, node := range d.cdnNodes { - if node.Id == nodeId { + if strings.TrimPrefix(node.Key, "0x") == strings.TrimPrefix(nodeKey.ToHexString(), "0x") { params, err := json.Marshal(node.Params) if err != nil { return nil, err } - return &bucket.CDNNodeStatus{ - NodeId: nodeId, - Node: bucket.CDNNode{ + return &bucket.CdnNodeInfo{ + Key: nodeKey, + Node: bucket.CdnNode{ ProviderId: types.AccountID{}, UndistributedPayment: types.NewU128(*big.NewInt(1)), + Params: string(params), }, - Params: string(params), }, nil } } @@ -181,12 +195,12 @@ func (d *ddcBucketContractMock) AccountGet(account types.AccountID) (*bucket.Acc if acc == account { return &bucket.Account{ Bonded: types.NewU128(*big.NewInt(100000)), - UnbondedTimestamp: uint64(time.Now().UnixMilli()), + UnbondedTimestamp: types.U64(time.Now().UnixMilli()), }, nil } } - return nil, errors.New("account doesn't exist") + return nil, fmt.Errorf("account doesn't exist %x | available nodes are: %v", account, writerIds) } func (d *ddcBucketContractMock) GetApiUrl() string { @@ -209,19 +223,19 @@ func (d *ddcBucketContractMock) AddContractEventHandler(event string, handler fu return nil } -func CreateBucket(bucketId uint32, clusterId uint32, bucketParams string, writerIds []types.AccountID) *bucket.BucketStatus { - return &bucket.BucketStatus{ +func CreateBucket(bucketId bucket.BucketId, clusterId uint32, bucketParams string, writerIds []types.AccountID) *bucket.BucketInfo { + return &bucket.BucketInfo{ BucketId: bucketId, Bucket: bucket.Bucket{ OwnerId: writerIds[0], - ClusterId: clusterId, + ClusterId: types.NewU32(clusterId), ResourceReserved: 32, - PublicAvailability: clusterId != bucketId, + PublicAvailability: types.NewU32(clusterId) != bucketId, GasConsumptionCap: math.MaxUint32, }, Params: bucketParams, WriterIds: writerIds, - RentCoveredUntilMs: uint64(time.Now().UnixMilli() + time.Hour.Milliseconds()), + RentCoveredUntilMs: types.U64(time.Now().UnixMilli() + time.Hour.Milliseconds()), } } @@ -241,3 +255,248 @@ func getAccountIDs(ss58Addresses []string) []types.AccountID { func (d *ddcBucketContractMock) GetEventDispatcher() map[types.Hash]pkg.ContractEventDispatchEntry { return nil } + +func (d *ddcBucketContractMock) ClusterCreate(ctx context.Context, keyPair signature.KeyringPair, params bucket.Params, resourcePerVNode bucket.Resource) (blockHash types.Hash, err error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterAddNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, vNodes [][]bucket.Token) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterRemoveNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterResetNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, vNodes [][]bucket.Token) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterReplaceNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, vNodes [][]bucket.Token, newNodeKey bucket.NodeKey) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterAddCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterRemoveCdnNode(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterSetParams(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, params bucket.Params) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterRemove(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterSetNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, nodeKey bucket.NodeKey, statusInCluster string) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterSetCdnNodeStatus(ctx context.Context, keyPair signature.KeyringPair, clusterId bucket.ClusterId, cdnNodeKey bucket.CdnNodeKey, statusInCluster string) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) ClusterList(offset types.U32, limit types.U32, filterManagerId types.OptionAccountID) (*bucket.ClusterListInfo, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) NodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, params bucket.Params, capacity bucket.Resource, rent bucket.Rent) (blockHash types.Hash, err error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) NodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) NodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, params bucket.Params) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) NodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*bucket.NodeListInfo, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) CdnNodeCreate(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey, params bucket.CDNNodeParams) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) CdnNodeRemove(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) CdnNodeSetParams(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.CdnNodeKey, params bucket.CDNNodeParams) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) CdnNodeList(offset types.U32, limit types.U32, filterProviderId types.OptionAccountID) (*bucket.CdnNodeListInfo, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) HasPermission(account bucket.AccountId, permission string) (bool, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) GrantTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) RevokeTrustedManagerPermission(ctx context.Context, keyPair signature.KeyringPair, managerId bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AdminGrantPermission(ctx context.Context, keyPair signature.KeyringPair, grantee bucket.AccountId, permission string) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AdminRevokePermission(ctx context.Context, keyPair signature.KeyringPair, grantee bucket.AccountId, permission string) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AdminTransferNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, nodeKey bucket.NodeKey, newOwner bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AdminTransferCdnNodeOwnership(ctx context.Context, keyPair signature.KeyringPair, cdnNodeKey bucket.CdnNodeKey, newOwner bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AccountDeposit(ctx context.Context, keyPair signature.KeyringPair) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AccountBond(ctx context.Context, keyPair signature.KeyringPair, balance bucket.Balance) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AccountUnbond(ctx context.Context, keyPair signature.KeyringPair, bondAmount bucket.Balance) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AccountGetUsdPerCere() (bucket.Balance, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AccountSetUsdPerCere(ctx context.Context, keyPair signature.KeyringPair, balance bucket.Balance) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) AccountWithdrawUnbonded(ctx context.Context, keyPair signature.KeyringPair) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) GetAccounts() ([]bucket.AccountId, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketCreate(ctx context.Context, keyPair signature.KeyringPair, bucketParams bucket.BucketParams, clusterId bucket.ClusterId, ownerId types.OptionAccountID) (blockHash types.Hash, err error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketChangeOwner(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, ownerId bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketAllocIntoCluster(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, resource bucket.Resource) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketSettlePayment(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketChangeParams(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, bucketParams bucket.BucketParams) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketList(offset types.U32, limit types.U32, filterOnwerId types.OptionAccountID) (*bucket.BucketListInfo, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketListForAccount(ownerId bucket.AccountId) ([]bucket.Bucket, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketSetAvailability(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, publicAvailability bool) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketSetResourceCap(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, newResourceCap bucket.Resource) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) GetBucketWriters(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) ([]bucket.AccountId, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) GetBucketReaders(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId) ([]bucket.AccountId, error) { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketSetWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, writer bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketRevokeWriterPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, writer bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketSetReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, reader bucket.AccountId) error { + //TODO implement me + panic("implement me") +} + +func (d *ddcBucketContractMock) BucketRevokeReaderPerm(ctx context.Context, keyPair signature.KeyringPair, bucketId bucket.BucketId, reader bucket.AccountId) error { + //TODO implement me + panic("implement me") +} diff --git a/contract/pkg/utils.go b/contract/pkg/utils.go index ff544a5..5238c75 100644 --- a/contract/pkg/utils.go +++ b/contract/pkg/utils.go @@ -4,11 +4,12 @@ import ( "bytes" "errors" "fmt" + "strings" + "github.com/centrifuge/go-substrate-rpc-client/v4/scale" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/decred/base58" "golang.org/x/crypto/blake2b" - "strings" ) const addressLength = 32 + 1 + 2 diff --git a/core/pkg/crypto/ed25519.go b/core/pkg/crypto/ed25519.go index e01bdce..b6321e6 100644 --- a/core/pkg/crypto/ed25519.go +++ b/core/pkg/crypto/ed25519.go @@ -57,6 +57,10 @@ func (e *ed25519Scheme) Address() (string, error) { return subkey.SS58Address(e.publicKey, 42) } +func (e *ed25519Scheme) AddressForNetwork(network uint8) (string, error) { + return subkey.SS58Address(e.publicKey, network) +} + func (e *ed25519Scheme) PublicKeyHex() string { return fmt.Sprintf("0x%s", hex.EncodeToString(e.publicKey)) } diff --git a/core/pkg/crypto/ed25519_test.go b/core/pkg/crypto/ed25519_test.go index 44846d1..40bc1b4 100644 --- a/core/pkg/crypto/ed25519_test.go +++ b/core/pkg/crypto/ed25519_test.go @@ -91,6 +91,12 @@ func TestAddressEd25519Scheme(t *testing.T) { assert.Equal(t, address, addr) } +func TestAddressForCereNetworkEd25519Scheme(t *testing.T) { + addr, err := testEd25519Scheme.AddressForNetwork(54) + assert.NoError(t, err) + assert.Equal(t, addressForCereNetwork, addr) +} + func TestPublicKeyHexEd25519Scheme(t *testing.T) { keyHex := testEd25519Scheme.PublicKeyHex() assert.Equal(t, pubKeyHex, keyHex) diff --git a/core/pkg/crypto/scheme.go b/core/pkg/crypto/scheme.go index 5bc8003..8faed31 100644 --- a/core/pkg/crypto/scheme.go +++ b/core/pkg/crypto/scheme.go @@ -16,6 +16,7 @@ type ( Name() string PublicKey() []byte Address() (string, error) + AddressForNetwork(network uint8) (string, error) PublicKeyHex() string } ) diff --git a/core/pkg/crypto/scheme_test.go b/core/pkg/crypto/scheme_test.go index 31c0a91..3992edc 100644 --- a/core/pkg/crypto/scheme_test.go +++ b/core/pkg/crypto/scheme_test.go @@ -8,9 +8,10 @@ import ( ) const ( - content = "Hello world!" - address = "5FJDBC3jJbWX48PyfpRCo7pKsFwSy4Mzj5t39PfXixD5jMgy" - pubKeyHex = "0x8f01969eb5244d853cc9c6ad73c46d8a1a091842c414cabd2377531f0832635f" + content = "Hello world!" + address = "5FJDBC3jJbWX48PyfpRCo7pKsFwSy4Mzj5t39PfXixD5jMgy" + addressForCereNetwork = "6Sk8H6YZv61EvqFYYCyVKw1Rd5eydFvEzNXcXbP9HDLw7E4W" + pubKeyHex = "0x8f01969eb5244d853cc9c6ad73c46d8a1a091842c414cabd2377531f0832635f" ) func TestCreateScheme(t *testing.T) { diff --git a/core/pkg/crypto/secp256k1.go b/core/pkg/crypto/secp256k1.go index e5ec51f..d28a48c 100644 --- a/core/pkg/crypto/secp256k1.go +++ b/core/pkg/crypto/secp256k1.go @@ -18,6 +18,10 @@ func (s *secp256k1Scheme) Address() (string, error) { return subkey.SS58Address(s.publicKey, 42) } +func (s *secp256k1Scheme) AddressForNetwork(network uint8) (string, error) { + return subkey.SS58Address(s.publicKey, network) +} + func (s *secp256k1Scheme) PublicKeyHex() string { return fmt.Sprintf("0x%s", hex.EncodeToString(s.publicKey)) } diff --git a/core/pkg/crypto/secp256k1_test.go b/core/pkg/crypto/secp256k1_test.go index 0252ada..dee1b6f 100644 --- a/core/pkg/crypto/secp256k1_test.go +++ b/core/pkg/crypto/secp256k1_test.go @@ -66,6 +66,12 @@ func TestSecp256k1_Address(t *testing.T) { assert.Equal(t, expAddress, address) } +func TestSecp256k1_AddressForCereNetwork(t *testing.T) { + address, err := testEd25519Scheme.AddressForNetwork(54) + assert.NoError(t, err) + assert.Equal(t, addressForCereNetwork, address) +} + func TestSecp256k1_PublicKeyHex(t *testing.T) { publicKeyHex := testEd25519Scheme.PublicKeyHex() assert.Equal(t, publicKeyHex, pubKeyHex) diff --git a/core/pkg/crypto/sr25519.go b/core/pkg/crypto/sr25519.go index 7c538d4..2f86f62 100644 --- a/core/pkg/crypto/sr25519.go +++ b/core/pkg/crypto/sr25519.go @@ -59,6 +59,10 @@ func (s *sr25519Scheme) Address() (string, error) { return subkey.SS58Address(s.publicKey, 42) } +func (s *sr25519Scheme) AddressForNetwork(network uint8) (string, error) { + return subkey.SS58Address(s.publicKey, network) +} + func (s *sr25519Scheme) PublicKeyHex() string { return fmt.Sprintf("0x%s", hex.EncodeToString(s.publicKey)) } diff --git a/core/pkg/crypto/sr25519_test.go b/core/pkg/crypto/sr25519_test.go index 697fe8b..3008094 100644 --- a/core/pkg/crypto/sr25519_test.go +++ b/core/pkg/crypto/sr25519_test.go @@ -10,9 +10,11 @@ import ( ) const ( - privKeySr25519 = "6e40d467e86ec447ae0088c81072feff8c860eebcff7dc44017b1b15746cce0d" - pubKeyHexSr25519 = "0xc8393bc5fd86bccda163187c8c23cba9d63622a745ed59fedc51d51210d1884f" - signatureSr25519 = "ba4a02f174694ee29a6a38b4ad2c16ff59f590da38694b556299197d1b352f464db889d93d1e3d86b068522aabb3585f50c129e1565a48b653336014a5fe158f" + privKeySr25519 = "6e40d467e86ec447ae0088c81072feff8c860eebcff7dc44017b1b15746cce0d" + pubKeyHexSr25519 = "0xc8393bc5fd86bccda163187c8c23cba9d63622a745ed59fedc51d51210d1884f" + signatureSr25519 = "ba4a02f174694ee29a6a38b4ad2c16ff59f590da38694b556299197d1b352f464db889d93d1e3d86b068522aabb3585f50c129e1565a48b653336014a5fe158f" + addressSr25519 = "5GbESExKAqUSer8YHHRpze6XDGjRaC2dpS7E44vMiXmEHoSe" + addressForCereNetworkSr25519 = "6U39Y9T9nKyAXYz79fz7XTHcy6SxEPat5ikoSGdyGnu5fd9V" ) var ( @@ -70,7 +72,13 @@ func TestSignSr25519(t *testing.T) { func TestAddressSr25519(t *testing.T) { address, err := testSr25519Scheme.Address() assert.NoError(t, err) - assert.Equal(t, address, address) + assert.Equal(t, addressSr25519, address) +} + +func TestAddressForCereNetworkSr25519(t *testing.T) { + address, err := testSr25519Scheme.AddressForNetwork(54) + assert.NoError(t, err) + assert.Equal(t, address, addressForCereNetworkSr25519) } func TestPublicKeyHexSr25519(t *testing.T) { diff --git a/core/pkg/topology/sync/topology.go b/core/pkg/topology/sync/topology.go index 1f19fe5..8ca7406 100644 --- a/core/pkg/topology/sync/topology.go +++ b/core/pkg/topology/sync/topology.go @@ -1,8 +1,9 @@ package sync import ( - "github.com/cerebellum-network/cere-ddc-sdk-go/core/pkg/topology" "sync" + + "github.com/cerebellum-network/cere-ddc-sdk-go/core/pkg/topology" ) type ring struct { @@ -10,15 +11,15 @@ type ring struct { mutex sync.RWMutex } -func NewTopology(nodeIds []uint32, vNodes [][]uint64, replicaFactor uint) topology.Ring { +func NewTopology(nodes topology.NodesVNodes, replicaFactor uint) topology.Ring { return &ring{ - ring: topology.NewTopology(nodeIds, vNodes, replicaFactor), + ring: topology.NewTopology(nodes, replicaFactor), } } -func (r *ring) Tokens(nodeId uint32) []uint64 { +func (r *ring) Tokens(nodeKey string) []uint64 { r.mutex.RLock() - result := r.ring.Tokens(nodeId) + result := r.ring.Tokens(nodeKey) r.mutex.RUnlock() return result @@ -40,17 +41,17 @@ func (r *ring) Replicas(token uint64) []topology.VNode { return result } -func (r *ring) Partitions(nodeId uint32) []topology.Partition { +func (r *ring) Partitions(nodeKey string) []topology.Partition { r.mutex.RLock() - result := r.ring.Partitions(nodeId) + result := r.ring.Partitions(nodeKey) r.mutex.RUnlock() return result } -func (r *ring) ExcessPartitions(nodeId uint32) []topology.Partition { +func (r *ring) ExcessPartitions(nodeKey string) []topology.Partition { r.mutex.RLock() - result := r.ring.ExcessPartitions(nodeId) + result := r.ring.ExcessPartitions(nodeKey) r.mutex.RUnlock() return result diff --git a/core/pkg/topology/topology.go b/core/pkg/topology/topology.go index 9c97bb3..c05e49a 100644 --- a/core/pkg/topology/topology.go +++ b/core/pkg/topology/topology.go @@ -1,18 +1,19 @@ package topology import ( - "github.com/cerebellum-network/cere-ddc-sdk-go/core/pkg/utils" "sort" + + "github.com/cerebellum-network/cere-ddc-sdk-go/core/pkg/utils" ) type ( Ring interface { - Tokens(nodeId uint32) []uint64 + Tokens(nodeKey string) []uint64 Neighbours(token uint64) (VNode, VNode) Replicas(token uint64) []VNode - Partitions(nodeId uint32) []Partition - ExcessPartitions(nodeId uint32) []Partition + Partitions(nodeKey string) []Partition + ExcessPartitions(nodeKey string) []Partition RemoveVNode(token uint64) bool @@ -26,17 +27,26 @@ type ( } ) -func NewTopology(nodeIds []uint32, vNodes [][]uint64, replicaFactor uint) Ring { +type ( + NodeVNodes struct { + NodeKey string + VNodes []uint64 + } + + NodesVNodes = []NodeVNodes +) + +func NewTopology(nodes NodesVNodes, replicaFactor uint) Ring { if replicaFactor == 0 { replicaFactor = 1 } topologyVNodes := make([]VNode, 0) - for i, nodeId := range nodeIds { - for _, token := range vNodes[i] { + for _, node := range nodes { + for _, token := range node.VNodes { topologyVNode := VNode{ - nodeId: nodeId, - token: token, + nodeKey: node.NodeKey, + token: token, } topologyVNodes = append(topologyVNodes, topologyVNode) @@ -53,10 +63,10 @@ func NewTopology(nodeIds []uint32, vNodes [][]uint64, replicaFactor uint) Ring { } } -func (r *ring) Tokens(nodeId uint32) []uint64 { +func (r *ring) Tokens(nodeKey string) []uint64 { result := make([]uint64, 0) - r.vNodeDo(nodeId, func(i int, vNode VNode) { + r.vNodeDo(nodeKey, func(i int, vNode VNode) { result = append(result, vNode.token) }) @@ -90,9 +100,9 @@ func (r *ring) Neighbours(token uint64) (prev VNode, next VNode) { return } -func (r *ring) Partitions(nodeId uint32) []Partition { +func (r *ring) Partitions(nodeKey string) []Partition { result := make([]Partition, 0) - r.vNodeDo(nodeId, func(i int, vNode VNode) { + r.vNodeDo(nodeKey, func(i int, vNode VNode) { for j := uint(1); j < r.replicationFactor; j++ { i = r.prevIndex(i) } @@ -108,8 +118,8 @@ func (r *ring) Partitions(nodeId uint32) []Partition { return result } -func (r *ring) ExcessPartitions(nodeId uint32) []Partition { - partitions := r.Partitions(nodeId) +func (r *ring) ExcessPartitions(nodeKey string) []Partition { + partitions := r.Partitions(nodeKey) result := make([]Partition, 0) for i := 0; i < len(partitions); i++ { @@ -155,9 +165,9 @@ func (r *ring) nextIndex(i int) int { return nextIndex(i, len(r.vNodes)) } -func (r *ring) vNodeDo(nodeId uint32, do func(int, VNode)) { +func (r *ring) vNodeDo(nodeKey string, do func(int, VNode)) { for i, vNode := range r.vNodes { - if nodeId == vNode.nodeId { + if nodeKey == vNode.nodeKey { do(i, vNode) } } diff --git a/core/pkg/topology/topology_test.go b/core/pkg/topology/topology_test.go index 35850b2..a75fef4 100644 --- a/core/pkg/topology/topology_test.go +++ b/core/pkg/topology/topology_test.go @@ -1,38 +1,127 @@ package topology import ( - "github.com/stretchr/testify/assert" "sort" "testing" + + "github.com/stretchr/testify/assert" ) +var NodeKey1 = "e5be9a5092b81bca64be81d212e7f2f9eba183bb7a90954f7b76361f6edb5c0a" +var NodeKey2 = "8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48" +var NodeKey3 = "90b5ab205c6974c9ea841be688864633dc9ca8a357843eeacf2314649965fe22" +var NodeKey4 = "306721211d5404bd9da88e0204360a1a9ab8b87c66c1bc2fcdd37f3c2222cc20" +var NodeKey5 = "e659a7a1628cdd93febc04a4e0646ea20e9f5f0ce097d9a05290d4a9e054df4e" +var NodeKey6 = "1cbd2d43530a44705ad088af313e18f80b53ef16b36177cd4b77b846f2a5f07c" +var NodeKey7 = "be5ddb1579b72e84524fc29e78609e3caf42e85aa118ebfe0b0ad404b5bdd25f" + var clusters = []struct { name string - nodeIds []uint32 - vNodes [][]uint64 + nodesVNodes NodesVNodes replicaFactor uint }{ - {"size 2 replication 3", []uint32{1, 2}, [][]uint64{{9223372036854775806, 3074457345618258602, 15372286728091293010}, {12297829382473034408, 6148914691236517204, 18446744073709551612}}, 2}, - {"size 3 replication 3", []uint32{1, 2, 3}, [][]uint64{{12297829382473034408, 3074457345618258602}, {6148914691236517204, 15372286728091293010}, {18446744073709551612, 9223372036854775806}}, 3}, - {"size 4 replication 3", []uint32{1, 2, 3, 4}, [][]uint64{{12297829382473034408, 3074457345618258602}, {6148914691236517204, 15372286728091293010}, {18446744073709551612, 9223372036854775806}, {4611686018427387903}}, 3}, - {"size 2 replication 1", []uint32{1, 2}, [][]uint64{{9223372036854775806, 3074457345618258602, 15372286728091293010}, {12297829382473034408, 6148914691236517204, 18446744073709551612}}, 1}, - {"size 3 replication 1", []uint32{1, 2, 3}, [][]uint64{{12297829382473034408, 3074457345618258602}, {6148914691236517204, 15372286728091293010}, {18446744073709551612, 9223372036854775806}}, 1}, + { + "size 2 replication 3", + NodesVNodes{ + NodeVNodes{ + NodeKey: NodeKey1, + VNodes: []uint64{9223372036854775806, 3074457345618258602, 15372286728091293010}, + }, + NodeVNodes{ + NodeKey: NodeKey2, + VNodes: []uint64{12297829382473034408, 6148914691236517204, 18446744073709551612}, + }, + }, + 2, + }, + { + "size 3 replication 3", + NodesVNodes{ + NodeVNodes{ + NodeKey: NodeKey1, + VNodes: []uint64{12297829382473034408, 3074457345618258602}, + }, + NodeVNodes{ + NodeKey: NodeKey2, + VNodes: []uint64{6148914691236517204, 15372286728091293010}, + }, + NodeVNodes{ + NodeKey: NodeKey3, + VNodes: []uint64{18446744073709551612, 9223372036854775806}, + }, + }, + 3, + }, + { + "size 4 replication 3", + NodesVNodes{ + NodeVNodes{ + NodeKey: NodeKey1, + VNodes: []uint64{12297829382473034408, 3074457345618258602}, + }, + NodeVNodes{ + NodeKey: NodeKey2, + VNodes: []uint64{6148914691236517204, 15372286728091293010}, + }, + NodeVNodes{ + NodeKey: NodeKey3, + VNodes: []uint64{18446744073709551612, 9223372036854775806}, + }, + NodeVNodes{ + NodeKey: NodeKey4, + VNodes: []uint64{4611686018427387903}, + }, + }, + 3, + }, + { + "size 2 replication 1", + NodesVNodes{ + NodeVNodes{ + NodeKey: NodeKey1, + VNodes: []uint64{9223372036854775806, 3074457345618258602, 15372286728091293010}, + }, + NodeVNodes{ + NodeKey: NodeKey2, + VNodes: []uint64{12297829382473034408, 6148914691236517204, 18446744073709551612}, + }, + }, + 1, + }, + { + "size 3 replication 1", + NodesVNodes{ + NodeVNodes{ + NodeKey: NodeKey1, + VNodes: []uint64{12297829382473034408, 3074457345618258602}, + }, + NodeVNodes{ + NodeKey: NodeKey2, + VNodes: []uint64{6148914691236517204, 15372286728091293010}, + }, + NodeVNodes{ + NodeKey: NodeKey3, + VNodes: []uint64{18446744073709551612, 9223372036854775806}, + }, + }, + 1, + }, } func TestTokens(t *testing.T) { for _, test := range clusters { t.Run(test.name, func(t *testing.T) { //given - testSubject := NewTopology(test.nodeIds, test.vNodes, test.replicaFactor) + testSubject := NewTopology(test.nodesVNodes, test.replicaFactor) - for i, nodeId := range test.nodeIds { + for _, node := range test.nodesVNodes { //when - tokens := testSubject.Tokens(nodeId) + tokens := testSubject.Tokens(node.NodeKey) //then assert.True(t, sort.SliceIsSorted(tokens, func(i, j int) bool { return tokens[i] < tokens[j] })) - expected := test.vNodes[i] + expected := node.VNodes assert.Len(t, tokens, len(expected)) for _, value := range expected { assert.Contains(t, tokens, value) @@ -49,19 +138,19 @@ func TestNeighbours(t *testing.T) { prev VNode next VNode }{ - {0, 3074457345618258602, VNode{2, 18446744073709551612}, VNode{2, 6148914691236517204}}, - {0, 3074457345618258602 + 100, VNode{1, 3074457345618258602}, VNode{2, 6148914691236517204}}, - {0, 18446744073709551612, VNode{1, 15372286728091293010}, VNode{1, 3074457345618258602}}, - {0, 18446744073709551612 + 1, VNode{2, 18446744073709551612}, VNode{1, 3074457345618258602}}, - {1, 6148914691236517204, VNode{1, 3074457345618258602}, VNode{3, 9223372036854775806}}, - {1, 6148914691236517204 + 100, VNode{2, 6148914691236517204}, VNode{3, 9223372036854775806}}, + {0, 3074457345618258602, VNode{NodeKey2, 18446744073709551612}, VNode{NodeKey2, 6148914691236517204}}, + {0, 3074457345618258602 + 100, VNode{NodeKey1, 3074457345618258602}, VNode{NodeKey2, 6148914691236517204}}, + {0, 18446744073709551612, VNode{NodeKey1, 15372286728091293010}, VNode{NodeKey1, 3074457345618258602}}, + {0, 18446744073709551612 + 1, VNode{NodeKey2, 18446744073709551612}, VNode{NodeKey1, 3074457345618258602}}, + {1, 6148914691236517204, VNode{NodeKey1, 3074457345618258602}, VNode{NodeKey3, 9223372036854775806}}, + {1, 6148914691236517204 + 100, VNode{NodeKey2, 6148914691236517204}, VNode{NodeKey3, 9223372036854775806}}, } for _, test := range tests { cluster := clusters[test.clusterId] t.Run(cluster.name, func(t *testing.T) { //given - testSubject := NewTopology(cluster.nodeIds, cluster.vNodes, cluster.replicaFactor) + testSubject := NewTopology(cluster.nodesVNodes, cluster.replicaFactor) //when prev, next := testSubject.Neighbours(test.token) @@ -80,21 +169,21 @@ func TestReplicas(t *testing.T) { token uint64 replicas []VNode }{ - {0, 3074457345618258602, []VNode{{1, 3074457345618258602}, {2, 6148914691236517204}}}, - {0, 3074457345618258602 + 100, []VNode{{1, 3074457345618258602}, {2, 6148914691236517204}}}, - {0, 18446744073709551612, []VNode{{2, 18446744073709551612}, {1, 3074457345618258602}}}, - {0, 18446744073709551612 + 1, []VNode{{2, 18446744073709551612}, {1, 3074457345618258602}}}, - {1, 6148914691236517204, []VNode{{2, 6148914691236517204}, {3, 9223372036854775806}, {1, 12297829382473034408}}}, - {1, 6148914691236517204 + 10, []VNode{{2, 6148914691236517204}, {3, 9223372036854775806}, {1, 12297829382473034408}}}, - {2, 6980919141067302587, []VNode{{2, 6148914691236517204}, {3, 9223372036854775806}, {1, 12297829382473034408}}}, - {2, 7577601381952616217, []VNode{{2, 6148914691236517204}, {3, 9223372036854775806}, {1, 12297829382473034408}}}, + {0, 3074457345618258602, []VNode{{NodeKey1, 3074457345618258602}, {NodeKey2, 6148914691236517204}}}, + {0, 3074457345618258602 + 100, []VNode{{NodeKey1, 3074457345618258602}, {NodeKey2, 6148914691236517204}}}, + {0, 18446744073709551612, []VNode{{NodeKey2, 18446744073709551612}, {NodeKey1, 3074457345618258602}}}, + {0, 18446744073709551612 + 1, []VNode{{NodeKey2, 18446744073709551612}, {NodeKey1, 3074457345618258602}}}, + {1, 6148914691236517204, []VNode{{NodeKey2, 6148914691236517204}, {NodeKey3, 9223372036854775806}, {NodeKey1, 12297829382473034408}}}, + {1, 6148914691236517204 + 10, []VNode{{NodeKey2, 6148914691236517204}, {NodeKey3, 9223372036854775806}, {NodeKey1, 12297829382473034408}}}, + {2, 6980919141067302587, []VNode{{NodeKey2, 6148914691236517204}, {NodeKey3, 9223372036854775806}, {NodeKey1, 12297829382473034408}}}, + {2, 7577601381952616217, []VNode{{NodeKey2, 6148914691236517204}, {NodeKey3, 9223372036854775806}, {NodeKey1, 12297829382473034408}}}, } for _, test := range tests { cluster := clusters[test.clusterId] t.Run(cluster.name, func(t *testing.T) { //given - testSubject := NewTopology(cluster.nodeIds, cluster.vNodes, cluster.replicaFactor) + testSubject := NewTopology(cluster.nodesVNodes, cluster.replicaFactor) //when replicas := testSubject.Replicas(test.token) @@ -111,66 +200,66 @@ func TestReplicas(t *testing.T) { func TestPartitions(t *testing.T) { tests := []struct { clusterId int - nodeId uint32 + nodeKey string partitions []Partition }{ - {3, 1, + {3, NodeKey1, []Partition{ - {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeId: 1, token: 3074457345618258602}}}, - {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeId: 1, token: 9223372036854775806}}}, - {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeId: 1, token: 15372286728091293010}}}, + {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 3074457345618258602}}}, + {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 9223372036854775806}}}, + {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 15372286728091293010}}}, }, }, - {3, 2, + {3, NodeKey2, []Partition{ - {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeId: 2, token: 6148914691236517204}}}, - {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeId: 2, token: 12297829382473034408}}}, - {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeId: 2, token: 18446744073709551612}}}, + {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 6148914691236517204}}}, + {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 12297829382473034408}}}, + {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 18446744073709551612}}}, }, }, - {4, 1, + {4, NodeKey1, []Partition{ - {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeId: 1, token: 3074457345618258602}}}, - {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeId: 1, token: 12297829382473034408}}}, + {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 3074457345618258602}}}, + {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 12297829382473034408}}}, }, }, - {4, 2, + {4, NodeKey2, []Partition{ - {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeId: 2, token: 6148914691236517204}}}, - {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeId: 2, token: 15372286728091293010}}}, + {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 6148914691236517204}}}, + {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 15372286728091293010}}}, }, }, - {4, 3, + {4, NodeKey3, []Partition{ - {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeId: 3, token: 9223372036854775806}}}, - {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeId: 3, token: 18446744073709551612}}}, + {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeKey: NodeKey3, token: 9223372036854775806}}}, + {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeKey: NodeKey3, token: 18446744073709551612}}}, }, }, - {0, 1, + {0, NodeKey1, []Partition{ - {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeId: 2, token: 18446744073709551612}, {nodeId: 1, token: 3074457345618258602}}}, - {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeId: 1, token: 3074457345618258602}, {nodeId: 2, token: 6148914691236517204}}}, - {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeId: 2, token: 6148914691236517204}, {nodeId: 1, token: 9223372036854775806}}}, - {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeId: 1, token: 9223372036854775806}, {nodeId: 2, token: 12297829382473034408}}}, - {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeId: 2, token: 12297829382473034408}, {nodeId: 1, token: 15372286728091293010}}}, - {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeId: 1, token: 15372286728091293010}, {nodeId: 2, token: 18446744073709551612}}}, + {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 18446744073709551612}, {nodeKey: NodeKey1, token: 3074457345618258602}}}, + {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 3074457345618258602}, {nodeKey: NodeKey2, token: 6148914691236517204}}}, + {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 6148914691236517204}, {nodeKey: NodeKey1, token: 9223372036854775806}}}, + {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 9223372036854775806}, {nodeKey: NodeKey2, token: 12297829382473034408}}}, + {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 12297829382473034408}, {nodeKey: NodeKey1, token: 15372286728091293010}}}, + {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 15372286728091293010}, {nodeKey: NodeKey2, token: 18446744073709551612}}}, }, }, - {0, 2, + {0, NodeKey2, []Partition{ - {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeId: 1, token: 3074457345618258602}, {nodeId: 2, token: 6148914691236517204}}}, - {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeId: 2, token: 6148914691236517204}, {nodeId: 1, token: 9223372036854775806}}}, - {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeId: 1, token: 9223372036854775806}, {nodeId: 2, token: 12297829382473034408}}}, - {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeId: 2, token: 12297829382473034408}, {nodeId: 1, token: 15372286728091293010}}}, - {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeId: 1, token: 15372286728091293010}, {nodeId: 2, token: 18446744073709551612}}}, - {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeId: 2, token: 18446744073709551612}, {nodeId: 1, token: 3074457345618258602}}}, + {From: 3074457345618258602, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 3074457345618258602}, {nodeKey: NodeKey2, token: 6148914691236517204}}}, + {From: 6148914691236517204, To: 9223372036854775806 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 6148914691236517204}, {nodeKey: NodeKey1, token: 9223372036854775806}}}, + {From: 9223372036854775806, To: 12297829382473034408 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 9223372036854775806}, {nodeKey: NodeKey2, token: 12297829382473034408}}}, + {From: 12297829382473034408, To: 15372286728091293010 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 12297829382473034408}, {nodeKey: NodeKey1, token: 15372286728091293010}}}, + {From: 15372286728091293010, To: 18446744073709551612 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 15372286728091293010}, {nodeKey: NodeKey2, token: 18446744073709551612}}}, + {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeKey: NodeKey2, token: 18446744073709551612}, {nodeKey: NodeKey1, token: 3074457345618258602}}}, }, }, - {2, 4, + {2, NodeKey4, []Partition{ - {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeId: 3, token: 18446744073709551612}, {nodeId: 1, token: 3074457345618258602}, {nodeId: 4, token: 4611686018427387903}}}, - {From: 3074457345618258602, To: 4611686018427387903 - 1, VNodes: []VNode{{nodeId: 1, token: 3074457345618258602}, {nodeId: 4, token: 4611686018427387903}, {nodeId: 2, token: 6148914691236517204}}}, - {From: 4611686018427387903, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeId: 4, token: 4611686018427387903}, {nodeId: 2, token: 6148914691236517204}, {nodeId: 3, token: 9223372036854775806}}}, + {From: 18446744073709551612, To: 3074457345618258602 - 1, VNodes: []VNode{{nodeKey: NodeKey3, token: 18446744073709551612}, {nodeKey: NodeKey1, token: 3074457345618258602}, {nodeKey: NodeKey4, token: 4611686018427387903}}}, + {From: 3074457345618258602, To: 4611686018427387903 - 1, VNodes: []VNode{{nodeKey: NodeKey1, token: 3074457345618258602}, {nodeKey: NodeKey4, token: 4611686018427387903}, {nodeKey: NodeKey2, token: 6148914691236517204}}}, + {From: 4611686018427387903, To: 6148914691236517204 - 1, VNodes: []VNode{{nodeKey: NodeKey4, token: 4611686018427387903}, {nodeKey: NodeKey2, token: 6148914691236517204}, {nodeKey: NodeKey3, token: 9223372036854775806}}}, }, }, } @@ -179,10 +268,10 @@ func TestPartitions(t *testing.T) { cluster := clusters[test.clusterId] t.Run(cluster.name, func(t *testing.T) { //given - testSubject := NewTopology(cluster.nodeIds, cluster.vNodes, cluster.replicaFactor) + testSubject := NewTopology(cluster.nodesVNodes, cluster.replicaFactor) //when - partitions := testSubject.Partitions(test.nodeId) + partitions := testSubject.Partitions(test.nodeKey) //then assert.Len(t, partitions, len(test.partitions)) @@ -196,28 +285,28 @@ func TestPartitions(t *testing.T) { func TestExcessPartitions(t *testing.T) { tests := []struct { clusterId int - nodeId uint32 + nodeKey string excessPartitions []Partition }{ - {3, 1, []Partition{{From: 6148914691236517204, To: 9223372036854775806 - 1}, {From: 12297829382473034408, To: 15372286728091293010 - 1}, {From: 18446744073709551612, To: 3074457345618258602 - 1}}}, - {3, 2, []Partition{{From: 9223372036854775806, To: 12297829382473034408 - 1}, {From: 15372286728091293010, To: 18446744073709551612 - 1}, {From: 3074457345618258602, To: 6148914691236517204 - 1}}}, - {4, 1, []Partition{{From: 6148914691236517204, To: 12297829382473034408 - 1}, {From: 15372286728091293010, To: 3074457345618258602 - 1}}}, - {4, 2, []Partition{{From: 9223372036854775806, To: 15372286728091293010 - 1}, {From: 18446744073709551612, To: 6148914691236517204 - 1}}}, - {4, 3, []Partition{{From: 12297829382473034408, To: 18446744073709551612 - 1}, {From: 3074457345618258602, To: 9223372036854775806 - 1}}}, - {0, 1, []Partition{}}, - {0, 2, []Partition{}}, - {0, 3, []Partition{}}, - {2, 4, []Partition{{From: 6148914691236517204, To: 18446744073709551612 - 1}}}, + {3, NodeKey1, []Partition{{From: 6148914691236517204, To: 9223372036854775806 - 1}, {From: 12297829382473034408, To: 15372286728091293010 - 1}, {From: 18446744073709551612, To: 3074457345618258602 - 1}}}, + {3, NodeKey2, []Partition{{From: 9223372036854775806, To: 12297829382473034408 - 1}, {From: 15372286728091293010, To: 18446744073709551612 - 1}, {From: 3074457345618258602, To: 6148914691236517204 - 1}}}, + {4, NodeKey1, []Partition{{From: 6148914691236517204, To: 12297829382473034408 - 1}, {From: 15372286728091293010, To: 3074457345618258602 - 1}}}, + {4, NodeKey2, []Partition{{From: 9223372036854775806, To: 15372286728091293010 - 1}, {From: 18446744073709551612, To: 6148914691236517204 - 1}}}, + {4, NodeKey3, []Partition{{From: 12297829382473034408, To: 18446744073709551612 - 1}, {From: 3074457345618258602, To: 9223372036854775806 - 1}}}, + {0, NodeKey1, []Partition{}}, + {0, NodeKey2, []Partition{}}, + {0, NodeKey3, []Partition{}}, + {2, NodeKey4, []Partition{{From: 6148914691236517204, To: 18446744073709551612 - 1}}}, } for _, test := range tests { cluster := clusters[test.clusterId] t.Run(cluster.name, func(t *testing.T) { //given - testSubject := NewTopology(cluster.nodeIds, cluster.vNodes, cluster.replicaFactor) + testSubject := NewTopology(cluster.nodesVNodes, cluster.replicaFactor) //when - partitions := testSubject.ExcessPartitions(test.nodeId) + partitions := testSubject.ExcessPartitions(test.nodeKey) //then assert.Len(t, partitions, len(test.excessPartitions)) @@ -236,15 +325,15 @@ func TestRemoveVNode(t *testing.T) { expectIsRemoved bool expected []VNode }{ - {0, 100, false, []VNode{{token: 3074457345618258602, nodeId: 1}, {token: 6148914691236517204, nodeId: 2}, {token: 9223372036854775806, nodeId: 1}, {token: 12297829382473034408, nodeId: 2}, {token: 15372286728091293010, nodeId: 1}, {token: 18446744073709551612, nodeId: 2}}}, - {0, 9223372036854775806, true, []VNode{{token: 3074457345618258602, nodeId: 1}, {token: 6148914691236517204, nodeId: 2}, {token: 12297829382473034408, nodeId: 2}, {token: 15372286728091293010, nodeId: 1}, {token: 18446744073709551612, nodeId: 2}}}, - {0, 12297829382473034408, true, []VNode{{token: 3074457345618258602, nodeId: 1}, {token: 6148914691236517204, nodeId: 2}, {token: 9223372036854775806, nodeId: 1}, {token: 15372286728091293010, nodeId: 1}, {token: 18446744073709551612, nodeId: 2}}}, + {0, 100, false, []VNode{{token: 3074457345618258602, nodeKey: NodeKey1}, {token: 6148914691236517204, nodeKey: NodeKey2}, {token: 9223372036854775806, nodeKey: NodeKey1}, {token: 12297829382473034408, nodeKey: NodeKey2}, {token: 15372286728091293010, nodeKey: NodeKey1}, {token: 18446744073709551612, nodeKey: NodeKey2}}}, + {0, 9223372036854775806, true, []VNode{{token: 3074457345618258602, nodeKey: NodeKey1}, {token: 6148914691236517204, nodeKey: NodeKey2}, {token: 12297829382473034408, nodeKey: NodeKey2}, {token: 15372286728091293010, nodeKey: NodeKey1}, {token: 18446744073709551612, nodeKey: NodeKey2}}}, + {0, 12297829382473034408, true, []VNode{{token: 3074457345618258602, nodeKey: NodeKey1}, {token: 6148914691236517204, nodeKey: NodeKey2}, {token: 9223372036854775806, nodeKey: NodeKey1}, {token: 15372286728091293010, nodeKey: NodeKey1}, {token: 18446744073709551612, nodeKey: NodeKey2}}}, } for _, test := range tests { cluster := clusters[test.clusterId] t.Run(cluster.name, func(t *testing.T) { //given - testSubject := NewTopology(cluster.nodeIds, cluster.vNodes, cluster.replicaFactor) + testSubject := NewTopology(cluster.nodesVNodes, cluster.replicaFactor) //when ok := testSubject.RemoveVNode(test.token) diff --git a/core/pkg/topology/vNode.go b/core/pkg/topology/vNode.go index 15af732..db8c2b7 100644 --- a/core/pkg/topology/vNode.go +++ b/core/pkg/topology/vNode.go @@ -3,12 +3,12 @@ package topology import "fmt" type VNode struct { - nodeId uint32 - token uint64 + nodeKey string + token uint64 } -func (v VNode) NodeId() uint32 { - return v.nodeId +func (v VNode) NodeKey() string { + return v.nodeKey } func (v VNode) Token() uint64 { @@ -16,5 +16,5 @@ func (v VNode) Token() uint64 { } func (v VNode) String() string { - return fmt.Sprintf("{\"nodeId\":%d,\"token\":%d}", v.nodeId, v.token) + return fmt.Sprintf("{\"nodeKey\":%v,\"token\":%d}", v.nodeKey, v.token) } diff --git a/model/pb/ack.pb.go b/model/pb/ack.pb.go index 8b120fc..002e2c1 100644 --- a/model/pb/ack.pb.go +++ b/model/pb/ack.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: ack.proto package pb diff --git a/model/pb/link.pb.go b/model/pb/link.pb.go index d0c9b27..474bfee 100644 --- a/model/pb/link.pb.go +++ b/model/pb/link.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: link.proto package pb diff --git a/model/pb/log_record.pb.go b/model/pb/log_record.pb.go index 4c1ee4e..2f43e9b 100644 --- a/model/pb/log_record.pb.go +++ b/model/pb/log_record.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: log_record.proto package pb diff --git a/model/pb/piece.pb.go b/model/pb/piece.pb.go index 1e729f0..fa3687e 100644 --- a/model/pb/piece.pb.go +++ b/model/pb/piece.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: piece.proto package pb diff --git a/model/pb/query.pb.go b/model/pb/query.pb.go index 2cc00d1..d89fab4 100644 --- a/model/pb/query.pb.go +++ b/model/pb/query.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: query.proto package pb diff --git a/model/pb/request.pb.go b/model/pb/request.pb.go index 8eafe95..7f116f7 100644 --- a/model/pb/request.pb.go +++ b/model/pb/request.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: request.proto package pb diff --git a/model/pb/response.pb.go b/model/pb/response.pb.go index 98546ac..5d6f4b1 100644 --- a/model/pb/response.pb.go +++ b/model/pb/response.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: response.proto package pb diff --git a/model/pb/search_result.pb.go b/model/pb/search_result.pb.go index e41b9f7..eb667b3 100644 --- a/model/pb/search_result.pb.go +++ b/model/pb/search_result.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: search_result.proto package pb diff --git a/model/pb/session_status.pb.go b/model/pb/session_status.pb.go index 791d40c..df4a969 100644 --- a/model/pb/session_status.pb.go +++ b/model/pb/session_status.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: session_status.proto package pb diff --git a/model/pb/signature.pb.go b/model/pb/signature.pb.go index 2614770..194b93f 100644 --- a/model/pb/signature.pb.go +++ b/model/pb/signature.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: signature.proto package pb diff --git a/model/pb/signed_piece.pb.go b/model/pb/signed_piece.pb.go index d298e5f..00b17fc 100644 --- a/model/pb/signed_piece.pb.go +++ b/model/pb/signed_piece.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: signed_piece.proto package pb diff --git a/model/pb/state.pb.go b/model/pb/state.pb.go index 3577b1a..7ac98b5 100644 --- a/model/pb/state.pb.go +++ b/model/pb/state.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: state.proto package pb @@ -160,8 +160,8 @@ type ShortState struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - // ID of the node from smart contract - NodeID uint32 `protobuf:"varint,1,opt,name=nodeID,proto3" json:"nodeID,omitempty"` + // PubKey of the node from smart contract + NodeKey string `protobuf:"bytes,1,opt,name=nodeKey,proto3" json:"nodeKey,omitempty"` // ID of the cluster from smart contract ClusterID uint32 `protobuf:"varint,2,opt,name=clusterID,proto3" json:"clusterID,omitempty"` // URL of the node @@ -208,11 +208,11 @@ func (*ShortState) Descriptor() ([]byte, []int) { return file_state_proto_rawDescGZIP(), []int{1} } -func (x *ShortState) GetNodeID() uint32 { +func (x *ShortState) GetNodeKey() string { if x != nil { - return x.NodeID + return x.NodeKey } - return 0 + return "" } func (x *ShortState) GetClusterID() uint32 { @@ -261,7 +261,7 @@ func (x *ShortState) GetUpdated() uint64 { // State bring short state (last updated state) and list of checks (who checks the state and what is the result) // each check is signed by CDN node, that make them // statistic is a last statistic state of CDN node, that needed for diagnostic only -// sign(CID(NodeID+ClusterID+URL+State+Location+Size+Updated_at)) +// sign(CID(nodeKey+ClusterID+URL+State+Location+Size+Updated_at)) type GossipState struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -415,8 +415,7 @@ func (x *Check) GetSignature() *StateSignature { // // - It is normal, if time of signing is bigger from state timestamp. // - The State hash is: -// - Short state: `Hash = CID(NodeID+ClusterID+URL+State+Location+Size+Updated_at)` -// +// - Short state: `Hash = CID(nodeKey+ClusterID+URL+State+Location+Size+Updated_at)` // - The signing scheme should be sr25519, and `scheme` should be empty. // - If this not supported by a signer, then `scheme` should be "ed25519". // @@ -695,72 +694,72 @@ var file_state_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x25, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbf, 0x01, 0x0a, 0x0a, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x05, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x18, 0x0a, 0x07, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x22, 0x96, 0x02, 0x0a, 0x0b, 0x47, 0x6f, 0x73, 0x73, 0x69, - 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, - 0x53, 0x68, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x6c, 0x61, 0x73, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, - 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x2b, 0x0a, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x73, 0x74, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x69, - 0x73, 0x74, 0x69, 0x63, 0x12, 0x33, 0x0a, 0x06, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x18, 0x04, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x73, 0x73, 0x69, 0x70, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x06, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x1a, 0x44, 0x0a, 0x0b, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x62, 0x2e, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, - 0x5f, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x68, 0x6f, - 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x30, - 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, - 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x22, 0x9a, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, - 0x75, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x69, 0x67, - 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x65, - 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6d, 0x75, 0x6c, - 0x74, 0x69, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xbf, 0x01, - 0x0a, 0x09, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x12, 0x1a, 0x0a, 0x08, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x72, 0x65, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x62, 0x2e, - 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x52, 0x09, 0x72, 0x65, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, 0x73, 0x69, - 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x61, 0x63, 0x68, 0x65, 0x53, - 0x69, 0x7a, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, - 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x6d, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0d, 0x52, 0x03, 0x72, 0x61, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x68, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x02, 0x68, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, 0x65, 0x22, - 0x33, 0x0a, 0x09, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x12, 0x0a, 0x04, - 0x73, 0x6f, 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x6f, 0x66, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, - 0x68, 0x61, 0x72, 0x64, 0x2a, 0x37, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x06, 0x0a, - 0x02, 0x4e, 0x41, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x47, 0x52, 0x41, 0x59, 0x10, 0x01, 0x12, - 0x09, 0x0a, 0x05, 0x47, 0x52, 0x45, 0x45, 0x4e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x4c, - 0x55, 0x45, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x45, 0x44, 0x10, 0x04, 0x42, 0x05, 0x5a, - 0x03, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x3a, 0x02, 0x38, 0x01, 0x22, 0xc1, 0x01, 0x0a, 0x0a, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x4b, 0x65, 0x79, 0x12, 0x1c, 0x0a, + 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x09, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x49, 0x44, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x1f, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x09, 0x2e, 0x70, + 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, + 0x7a, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x18, + 0x0a, 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, + 0x07, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x22, 0x96, 0x02, 0x0a, 0x0b, 0x47, 0x6f, 0x73, + 0x73, 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2d, 0x0a, 0x0a, 0x6c, 0x61, 0x73, 0x74, + 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, + 0x62, 0x2e, 0x53, 0x68, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x09, 0x6c, 0x61, + 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, + 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x2b, 0x0a, 0x09, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, + 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x52, 0x09, 0x73, 0x74, 0x61, + 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x12, 0x33, 0x0a, 0x06, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x70, 0x62, 0x2e, 0x47, 0x6f, 0x73, 0x73, + 0x69, 0x70, 0x53, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x06, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x1a, 0x44, 0x0a, 0x0b, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1f, 0x0a, 0x05, + 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x09, 0x2e, 0x70, 0x62, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, + 0x01, 0x22, 0x5f, 0x0a, 0x05, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x12, 0x24, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x53, + 0x68, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, + 0x12, 0x30, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, + 0x72, 0x65, 0x22, 0x9a, 0x01, 0x0a, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x69, 0x67, 0x6e, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x69, 0x67, + 0x6e, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x6d, + 0x75, 0x6c, 0x74, 0x69, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0d, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x48, 0x61, 0x73, 0x68, 0x54, 0x79, 0x70, + 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, + 0xbf, 0x01, 0x0a, 0x09, 0x53, 0x74, 0x61, 0x74, 0x69, 0x73, 0x74, 0x69, 0x63, 0x12, 0x1a, 0x0a, + 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x08, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2b, 0x0a, 0x09, 0x72, 0x65, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, + 0x62, 0x2e, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x52, 0x09, 0x72, 0x65, 0x64, + 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x63, 0x68, 0x65, 0x5f, + 0x73, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x63, 0x61, 0x63, 0x68, + 0x65, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x70, 0x75, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x03, 0x63, 0x70, 0x75, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x61, 0x6d, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x72, 0x61, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x68, 0x64, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x68, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x70, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x75, 0x70, 0x74, 0x69, 0x6d, + 0x65, 0x22, 0x33, 0x0a, 0x09, 0x52, 0x65, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x73, 0x6f, 0x66, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x73, 0x6f, + 0x66, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, + 0x52, 0x04, 0x68, 0x61, 0x72, 0x64, 0x2a, 0x37, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, + 0x06, 0x0a, 0x02, 0x4e, 0x41, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x47, 0x52, 0x41, 0x59, 0x10, + 0x01, 0x12, 0x09, 0x0a, 0x05, 0x47, 0x52, 0x45, 0x45, 0x4e, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, + 0x42, 0x4c, 0x55, 0x45, 0x10, 0x03, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x45, 0x44, 0x10, 0x04, 0x42, + 0x05, 0x5a, 0x03, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/model/pb/tag.pb.go b/model/pb/tag.pb.go index b46ff7c..5feb8f6 100644 --- a/model/pb/tag.pb.go +++ b/model/pb/tag.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.31.0 -// protoc v4.24.3 +// protoc v4.23.3 // source: tag.proto package pb diff --git a/test/setup_test.go b/test/setup_test.go index 8c32897..ffb84c2 100644 --- a/test/setup_test.go +++ b/test/setup_test.go @@ -3,6 +3,9 @@ package test import ( "context" "encoding/hex" + "os" + "testing" + "github.com/centrifuge/go-substrate-rpc-client/v4/signature" "github.com/centrifuge/go-substrate-rpc-client/v4/types" "github.com/cerebellum-network/cere-ddc-sdk-go/contract/pkg" @@ -13,8 +16,6 @@ import ( "github.com/stretchr/testify/suite" tc "github.com/testcontainers/testcontainers-go/modules/compose" "github.com/testcontainers/testcontainers-go/wait" - "os" - "testing" ) type ApplicationTestSuite struct {