From 0ea65ca6378a92d4bc44b4f01d869ca4647dcacc Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 7 Nov 2023 15:23:14 +0300 Subject: [PATCH] [#50] Drop audit and reputation contracts Signed-off-by: Evgenii Stratonikov --- Makefile | 2 +- audit/audit_contract.go | 220 ------------------------------ audit/config.yml | 4 - audit/doc.go | 29 ---- reputation/config.yml | 13 -- reputation/doc.go | 24 ---- reputation/reputation_contract.go | 119 ---------------- rpcclient/audit/client.go | 128 ----------------- rpcclient/reputation/client.go | 207 ---------------------------- tests/reputation_test.go | 77 ----------- 10 files changed, 1 insertion(+), 822 deletions(-) delete mode 100644 audit/audit_contract.go delete mode 100644 audit/config.yml delete mode 100644 audit/doc.go delete mode 100644 reputation/config.yml delete mode 100644 reputation/doc.go delete mode 100644 reputation/reputation_contract.go delete mode 100644 rpcclient/audit/client.go delete mode 100644 rpcclient/reputation/client.go delete mode 100644 tests/reputation_test.go diff --git a/Makefile b/Makefile index 4351ffc..34ff0f1 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,7 @@ all: sidechain mainnet sidechain: alphabet morph nns alphabet_sc = alphabet -morph_sc = audit balance container frostfsid netmap proxy reputation policy +morph_sc = balance container frostfsid netmap proxy policy mainnet_sc = frostfs processing nns_sc = nns all_sc = $(alphabet_sc) $(morph_sc) $(mainnet_sc) $(nns_sc) diff --git a/audit/audit_contract.go b/audit/audit_contract.go deleted file mode 100644 index 1f73609..0000000 --- a/audit/audit_contract.go +++ /dev/null @@ -1,220 +0,0 @@ -package audit - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-contract/common" - "github.com/nspcc-dev/neo-go/pkg/interop" - "github.com/nspcc-dev/neo-go/pkg/interop/iterator" - "github.com/nspcc-dev/neo-go/pkg/interop/native/crypto" - "github.com/nspcc-dev/neo-go/pkg/interop/native/management" - "github.com/nspcc-dev/neo-go/pkg/interop/runtime" - "github.com/nspcc-dev/neo-go/pkg/interop/storage" -) - -type ( - auditHeader struct { - epoch int - cid []byte - from interop.PublicKey - } -) - -// Audit key is a combination of the epoch, the container ID and the public key of the node that -// has executed the audit. Together, it shouldn't be more than 64 bytes. We can't shrink -// epoch and container ID since we iterate over these values. But we can shrink -// public key by using first bytes of the hashed value. - -// V2 format -const maxKeySize = 24 // 24 + 32 (container ID length) + 8 (epoch length) = 64 - -func (a auditHeader) ID() []byte { - var buf any = a.epoch - - hashedKey := crypto.Sha256(a.from) - shortedKey := hashedKey[:maxKeySize] - - return append(buf.([]byte), append(a.cid, shortedKey...)...) -} - -const ( - netmapContractKey = "netmapScriptHash" -) - -func _deploy(data any, isUpdate bool) { - ctx := storage.GetContext() - - if isUpdate { - args := data.([]any) - common.CheckVersion(args[len(args)-1].(int)) - return - } - - args := data.(struct { - addrNetmap interop.Hash160 - }) - - if len(args.addrNetmap) != interop.Hash160Len { - panic("incorrect length of contract script hash") - } - - storage.Put(ctx, netmapContractKey, args.addrNetmap) - - runtime.Log("audit contract initialized") -} - -// Update method updates contract source code and manifest. It can be invoked -// only by committee. -func Update(script []byte, manifest []byte, data any) { - if !common.HasUpdateAccess() { - panic("only committee can update contract") - } - - management.UpdateWithData(script, manifest, common.AppendVersion(data)) - runtime.Log("audit contract updated") -} - -// Put method stores a stable marshalled `DataAuditResult` structure. It can be -// invoked only by Inner Ring nodes. -// -// Inner Ring nodes perform audit of containers and produce `DataAuditResult` -// structures. They are stored in audit contract and used for settlements -// in later epochs. -func Put(rawAuditResult []byte) { - ctx := storage.GetContext() - - innerRing := common.InnerRingNodes() - - hdr := newAuditHeader(rawAuditResult) - presented := false - - for i := range innerRing { - ir := innerRing[i] - if common.BytesEqual(ir, hdr.from) { - presented = true - - break - } - } - - if !runtime.CheckWitness(hdr.from) || !presented { - panic("put access denied") - } - - storage.Put(ctx, hdr.ID(), rawAuditResult) - - runtime.Log("audit: result has been saved") -} - -// Get method returns a stable marshaled DataAuditResult structure. -// -// The ID of the DataAuditResult can be obtained from listing methods. -func Get(id []byte) []byte { - ctx := storage.GetReadOnlyContext() - return storage.Get(ctx, id).([]byte) -} - -// List method returns a list of all available DataAuditResult IDs from -// the contract storage. -func List() [][]byte { - ctx := storage.GetReadOnlyContext() - it := storage.Find(ctx, []byte{}, storage.KeysOnly) - - return list(it) -} - -// ListByEpoch method returns a list of DataAuditResult IDs generated during -// the specified epoch. -func ListByEpoch(epoch int) [][]byte { - ctx := storage.GetReadOnlyContext() - var buf any = epoch - it := storage.Find(ctx, buf.([]byte), storage.KeysOnly) - - return list(it) -} - -// ListByCID method returns a list of DataAuditResult IDs generated during -// the specified epoch for the specified container. -func ListByCID(epoch int, cid []byte) [][]byte { - ctx := storage.GetReadOnlyContext() - - var buf any = epoch - - prefix := append(buf.([]byte), cid...) - it := storage.Find(ctx, prefix, storage.KeysOnly) - - return list(it) -} - -// ListByNode method returns a list of DataAuditResult IDs generated in -// the specified epoch for the specified container by the specified Inner Ring node. -func ListByNode(epoch int, cid []byte, key interop.PublicKey) [][]byte { - ctx := storage.GetReadOnlyContext() - hdr := auditHeader{ - epoch: epoch, - cid: cid, - from: key, - } - - it := storage.Find(ctx, hdr.ID(), storage.KeysOnly) - - return list(it) -} - -func list(it iterator.Iterator) [][]byte { - var result [][]byte - - ignore := [][]byte{ - []byte(netmapContractKey), - } - -loop: - for iterator.Next(it) { - key := iterator.Value(it).([]byte) // iterator MUST BE `storage.KeysOnly` - for _, ignoreKey := range ignore { - if common.BytesEqual(key, ignoreKey) { - continue loop - } - } - - result = append(result, key) - } - - return result -} - -// Version returns the version of the contract. -func Version() int { - return common.Version -} - -// readNext reads the length from the first byte, and then reads data (max 127 bytes). -func readNext(input []byte) ([]byte, int) { - var buf any = input[0] - ln := buf.(int) - - return input[1 : 1+ln], 1 + ln -} - -func newAuditHeader(input []byte) auditHeader { - // V2 format - offset := int(input[1]) - offset = 2 + offset + 1 // version prefix + version len + epoch prefix - - var buf any = input[offset : offset+8] // [ 8 integer bytes ] - epoch := buf.(int) - - offset = offset + 8 - - // cid is a nested structure with raw bytes - // [ cid struct prefix (wireType + len = 2 bytes), cid value wireType (1 byte), ... ] - cid, cidOffset := readNext(input[offset+2+1:]) - - // key is a raw byte - // [ public key wireType (1 byte), ... ] - key, _ := readNext(input[offset+2+1+cidOffset+1:]) - - return auditHeader{ - epoch, - cid, - key, - } -} diff --git a/audit/config.yml b/audit/config.yml deleted file mode 100644 index 5033360..0000000 --- a/audit/config.yml +++ /dev/null @@ -1,4 +0,0 @@ -name: "Audit" -safemethods: ["get", "list", "listByEpoch", "listByCID", "listByNode", "version"] -permissions: - - methods: ["update"] diff --git a/audit/doc.go b/audit/doc.go deleted file mode 100644 index 56dfc00..0000000 --- a/audit/doc.go +++ /dev/null @@ -1,29 +0,0 @@ -/* -Audit contract is a contract deployed in FrostFS sidechain. - -Inner Ring nodes perform audit of the registered containers during every epoch. -If a container contains StorageGroup objects, an Inner Ring node initializes -a series of audit checks. Based on the results of these checks, the Inner Ring -node creates a DataAuditResult structure for the container. The content of this -structure makes it possible to determine which storage nodes have been examined and -see the status of these checks. Regarding this information, the container owner is -charged for data storage. - -Audit contract is used as a reliable and verifiable storage for all -DataAuditResult structures. At the end of data audit routine, Inner Ring -nodes send a stable marshaled version of the DataAuditResult structure to the -contract. When Alphabet nodes of the Inner Ring perform settlement operations, -they make a list and get these AuditResultStructures from the audit contract. - -# Contract notifications - -Audit contract does not produce notifications to process. - -# Contract storage scheme - - | Key | Value | Description | - |--------------------|------------|-----------------------------------------------------------| - | `netmapScriptHash` | Hash160 | netmap contract hash | - | auditID | ByteArray | serialized DataAuditResult structure | -*/ -package audit diff --git a/reputation/config.yml b/reputation/config.yml deleted file mode 100644 index ffe98c6..0000000 --- a/reputation/config.yml +++ /dev/null @@ -1,13 +0,0 @@ -name: "Reputation" -safemethods: ["get", "getByID", "listByEpoch"] -permissions: - - methods: ["update"] -events: - - name: reputationPut - parameters: - - name: epoch - type: Integer - - name: peerID - type: ByteArray - - name: value - type: ByteArray diff --git a/reputation/doc.go b/reputation/doc.go deleted file mode 100644 index 094f6cb..0000000 --- a/reputation/doc.go +++ /dev/null @@ -1,24 +0,0 @@ -/* -Reputation contract is a contract deployed in FrostFS sidechain. - -Inner Ring nodes produce data audit for each container during each epoch. In the end, -nodes produce DataAuditResult structure that contains information about audit -progress. Reputation contract provides storage for such structures and simple -interface to iterate over available DataAuditResults on specified epoch. - -During settlement process, Alphabet nodes fetch all DataAuditResult structures -from the epoch and execute balance transfers from data owners to Storage and -Inner Ring nodes if data audit succeeds. - -# Contract notifications - -Reputation contract does not produce notifications to process. - -# Contract storage scheme - - | Key | Value | Description | - |-----------------------------|------------|-----------------------------------| - | `c` + epoch + peerID | int | peer reputation count | - | `r` + count | ByteArray | serialized DataAuditResult struct | -*/ -package reputation diff --git a/reputation/reputation_contract.go b/reputation/reputation_contract.go deleted file mode 100644 index 66e4b5d..0000000 --- a/reputation/reputation_contract.go +++ /dev/null @@ -1,119 +0,0 @@ -package reputation - -import ( - "git.frostfs.info/TrueCloudLab/frostfs-contract/common" - "github.com/nspcc-dev/neo-go/pkg/interop/convert" - "github.com/nspcc-dev/neo-go/pkg/interop/iterator" - "github.com/nspcc-dev/neo-go/pkg/interop/native/management" - "github.com/nspcc-dev/neo-go/pkg/interop/runtime" - "github.com/nspcc-dev/neo-go/pkg/interop/storage" -) - -const ( - reputationValuePrefix = 'r' - reputationCountPrefix = 'c' -) - -func _deploy(data any, isUpdate bool) { - if isUpdate { - args := data.([]any) - common.CheckVersion(args[len(args)-1].(int)) - return - } - - runtime.Log("reputation contract initialized") -} - -// Update method updates contract source code and manifest. It can be invoked -// only by committee. -func Update(script []byte, manifest []byte, data any) { - if !common.HasUpdateAccess() { - panic("only committee can update contract") - } - - management.UpdateWithData(script, manifest, common.AppendVersion(data)) - runtime.Log("reputation contract updated") -} - -// Put method saves DataAuditResult in contract storage. It can be invoked only by -// Inner Ring nodes. It does not require multisignature invocations. -// -// Epoch is the epoch number when DataAuditResult structure was generated. -// PeerID contains public keys of the Inner Ring node that has produced DataAuditResult. -// Value contains a stable marshaled structure of DataAuditResult. -func Put(epoch int, peerID []byte, value []byte) { - ctx := storage.GetContext() - - multiaddr := common.AlphabetAddress() - if !runtime.CheckWitness(multiaddr) { - runtime.Notify("reputationPut", epoch, peerID, value) - return - } - - id := storageID(epoch, peerID) - key := getReputationKey(reputationCountPrefix, id) - rawCnt := storage.Get(ctx, key) - cnt := 0 - if rawCnt != nil { - cnt = rawCnt.(int) - } - cnt++ - storage.Put(ctx, key, cnt) - - key[0] = reputationValuePrefix - key = append(key, convert.ToBytes(cnt)...) - storage.Put(ctx, key, value) -} - -// Get method returns a list of all stable marshaled DataAuditResult structures -// produced by the specified Inner Ring node during the specified epoch. -func Get(epoch int, peerID []byte) [][]byte { - id := storageID(epoch, peerID) - return GetByID(id) -} - -// GetByID method returns a list of all stable marshaled DataAuditResult with -// the specified id. Use ListByEpoch method to obtain the id. -func GetByID(id []byte) [][]byte { - ctx := storage.GetReadOnlyContext() - - var data [][]byte - - it := storage.Find(ctx, getReputationKey(reputationValuePrefix, id), storage.ValuesOnly) - for iterator.Next(it) { - data = append(data, iterator.Value(it).([]byte)) - } - return data -} - -func getReputationKey(prefix byte, id []byte) []byte { - return append([]byte{prefix}, id...) -} - -// ListByEpoch returns a list of IDs that may be used to get reputation data -// with GetByID method. -func ListByEpoch(epoch int) [][]byte { - ctx := storage.GetReadOnlyContext() - key := getReputationKey(reputationCountPrefix, convert.ToBytes(epoch)) - it := storage.Find(ctx, key, storage.KeysOnly) - - var result [][]byte - - for iterator.Next(it) { - key := iterator.Value(it).([]byte) // iterator MUST BE `storage.KeysOnly` - result = append(result, key[1:]) - } - - return result -} - -// Version returns the version of the contract. -func Version() int { - return common.Version -} - -func storageID(epoch int, peerID []byte) []byte { - var buf any = epoch - - return append(buf.([]byte), peerID...) -} diff --git a/rpcclient/audit/client.go b/rpcclient/audit/client.go deleted file mode 100644 index 8bb7a66..0000000 --- a/rpcclient/audit/client.go +++ /dev/null @@ -1,128 +0,0 @@ -// Package audit contains RPC wrappers for Audit contract. -// -// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT. -package audit - -import ( - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/crypto/keys" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "math/big" -) - -// Invoker is used by ContractReader to call various safe methods. -type Invoker interface { - Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) -} - -// Actor is used by Contract to call state-changing methods. -type Actor interface { - Invoker - - MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) - MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) - MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) - SendRun(script []byte) (util.Uint256, uint32, error) -} - -// ContractReader implements safe contract methods. -type ContractReader struct { - invoker Invoker - hash util.Uint160 -} - -// Contract implements all contract methods. -type Contract struct { - ContractReader - actor Actor - hash util.Uint160 -} - -// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. -func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { - return &ContractReader{invoker, hash} -} - -// New creates an instance of Contract using provided contract hash and the given Actor. -func New(actor Actor, hash util.Uint160) *Contract { - return &Contract{ContractReader{actor, hash}, actor, hash} -} - -// Get invokes `get` method of contract. -func (c *ContractReader) Get(id []byte) ([]byte, error) { - return unwrap.Bytes(c.invoker.Call(c.hash, "get", id)) -} - -// List invokes `list` method of contract. -func (c *ContractReader) List() ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.Call(c.hash, "list")) -} - -// ListByCID invokes `listByCID` method of contract. -func (c *ContractReader) ListByCID(epoch *big.Int, cid []byte) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.Call(c.hash, "listByCID", epoch, cid)) -} - -// ListByEpoch invokes `listByEpoch` method of contract. -func (c *ContractReader) ListByEpoch(epoch *big.Int) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.Call(c.hash, "listByEpoch", epoch)) -} - -// ListByNode invokes `listByNode` method of contract. -func (c *ContractReader) ListByNode(epoch *big.Int, cid []byte, key *keys.PublicKey) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.Call(c.hash, "listByNode", epoch, cid, key)) -} - -// Version invokes `version` method of contract. -func (c *ContractReader) Version() (*big.Int, error) { - return unwrap.BigInt(c.invoker.Call(c.hash, "version")) -} - -// Put creates a transaction invoking `put` method of the contract. -// This transaction is signed and immediately sent to the network. -// The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) Put(rawAuditResult []byte) (util.Uint256, uint32, error) { - return c.actor.SendCall(c.hash, "put", rawAuditResult) -} - -// PutTransaction creates a transaction invoking `put` method of the contract. -// This transaction is signed, but not sent to the network, instead it's -// returned to the caller. -func (c *Contract) PutTransaction(rawAuditResult []byte) (*transaction.Transaction, error) { - return c.actor.MakeCall(c.hash, "put", rawAuditResult) -} - -// PutUnsigned creates a transaction invoking `put` method of the contract. -// This transaction is not signed, it's simply returned to the caller. -// Any fields of it that do not affect fees can be changed (ValidUntilBlock, -// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) PutUnsigned(rawAuditResult []byte) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(c.hash, "put", nil, rawAuditResult) -} - -// Update creates a transaction invoking `update` method of the contract. -// This transaction is signed and immediately sent to the network. -// The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { - return c.actor.SendCall(c.hash, "update", script, manifest, data) -} - -// UpdateTransaction creates a transaction invoking `update` method of the contract. -// This transaction is signed, but not sent to the network, instead it's -// returned to the caller. -func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { - return c.actor.MakeCall(c.hash, "update", script, manifest, data) -} - -// UpdateUnsigned creates a transaction invoking `update` method of the contract. -// This transaction is not signed, it's simply returned to the caller. -// Any fields of it that do not affect fees can be changed (ValidUntilBlock, -// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) -} diff --git a/rpcclient/reputation/client.go b/rpcclient/reputation/client.go deleted file mode 100644 index 3a495cb..0000000 --- a/rpcclient/reputation/client.go +++ /dev/null @@ -1,207 +0,0 @@ -// Package reputation contains RPC wrappers for Reputation contract. -// -// Code generated by neo-go contract generate-rpcwrapper --manifest --out [--hash ] [--config ]; DO NOT EDIT. -package reputation - -import ( - "errors" - "fmt" - "github.com/nspcc-dev/neo-go/pkg/core/transaction" - "github.com/nspcc-dev/neo-go/pkg/neorpc/result" - "github.com/nspcc-dev/neo-go/pkg/rpcclient/unwrap" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" - "math/big" -) - -// ReputationPutEvent represents "reputationPut" event emitted by the contract. -type ReputationPutEvent struct { - Epoch *big.Int - PeerID []byte - Value []byte -} - -// Invoker is used by ContractReader to call various safe methods. -type Invoker interface { - Call(contract util.Uint160, operation string, params ...any) (*result.Invoke, error) -} - -// Actor is used by Contract to call state-changing methods. -type Actor interface { - Invoker - - MakeCall(contract util.Uint160, method string, params ...any) (*transaction.Transaction, error) - MakeRun(script []byte) (*transaction.Transaction, error) - MakeUnsignedCall(contract util.Uint160, method string, attrs []transaction.Attribute, params ...any) (*transaction.Transaction, error) - MakeUnsignedRun(script []byte, attrs []transaction.Attribute) (*transaction.Transaction, error) - SendCall(contract util.Uint160, method string, params ...any) (util.Uint256, uint32, error) - SendRun(script []byte) (util.Uint256, uint32, error) -} - -// ContractReader implements safe contract methods. -type ContractReader struct { - invoker Invoker - hash util.Uint160 -} - -// Contract implements all contract methods. -type Contract struct { - ContractReader - actor Actor - hash util.Uint160 -} - -// NewReader creates an instance of ContractReader using provided contract hash and the given Invoker. -func NewReader(invoker Invoker, hash util.Uint160) *ContractReader { - return &ContractReader{invoker, hash} -} - -// New creates an instance of Contract using provided contract hash and the given Actor. -func New(actor Actor, hash util.Uint160) *Contract { - return &Contract{ContractReader{actor, hash}, actor, hash} -} - -// Get invokes `get` method of contract. -func (c *ContractReader) Get(epoch *big.Int, peerID []byte) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.Call(c.hash, "get", epoch, peerID)) -} - -// GetByID invokes `getByID` method of contract. -func (c *ContractReader) GetByID(id []byte) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.Call(c.hash, "getByID", id)) -} - -// ListByEpoch invokes `listByEpoch` method of contract. -func (c *ContractReader) ListByEpoch(epoch *big.Int) ([]stackitem.Item, error) { - return unwrap.Array(c.invoker.Call(c.hash, "listByEpoch", epoch)) -} - -// Put creates a transaction invoking `put` method of the contract. -// This transaction is signed and immediately sent to the network. -// The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) Put(epoch *big.Int, peerID []byte, value []byte) (util.Uint256, uint32, error) { - return c.actor.SendCall(c.hash, "put", epoch, peerID, value) -} - -// PutTransaction creates a transaction invoking `put` method of the contract. -// This transaction is signed, but not sent to the network, instead it's -// returned to the caller. -func (c *Contract) PutTransaction(epoch *big.Int, peerID []byte, value []byte) (*transaction.Transaction, error) { - return c.actor.MakeCall(c.hash, "put", epoch, peerID, value) -} - -// PutUnsigned creates a transaction invoking `put` method of the contract. -// This transaction is not signed, it's simply returned to the caller. -// Any fields of it that do not affect fees can be changed (ValidUntilBlock, -// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) PutUnsigned(epoch *big.Int, peerID []byte, value []byte) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(c.hash, "put", nil, epoch, peerID, value) -} - -// Update creates a transaction invoking `update` method of the contract. -// This transaction is signed and immediately sent to the network. -// The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) Update(script []byte, manifest []byte, data any) (util.Uint256, uint32, error) { - return c.actor.SendCall(c.hash, "update", script, manifest, data) -} - -// UpdateTransaction creates a transaction invoking `update` method of the contract. -// This transaction is signed, but not sent to the network, instead it's -// returned to the caller. -func (c *Contract) UpdateTransaction(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { - return c.actor.MakeCall(c.hash, "update", script, manifest, data) -} - -// UpdateUnsigned creates a transaction invoking `update` method of the contract. -// This transaction is not signed, it's simply returned to the caller. -// Any fields of it that do not affect fees can be changed (ValidUntilBlock, -// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) UpdateUnsigned(script []byte, manifest []byte, data any) (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(c.hash, "update", nil, script, manifest, data) -} - -// Version creates a transaction invoking `version` method of the contract. -// This transaction is signed and immediately sent to the network. -// The values returned are its hash, ValidUntilBlock value and error if any. -func (c *Contract) Version() (util.Uint256, uint32, error) { - return c.actor.SendCall(c.hash, "version") -} - -// VersionTransaction creates a transaction invoking `version` method of the contract. -// This transaction is signed, but not sent to the network, instead it's -// returned to the caller. -func (c *Contract) VersionTransaction() (*transaction.Transaction, error) { - return c.actor.MakeCall(c.hash, "version") -} - -// VersionUnsigned creates a transaction invoking `version` method of the contract. -// This transaction is not signed, it's simply returned to the caller. -// Any fields of it that do not affect fees can be changed (ValidUntilBlock, -// Nonce), fee values (NetworkFee, SystemFee) can be increased as well. -func (c *Contract) VersionUnsigned() (*transaction.Transaction, error) { - return c.actor.MakeUnsignedCall(c.hash, "version", nil) -} - -// ReputationPutEventsFromApplicationLog retrieves a set of all emitted events -// with "reputationPut" name from the provided [result.ApplicationLog]. -func ReputationPutEventsFromApplicationLog(log *result.ApplicationLog) ([]*ReputationPutEvent, error) { - if log == nil { - return nil, errors.New("nil application log") - } - - var res []*ReputationPutEvent - for i, ex := range log.Executions { - for j, e := range ex.Events { - if e.Name != "reputationPut" { - continue - } - event := new(ReputationPutEvent) - err := event.FromStackItem(e.Item) - if err != nil { - return nil, fmt.Errorf("failed to deserialize ReputationPutEvent from stackitem (execution #%d, event #%d): %w", i, j, err) - } - res = append(res, event) - } - } - - return res, nil -} - -// FromStackItem converts provided [stackitem.Array] to ReputationPutEvent or -// returns an error if it's not possible to do to so. -func (e *ReputationPutEvent) FromStackItem(item *stackitem.Array) error { - if item == nil { - return errors.New("nil item") - } - arr, ok := item.Value().([]stackitem.Item) - if !ok { - return errors.New("not an array") - } - if len(arr) != 3 { - return errors.New("wrong number of structure elements") - } - - var ( - index = -1 - err error - ) - index++ - e.Epoch, err = arr[index].TryInteger() - if err != nil { - return fmt.Errorf("field Epoch: %w", err) - } - - index++ - e.PeerID, err = arr[index].TryBytes() - if err != nil { - return fmt.Errorf("field PeerID: %w", err) - } - - index++ - e.Value, err = arr[index].TryBytes() - if err != nil { - return fmt.Errorf("field Value: %w", err) - } - - return nil -} diff --git a/tests/reputation_test.go b/tests/reputation_test.go deleted file mode 100644 index 844e74f..0000000 --- a/tests/reputation_test.go +++ /dev/null @@ -1,77 +0,0 @@ -package tests - -import ( - "path" - "testing" - - "github.com/nspcc-dev/neo-go/pkg/neotest" - "github.com/nspcc-dev/neo-go/pkg/neotest/chain" - "github.com/nspcc-dev/neo-go/pkg/util" - "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" -) - -const reputationPath = "../reputation" - -func deployReputationContract(t *testing.T, e *neotest.Executor) util.Uint160 { - c := neotest.CompileFile(t, e.CommitteeHash, reputationPath, - path.Join(reputationPath, "config.yml")) - - e.DeployContract(t, c, []any{}) - return c.Hash -} - -func newReputationInvoker(t *testing.T) *neotest.ContractInvoker { - bc, acc := chain.NewSingle(t) - e := neotest.NewExecutor(t, bc, acc, acc) - h := deployReputationContract(t, e) - return e.CommitteeInvoker(h) -} - -func TestReputation_Put(t *testing.T) { - e := newReputationInvoker(t) - - peerID := []byte{1, 2, 3} - e.Invoke(t, stackitem.Null{}, "put", int64(1), peerID, []byte{4}) - - t.Run("concurrent invocations", func(t *testing.T) { - repValue1 := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} - repValue2 := []byte{10, 20, 30, 40, 50, 60, 70, 80} - tx1 := e.PrepareInvoke(t, "put", int64(1), peerID, repValue1) - tx2 := e.PrepareInvoke(t, "put", int64(1), peerID, repValue2) - - e.AddNewBlock(t, tx1, tx2) - e.CheckHalt(t, tx1.Hash(), stackitem.Null{}) - e.CheckHalt(t, tx2.Hash(), stackitem.Null{}) - - t.Run("get all", func(t *testing.T) { - result := stackitem.NewArray([]stackitem.Item{ - stackitem.NewBuffer([]byte{4}), - stackitem.NewBuffer(repValue1), - stackitem.NewBuffer(repValue2), - }) - e.Invoke(t, result, "get", int64(1), peerID) - }) - }) -} - -func TestReputation_ListByEpoch(t *testing.T) { - e := newReputationInvoker(t) - - peerIDs := []string{"peer1", "peer2"} - e.Invoke(t, stackitem.Null{}, "put", int64(1), peerIDs[0], []byte{1}) - e.Invoke(t, stackitem.Null{}, "put", int64(1), peerIDs[0], []byte{2}) - e.Invoke(t, stackitem.Null{}, "put", int64(2), peerIDs[1], []byte{3}) - e.Invoke(t, stackitem.Null{}, "put", int64(2), peerIDs[0], []byte{4}) - e.Invoke(t, stackitem.Null{}, "put", int64(2), peerIDs[1], []byte{5}) - - result := stackitem.NewArray([]stackitem.Item{ - stackitem.NewBuffer(append([]byte{1}, peerIDs[0]...)), - }) - e.Invoke(t, result, "listByEpoch", int64(1)) - - result = stackitem.NewArray([]stackitem.Item{ - stackitem.NewBuffer(append([]byte{2}, peerIDs[0]...)), - stackitem.NewBuffer(append([]byte{2}, peerIDs[1]...)), - }) - e.Invoke(t, result, "listByEpoch", int64(2)) -}