Drop notaryless deploy parameter #50
41 changed files with 213 additions and 1097 deletions
14
Makefile
14
Makefile
|
@ -22,7 +22,7 @@ all: sidechain mainnet
|
||||||
sidechain: alphabet morph nns
|
sidechain: alphabet morph nns
|
||||||
|
|
||||||
alphabet_sc = alphabet
|
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
|
mainnet_sc = frostfs processing
|
||||||
nns_sc = nns
|
nns_sc = nns
|
||||||
all_sc = $(alphabet_sc) $(morph_sc) $(mainnet_sc) $(nns_sc)
|
all_sc = $(alphabet_sc) $(morph_sc) $(mainnet_sc) $(nns_sc)
|
||||||
|
@ -64,6 +64,18 @@ generate-wrappers: build $(foreach sc,$(all_sc),generate-wrapper.$(sc))
|
||||||
test:
|
test:
|
||||||
@go test ./tests/...
|
@go test ./tests/...
|
||||||
|
|
||||||
|
# Run all code formatters
|
||||||
|
fmts: fumpt imports
|
||||||
|
|
||||||
|
# Reformat imports
|
||||||
|
imports:
|
||||||
|
@echo "⇒ Processing goimports check"
|
||||||
|
@goimports -w $(all_sc) tests/
|
||||||
|
|
||||||
|
fumpt:
|
||||||
|
@echo "⇒ Processing gofumpt check"
|
||||||
|
@gofumpt -l -w $(all_sc) tests/
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
find . -name '*.nef' -exec rm -rf {} \;
|
find . -name '*.nef' -exec rm -rf {} \;
|
||||||
find . -name 'config.json' -exec rm -rf {} \;
|
find . -name 'config.json' -exec rm -rf {} \;
|
||||||
|
|
|
@ -18,38 +18,32 @@ const (
|
||||||
indexKey = "index"
|
indexKey = "index"
|
||||||
totalKey = "threshold"
|
totalKey = "threshold"
|
||||||
nameKey = "name"
|
nameKey = "name"
|
||||||
|
|
||||||
notaryDisabledKey = "notary"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// OnNEP17Payment is a callback for NEP-17 compatible native GAS and NEO
|
// OnNEP17Payment is a callback for NEP-17 compatible native GAS and NEO
|
||||||
// contracts.
|
// contracts.
|
||||||
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
func OnNEP17Payment(from interop.Hash160, amount int, data any) {
|
||||||
caller := runtime.GetCallingScriptHash()
|
caller := runtime.GetCallingScriptHash()
|
||||||
if !common.BytesEqual(caller, []byte(gas.Hash)) && !common.BytesEqual(caller, []byte(neo.Hash)) {
|
if !common.BytesEqual(caller, []byte(gas.Hash)) && !common.BytesEqual(caller, []byte(neo.Hash)) {
|
||||||
common.AbortWithMessage("alphabet contract accepts GAS and NEO only")
|
common.AbortWithMessage("alphabet contract accepts GAS and NEO only")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
|
||||||
|
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
args := data.(struct {
|
args := data.(struct {
|
||||||
//TODO(@acid-ant): #9 remove notaryDisabled in future version
|
addrNetmap interop.Hash160
|
||||||
notaryDisabled bool
|
addrProxy interop.Hash160
|
||||||
addrNetmap interop.Hash160
|
name string
|
||||||
addrProxy interop.Hash160
|
index int
|
||||||
name string
|
total int
|
||||||
index int
|
|
||||||
total int
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrProxy) != interop.Hash160Len {
|
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrProxy) != interop.Hash160Len {
|
||||||
|
@ -67,7 +61,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
panic("only committee can update contract")
|
panic("only committee can update contract")
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,13 +20,12 @@ Alphabet contract does not produce notifications to process.
|
||||||
|
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|--------------------|------------|-------------------------------------------------|
|
|--------------------|------------|-------------------------------------------------|
|
||||||
| `netmapScriptHash` | Hash160 | netmap contract hash |
|
| `netmapScriptHash` | Hash160 | netmap contract hash |
|
||||||
| `proxyScriptHash` | Hash160 | proxy contract hash |
|
| `proxyScriptHash` | Hash160 | proxy contract hash |
|
||||||
| `name` | string | assigned glagolitic letter |
|
| `name` | string | assigned glagolitic letter |
|
||||||
| `index` | int | the index of deployed alphabet contract |
|
| `index` | int | the index of deployed alphabet contract |
|
||||||
| `threshold` | int | the total number of deployed alphabet contracts |
|
| `threshold` | int | the total number of deployed alphabet contracts |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package alphabet
|
package alphabet
|
||||||
|
|
|
@ -1,226 +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 interface{} = a.epoch
|
|
||||||
|
|
||||||
hashedKey := crypto.Sha256(a.from)
|
|
||||||
shortedKey := hashedKey[:maxKeySize]
|
|
||||||
|
|
||||||
return append(buf.([]byte), append(a.cid, shortedKey...)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
netmapContractKey = "netmapScriptHash"
|
|
||||||
|
|
||||||
notaryDisabledKey = "notary"
|
|
||||||
)
|
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
|
||||||
ctx := storage.GetContext()
|
|
||||||
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
|
||||||
|
|
||||||
if isUpdate {
|
|
||||||
args := data.([]interface{})
|
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
args := data.(struct {
|
|
||||||
//TODO(@acid-ant): #9 remove notaryDisabled in future version
|
|
||||||
notaryDisabled bool
|
|
||||||
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 interface{}) {
|
|
||||||
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 interface{} = 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 interface{} = 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 interface{} = 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 interface{} = 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,
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
name: "Audit"
|
|
||||||
safemethods: ["get", "list", "listByEpoch", "listByCID", "listByNode", "version"]
|
|
||||||
permissions:
|
|
||||||
- methods: ["update"]
|
|
30
audit/doc.go
30
audit/doc.go
|
@ -1,30 +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
|
|
|
@ -47,7 +47,6 @@ const (
|
||||||
|
|
||||||
netmapContractKey = "netmapScriptHash"
|
netmapContractKey = "netmapScriptHash"
|
||||||
containerContractKey = "containerScriptHash"
|
containerContractKey = "containerScriptHash"
|
||||||
notaryDisabledKey = "notary"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var token Token
|
var token Token
|
||||||
|
@ -64,22 +63,18 @@ func init() {
|
||||||
token = createToken()
|
token = createToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
|
||||||
|
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
args := data.(struct {
|
args := data.(struct {
|
||||||
// TODO(@acid-ant): #9 remove notaryDisabled in future version
|
addrNetmap interop.Hash160
|
||||||
notaryDisabled bool
|
addrContainer interop.Hash160
|
||||||
addrNetmap interop.Hash160
|
|
||||||
addrContainer interop.Hash160
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrContainer) != interop.Hash160Len {
|
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrContainer) != interop.Hash160Len {
|
||||||
|
@ -94,7 +89,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
panic("only committee can update contract")
|
panic("only committee can update contract")
|
||||||
}
|
}
|
||||||
|
@ -133,7 +128,7 @@ func BalanceOf(account interop.Hash160) int {
|
||||||
//
|
//
|
||||||
// It produces Transfer and TransferX notifications. TransferX notification
|
// It produces Transfer and TransferX notifications. TransferX notification
|
||||||
// will have empty details field.
|
// will have empty details field.
|
||||||
func Transfer(from, to interop.Hash160, amount int, data interface{}) bool {
|
func Transfer(from, to interop.Hash160, amount int, data any) bool {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
return token.transfer(ctx, from, to, amount, false, nil)
|
return token.transfer(ctx, from, to, amount, false, nil)
|
||||||
}
|
}
|
||||||
|
@ -335,9 +330,7 @@ func (t Token) transfer(ctx storage.Context, from, to interop.Hash160, amount in
|
||||||
|
|
||||||
// canTransfer returns the amount it can transfer.
|
// canTransfer returns the amount it can transfer.
|
||||||
func (t Token) canTransfer(ctx storage.Context, from, to interop.Hash160, amount int, innerRing bool) (Account, bool) {
|
func (t Token) canTransfer(ctx storage.Context, from, to interop.Hash160, amount int, innerRing bool) (Account, bool) {
|
||||||
var (
|
emptyAcc := Account{}
|
||||||
emptyAcc = Account{}
|
|
||||||
)
|
|
||||||
|
|
||||||
if !innerRing {
|
if !innerRing {
|
||||||
if len(to) != interop.Hash160Len || !isUsableAddress(from) {
|
if len(to) != interop.Hash160Len || !isUsableAddress(from) {
|
||||||
|
@ -375,7 +368,7 @@ func isUsableAddress(addr interop.Hash160) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAccount(ctx storage.Context, key interface{}) Account {
|
func getAccount(ctx storage.Context, key any) Account {
|
||||||
data := storage.Get(ctx, key)
|
data := storage.Get(ctx, key)
|
||||||
if data != nil {
|
if data != nil {
|
||||||
acc := std.Deserialize(data.([]byte)).(account)
|
acc := std.Deserialize(data.([]byte)).(account)
|
||||||
|
@ -389,7 +382,7 @@ func getAccount(ctx storage.Context, key interface{}) Account {
|
||||||
return Account{}
|
return Account{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setAccount(ctx storage.Context, key interface{}, acc Account) {
|
func setAccount(ctx storage.Context, key any, acc Account) {
|
||||||
common.SetSerialized(ctx, key, account{
|
common.SetSerialized(ctx, key, account{
|
||||||
Balance: common.ToFixedWidth64(acc.Balance),
|
Balance: common.ToFixedWidth64(acc.Balance),
|
||||||
Until: common.ToFixedWidth64(acc.Until),
|
Until: common.ToFixedWidth64(acc.Until),
|
||||||
|
|
|
@ -77,11 +77,10 @@ when FrostFS contract has transferred GAS assets back to the user.
|
||||||
|
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|-----------------------|------------|----------------------------------|
|
|-----------------------|------------|----------------------------------|
|
||||||
| `netmapScriptHash` | Hash160 | netmap contract hash |
|
| `netmapScriptHash` | Hash160 | netmap contract hash |
|
||||||
| `containerScriptHash` | Hash160 | container contract hash |
|
| `containerScriptHash` | Hash160 | container contract hash |
|
||||||
| circulationKey | int | the token circulation key value |
|
| circulationKey | int | the token circulation key value |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package balance
|
package balance
|
||||||
|
|
|
@ -1,26 +1,11 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
"github.com/nspcc-dev/neo-go/pkg/interop/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
panicMsgForNotaryDisabledEnv = "contract not applicable for notary-disabled environment"
|
|
||||||
)
|
|
||||||
|
|
||||||
// BytesEqual compares two slices of bytes by wrapping them into strings,
|
// BytesEqual compares two slices of bytes by wrapping them into strings,
|
||||||
// which is necessary with new util.Equals interop behaviour, see neo-go#1176.
|
// which is necessary with new util.Equals interop behaviour, see neo-go#1176.
|
||||||
func BytesEqual(a []byte, b []byte) bool {
|
func BytesEqual(a []byte, b []byte) bool {
|
||||||
return util.Equals(string(a), string(b))
|
return util.Equals(string(a), string(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
// RmAndCheckNotaryDisabledKey remove notary disabled key from storage and
|
|
||||||
// panic in notary disabled environment
|
|
||||||
func RmAndCheckNotaryDisabledKey(data interface{}, key interface{}) {
|
|
||||||
//TODO(@acid-ant): #9 remove notaryDisabled from args in future version
|
|
||||||
storage.Delete(storage.GetContext(), key)
|
|
||||||
if data.([]interface{})[0].(bool) {
|
|
||||||
panic(panicMsgForNotaryDisabledEnv)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// SetSerialized serializes data and puts it into contract storage.
|
// SetSerialized serializes data and puts it into contract storage.
|
||||||
func SetSerialized(ctx storage.Context, key interface{}, value interface{}) {
|
func SetSerialized(ctx storage.Context, key any, value interface{}) {
|
||||||
data := std.Serialize(value)
|
data := std.Serialize(value)
|
||||||
storage.Put(ctx, key, data)
|
storage.Put(ctx, key, data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func LockTransferDetails(txDetails []byte) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func UnlockTransferDetails(epoch int) []byte {
|
func UnlockTransferDetails(epoch int) []byte {
|
||||||
var buf interface{} = epoch
|
var buf any = epoch
|
||||||
return append(unlockPrefix, buf.([]byte)...)
|
return append(unlockPrefix, buf.([]byte)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,9 +38,9 @@ func CheckVersion(from int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppendVersion appends current contract version to the list of deploy arguments.
|
// AppendVersion appends current contract version to the list of deploy arguments.
|
||||||
func AppendVersion(data interface{}) []interface{} {
|
func AppendVersion(data any) []interface{} {
|
||||||
if data == nil {
|
if data == nil {
|
||||||
return []interface{}{Version}
|
return []any{Version}
|
||||||
}
|
}
|
||||||
return append(data.([]interface{}), Version)
|
return append(data.([]any), Version)
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,6 @@ const (
|
||||||
nnsContractKey = "nnsScriptHash"
|
nnsContractKey = "nnsScriptHash"
|
||||||
nnsRootKey = "nnsRoot"
|
nnsRootKey = "nnsRoot"
|
||||||
nnsHasAliasKey = "nnsHasAlias"
|
nnsHasAliasKey = "nnsHasAlias"
|
||||||
notaryDisabledKey = "notary"
|
|
||||||
|
|
||||||
// RegistrationFeeKey is a key in netmap config which contains fee for container registration.
|
// RegistrationFeeKey is a key in netmap config which contains fee for container registration.
|
||||||
RegistrationFeeKey = "ContainerFee"
|
RegistrationFeeKey = "ContainerFee"
|
||||||
|
@ -83,21 +82,17 @@ const (
|
||||||
defaultTTL = 3600 // 1 hour
|
defaultTTL = 3600 // 1 hour
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var eACLPrefix = []byte("eACL")
|
||||||
eACLPrefix = []byte("eACL")
|
|
||||||
)
|
|
||||||
|
|
||||||
// OnNEP11Payment is needed for registration with contract as the owner to work.
|
// OnNEP11Payment is needed for registration with contract as the owner to work.
|
||||||
func OnNEP11Payment(a interop.Hash160, b int, c []byte, d interface{}) {
|
func OnNEP11Payment(a interop.Hash160, b int, c []byte, d any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
|
||||||
|
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
|
|
||||||
it := storage.Find(ctx, []byte{}, storage.None)
|
it := storage.Find(ctx, []byte{}, storage.None)
|
||||||
|
@ -123,13 +118,11 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
args := data.(struct {
|
args := data.(struct {
|
||||||
//TODO(@acid-ant): #9 remove notaryDisabled in future version
|
addrNetmap interop.Hash160
|
||||||
notaryDisabled bool
|
addrBalance interop.Hash160
|
||||||
addrNetmap interop.Hash160
|
addrID interop.Hash160
|
||||||
addrBalance interop.Hash160
|
addrNNS interop.Hash160
|
||||||
addrID interop.Hash160
|
nnsRoot string
|
||||||
addrNNS interop.Hash160
|
|
||||||
nnsRoot string
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(args.addrNetmap) != interop.Hash160Len ||
|
if len(args.addrNetmap) != interop.Hash160Len ||
|
||||||
|
@ -167,7 +160,7 @@ func registerNiceNameTLD(addrNNS interop.Hash160, nnsRoot string) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// by committee only.
|
// by committee only.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
panic("only committee can update contract")
|
panic("only committee can update contract")
|
||||||
}
|
}
|
||||||
|
@ -192,7 +185,8 @@ func Put(container []byte, signature interop.Signature, publicKey interop.Public
|
||||||
// Note that zone must exist.
|
// Note that zone must exist.
|
||||||
func PutNamed(container []byte, signature interop.Signature,
|
func PutNamed(container []byte, signature interop.Signature,
|
||||||
publicKey interop.PublicKey, token []byte,
|
publicKey interop.PublicKey, token []byte,
|
||||||
name, zone string) {
|
name, zone string,
|
||||||
|
) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
ownerID := ownerFromBinaryContainer(container)
|
ownerID := ownerFromBinaryContainer(container)
|
||||||
|
@ -329,7 +323,7 @@ func Delete(containerID []byte, signature interop.Signature, publicKey interop.P
|
||||||
// and inability to delete a container. We should also check if we own the record in case.
|
// and inability to delete a container. We should also check if we own the record in case.
|
||||||
nnsContractAddr := storage.Get(ctx, nnsContractKey).(interop.Hash160)
|
nnsContractAddr := storage.Get(ctx, nnsContractKey).(interop.Hash160)
|
||||||
res := contract.Call(nnsContractAddr, "getRecords", contract.ReadStates|contract.AllowCall, domain, 16 /* TXT */)
|
res := contract.Call(nnsContractAddr, "getRecords", contract.ReadStates|contract.AllowCall, domain, 16 /* TXT */)
|
||||||
if res != nil && std.Base58Encode(containerID) == string(res.([]interface{})[0].(string)) {
|
if res != nil && std.Base58Encode(containerID) == string(res.([]any)[0].(string)) {
|
||||||
contract.Call(nnsContractAddr, "deleteRecords", contract.All, domain, 16 /* TXT */)
|
contract.Call(nnsContractAddr, "deleteRecords", contract.All, domain, 16 /* TXT */)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -546,7 +540,7 @@ func GetContainerSize(id []byte) containerSizes {
|
||||||
func ListContainerSizes(epoch int) [][]byte {
|
func ListContainerSizes(epoch int) [][]byte {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
var buf interface{} = epoch
|
var buf any = epoch
|
||||||
|
|
||||||
key := []byte(estimateKeyPrefix)
|
key := []byte(estimateKeyPrefix)
|
||||||
key = append(key, buf.([]byte)...)
|
key = append(key, buf.([]byte)...)
|
||||||
|
@ -578,7 +572,7 @@ func ListContainerSizes(epoch int) [][]byte {
|
||||||
func IterateContainerSizes(epoch int) iterator.Iterator {
|
func IterateContainerSizes(epoch int) iterator.Iterator {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
|
|
||||||
var buf interface{} = epoch
|
var buf any = epoch
|
||||||
|
|
||||||
key := []byte(estimateKeyPrefix)
|
key := []byte(estimateKeyPrefix)
|
||||||
key = append(key, buf.([]byte)...)
|
key = append(key, buf.([]byte)...)
|
||||||
|
@ -696,7 +690,7 @@ func ownerFromBinaryContainer(container []byte) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func estimationKey(epoch int, cid []byte, key interop.PublicKey) []byte {
|
func estimationKey(epoch int, cid []byte, key interop.PublicKey) []byte {
|
||||||
var buf interface{} = epoch
|
var buf any = epoch
|
||||||
|
|
||||||
hash := crypto.Ripemd160(key)
|
hash := crypto.Ripemd160(key)
|
||||||
|
|
||||||
|
@ -774,7 +768,7 @@ func cleanupContainers(ctx storage.Context, epoch int) {
|
||||||
// V2 format
|
// V2 format
|
||||||
nbytes := k[len(estimateKeyPrefix) : len(k)-containerIDSize-estimatePostfixSize]
|
nbytes := k[len(estimateKeyPrefix) : len(k)-containerIDSize-estimatePostfixSize]
|
||||||
|
|
||||||
var n interface{} = nbytes
|
var n any = nbytes
|
||||||
|
|
||||||
if epoch-n.(int) > TotalCleanupDelta {
|
if epoch-n.(int) > TotalCleanupDelta {
|
||||||
storage.Delete(ctx, k)
|
storage.Delete(ctx, k)
|
||||||
|
|
|
@ -26,19 +26,17 @@ it in Container contract.
|
||||||
|
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|-----------------------------------------------------------------------------------------------------|
|
|-----------------------------------------------------------------------------------------------------|
|
||||||
| `netmapScriptHash` | Hash160 | netmap contract hash |
|
| `netmapScriptHash` | Hash160 | netmap contract hash |
|
||||||
| `balanceScriptHash` | Hash160 | balance contract hash |
|
| `balanceScriptHash` | Hash160 | balance contract hash |
|
||||||
| `identityScriptHash` | Hash160 | frostfsID contract hash |
|
| `identityScriptHash` | Hash160 | frostfsID contract hash |
|
||||||
| `nnsContractKey` | Hash160 | nns contract hash |
|
| `nnsContractKey` | Hash160 | nns contract hash |
|
||||||
| `nnsRoot` | string | default value for domain zone |
|
| `nnsRoot` | string | default value for domain zone |
|
||||||
| `cnr` + epoch + containerID + publicKeyHash[:10] | ByteArray | estimated container size |
|
| `cnr` + epoch + containerID + publicKeyHash[:10] | ByteArray | estimated container size |
|
||||||
| `est` + containerID + publicKeyHash | ByteArray | serialized epochs array |
|
| `est` + containerID + publicKeyHash | ByteArray | serialized epochs array |
|
||||||
| `o` + ownerID + containerID | ByteArray | container ID |
|
| `o` + ownerID + containerID | ByteArray | container ID |
|
||||||
| `x` + containerID | ByteArray | serialized container struct |
|
| `x` + containerID | ByteArray | serialized container struct |
|
||||||
| `nnsHasAlias` + containerID | string | domain name |
|
| `nnsHasAlias` + containerID | string | domain name |
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package container
|
package container
|
||||||
|
|
|
@ -83,12 +83,10 @@ FrostFS network configuration value.
|
||||||
|
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|-----------------------------------------------------------------------------|
|
|-----------------------------------------------------------------------------|
|
||||||
| `processingScriptHash` | Hash160 | processing contract hash |
|
| `processingScriptHash` | Hash160 | processing contract hash |
|
||||||
| `candidates` + candidateKey | ByteArray | it flags inner ring candidate |
|
| `candidates` + candidateKey | ByteArray | it flags inner ring candidate |
|
||||||
| `config` + postfix | ByteArray | serialized config data |
|
| `config` + postfix | ByteArray | serialized config data |
|
||||||
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package frostfs
|
package frostfs
|
||||||
|
|
|
@ -26,9 +26,8 @@ const (
|
||||||
CandidateFeeConfigKey = "InnerRingCandidateFee"
|
CandidateFeeConfigKey = "InnerRingCandidateFee"
|
||||||
withdrawFeeConfigKey = "WithdrawFee"
|
withdrawFeeConfigKey = "WithdrawFee"
|
||||||
|
|
||||||
alphabetKey = "alphabet"
|
alphabetKey = "alphabet"
|
||||||
candidatesKey = "candidates"
|
candidatesKey = "candidates"
|
||||||
notaryDisabledKey = "notary"
|
|
||||||
|
|
||||||
processingContractKey = "processingScriptHash"
|
processingContractKey = "processingScriptHash"
|
||||||
|
|
||||||
|
@ -39,28 +38,22 @@ const (
|
||||||
ignoreDepositNotification = "\x57\x0b"
|
ignoreDepositNotification = "\x57\x0b"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var configPrefix = []byte("config")
|
||||||
configPrefix = []byte("config")
|
|
||||||
)
|
|
||||||
|
|
||||||
// _deploy sets up initial alphabet node keys.
|
// _deploy sets up initial alphabet node keys.
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
|
||||||
|
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
args := data.(struct {
|
args := data.(struct {
|
||||||
//TODO(@acid-ant): #9 remove notaryDisabled in future version
|
addrProc interop.Hash160
|
||||||
notaryDisabled bool
|
keys []interop.PublicKey
|
||||||
addrProc interop.Hash160
|
config [][]byte
|
||||||
keys []interop.PublicKey
|
|
||||||
config [][]byte
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(args.keys) == 0 {
|
if len(args.keys) == 0 {
|
||||||
|
@ -100,7 +93,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by sidechain committee.
|
// only by sidechain committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
blockHeight := ledger.CurrentIndex()
|
blockHeight := ledger.CurrentIndex()
|
||||||
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
||||||
alphabetCommittee := common.Multiaddress(alphabetKeys, true)
|
alphabetCommittee := common.Multiaddress(alphabetKeys, true)
|
||||||
|
@ -190,7 +183,7 @@ func InnerRingCandidateAdd(key interop.PublicKey) {
|
||||||
// It takes no more than 9000.0 GAS. Native GAS has precision 8, and
|
// It takes no more than 9000.0 GAS. Native GAS has precision 8, and
|
||||||
// FrostFS balance contract has precision 12. Values bigger than 9000.0 can
|
// FrostFS balance contract has precision 12. Values bigger than 9000.0 can
|
||||||
// break JSON limits for integers when precision is converted.
|
// break JSON limits for integers when precision is converted.
|
||||||
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
func OnNEP17Payment(from interop.Hash160, amount int, data any) {
|
||||||
rcv := data.(interop.Hash160)
|
rcv := data.(interop.Hash160)
|
||||||
if common.BytesEqual(rcv, []byte(ignoreDepositNotification)) {
|
if common.BytesEqual(rcv, []byte(ignoreDepositNotification)) {
|
||||||
return
|
return
|
||||||
|
@ -321,7 +314,7 @@ func Unbind(user []byte, keys []interop.PublicKey) {
|
||||||
|
|
||||||
// Config returns configuration value of FrostFS configuration. If the key does
|
// Config returns configuration value of FrostFS configuration. If the key does
|
||||||
// not exists, returns nil.
|
// not exists, returns nil.
|
||||||
func Config(key []byte) interface{} {
|
func Config(key []byte) any {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return getConfig(ctx, key)
|
return getConfig(ctx, key)
|
||||||
}
|
}
|
||||||
|
@ -376,7 +369,7 @@ func getAlphabetNodes(ctx storage.Context) []interop.PublicKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// getConfig returns the installed frostfs configuration value or nil if it is not set.
|
// getConfig returns the installed frostfs configuration value or nil if it is not set.
|
||||||
func getConfig(ctx storage.Context, key interface{}) interface{} {
|
func getConfig(ctx storage.Context, key any) interface{} {
|
||||||
postfix := key.([]byte)
|
postfix := key.([]byte)
|
||||||
storageKey := append(configPrefix, postfix...)
|
storageKey := append(configPrefix, postfix...)
|
||||||
|
|
||||||
|
@ -384,7 +377,7 @@ func getConfig(ctx storage.Context, key interface{}) interface{} {
|
||||||
}
|
}
|
||||||
|
|
||||||
// setConfig sets a frostfs configuration value in the contract storage.
|
// setConfig sets a frostfs configuration value in the contract storage.
|
||||||
func setConfig(ctx storage.Context, key, val interface{}) {
|
func setConfig(ctx storage.Context, key, val any) {
|
||||||
postfix := key.([]byte)
|
postfix := key.([]byte)
|
||||||
storageKey := append(configPrefix, postfix...)
|
storageKey := append(configPrefix, postfix...)
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,10 @@ FrostFSID contract does not produce notifications to process.
|
||||||
|
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|-----------------------------|------------|----------------------------------|
|
|-----------------------------|------------|----------------------------------|
|
||||||
| `processingScriptHash` | Hash160 | netmap contract hash |
|
| `processingScriptHash` | Hash160 | netmap contract hash |
|
||||||
| `containerScriptHash` | Hash160 | container contract hash |
|
| `containerScriptHash` | Hash160 | container contract hash |
|
||||||
| `o` + ownerID + publicKey | ByteArray | it flags owner's public key |
|
| `o` + ownerID + publicKey | ByteArray | it flags owner's public key |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package frostfsid
|
package frostfsid
|
||||||
|
|
|
@ -22,26 +22,21 @@ const (
|
||||||
const (
|
const (
|
||||||
netmapContractKey = "netmapScriptHash"
|
netmapContractKey = "netmapScriptHash"
|
||||||
containerContractKey = "containerScriptHash"
|
containerContractKey = "containerScriptHash"
|
||||||
notaryDisabledKey = "notary"
|
|
||||||
ownerKeysPrefix = 'o'
|
ownerKeysPrefix = 'o'
|
||||||
)
|
)
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
|
||||||
|
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
args := data.(struct {
|
args := data.(struct {
|
||||||
//TODO(@acid-ant): #9 remove notaryDisabled in future version
|
addrNetmap interop.Hash160
|
||||||
notaryDisabled bool
|
addrContainer interop.Hash160
|
||||||
addrNetmap interop.Hash160
|
|
||||||
addrContainer interop.Hash160
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrContainer) != interop.Hash160Len {
|
if len(args.addrNetmap) != interop.Hash160Len || len(args.addrContainer) != interop.Hash160Len {
|
||||||
|
@ -56,7 +51,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
panic("only committee can update contract")
|
panic("only committee can update contract")
|
||||||
}
|
}
|
||||||
|
@ -148,7 +143,7 @@ func Version() int {
|
||||||
return common.Version
|
return common.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUserInfo(ctx storage.Context, key interface{}) UserInfo {
|
func getUserInfo(ctx storage.Context, key any) UserInfo {
|
||||||
it := storage.Find(ctx, key, storage.KeysOnly|storage.RemovePrefix)
|
it := storage.Find(ctx, key, storage.KeysOnly|storage.RemovePrefix)
|
||||||
pubs := [][]byte{}
|
pubs := [][]byte{}
|
||||||
for iterator.Next(it) {
|
for iterator.Next(it) {
|
||||||
|
|
|
@ -32,15 +32,14 @@ in the network by invoking NewEpoch method.
|
||||||
|
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|-----------------------------|------------|-----------------------------------|
|
|-----------------------------|------------|-----------------------------------|
|
||||||
| `snapshotCount` | int | snapshot count |
|
| `snapshotCount` | int | snapshot count |
|
||||||
| `snapshotEpoch` | int | snapshot epoch |
|
| `snapshotEpoch` | int | snapshot epoch |
|
||||||
| `snapshotBlock` | int | snapshot block |
|
| `snapshotBlock` | int | snapshot block |
|
||||||
| `snapshot_` + snapshotNum | ByteArray | serialized '[]Node' array |
|
| `snapshot_` + snapshotNum | ByteArray | serialized '[]Node' array |
|
||||||
| `snapshotCurrent` | int | current snapshot |
|
| `snapshotCurrent` | int | current snapshot |
|
||||||
| `balanceScriptHash` | Hash160 | balance contract hash |
|
| `balanceScriptHash` | Hash160 | balance contract hash |
|
||||||
| `containerScriptHash` | Hash160 | container contract hash |
|
| `containerScriptHash` | Hash160 | container contract hash |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package netmap
|
package netmap
|
||||||
|
|
|
@ -43,8 +43,7 @@ type Node struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
notaryDisabledKey = "notary"
|
innerRingKey = "innerring"
|
||||||
innerRingKey = "innerring"
|
|
||||||
|
|
||||||
// DefaultSnapshotCount contains the number of previous snapshots stored by this contract.
|
// DefaultSnapshotCount contains the number of previous snapshots stored by this contract.
|
||||||
// Must be less than 255.
|
// Must be less than 255.
|
||||||
|
@ -67,19 +66,15 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
// _deploy function sets up initial list of inner ring public keys.
|
// _deploy function sets up initial list of inner ring public keys.
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
ctx := storage.GetContext()
|
ctx := storage.GetContext()
|
||||||
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
args := data.(struct {
|
||||||
|
addrBalance interop.Hash160
|
||||||
var args = data.(struct {
|
addrContainer interop.Hash160
|
||||||
//TODO(@acid-ant): #9 remove notaryDisabled in future version
|
keys []interop.PublicKey
|
||||||
notaryDisabled bool
|
config [][]byte
|
||||||
addrBalance interop.Hash160
|
version int
|
||||||
addrContainer interop.Hash160
|
|
||||||
keys []interop.PublicKey
|
|
||||||
config [][]byte
|
|
||||||
version int
|
|
||||||
})
|
})
|
||||||
|
|
||||||
ln := len(args.config)
|
ln := len(args.config)
|
||||||
|
@ -122,7 +117,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
panic("only committee can update contract")
|
panic("only committee can update contract")
|
||||||
}
|
}
|
||||||
|
@ -431,7 +426,7 @@ func SnapshotByEpoch(epoch int) []Node {
|
||||||
|
|
||||||
// Config returns configuration value of FrostFS configuration. If key does
|
// Config returns configuration value of FrostFS configuration. If key does
|
||||||
// not exists, returns nil.
|
// not exists, returns nil.
|
||||||
func Config(key []byte) interface{} {
|
func Config(key []byte) any {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
return getConfig(ctx, key)
|
return getConfig(ctx, key)
|
||||||
}
|
}
|
||||||
|
@ -543,14 +538,14 @@ func getSnapshot(ctx storage.Context, key string) []Node {
|
||||||
return []Node{}
|
return []Node{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getConfig(ctx storage.Context, key interface{}) interface{} {
|
func getConfig(ctx storage.Context, key any) interface{} {
|
||||||
postfix := key.([]byte)
|
postfix := key.([]byte)
|
||||||
storageKey := append(configPrefix, postfix...)
|
storageKey := append(configPrefix, postfix...)
|
||||||
|
|
||||||
return storage.Get(ctx, storageKey)
|
return storage.Get(ctx, storageKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setConfig(ctx storage.Context, key, val interface{}) {
|
func setConfig(ctx storage.Context, key, val any) {
|
||||||
postfix := key.([]byte)
|
postfix := key.([]byte)
|
||||||
storageKey := append(configPrefix, postfix...)
|
storageKey := append(configPrefix, postfix...)
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ type RecordState struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update updates NameService contract.
|
// Update updates NameService contract.
|
||||||
func Update(nef []byte, manifest string, data interface{}) {
|
func Update(nef []byte, manifest string, data any) {
|
||||||
checkCommittee()
|
checkCommittee()
|
||||||
// Calculating keys and serializing requires calling
|
// Calculating keys and serializing requires calling
|
||||||
// std and crypto contracts. This can be helpful on update
|
// std and crypto contracts. This can be helpful on update
|
||||||
|
@ -87,9 +87,9 @@ func Update(nef []byte, manifest string, data interface{}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// _deploy initializes defaults (total supply and registration price) on contract deploy.
|
// _deploy initializes defaults (total supply and registration price) on contract deploy.
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -128,10 +128,10 @@ func OwnerOf(tokenID []byte) interop.Hash160 {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Properties returns a domain name and an expiration date of the specified domain.
|
// Properties returns a domain name and an expiration date of the specified domain.
|
||||||
func Properties(tokenID []byte) map[string]interface{} {
|
func Properties(tokenID []byte) map[string]any {
|
||||||
ctx := storage.GetReadOnlyContext()
|
ctx := storage.GetReadOnlyContext()
|
||||||
ns := getNameState(ctx, tokenID)
|
ns := getNameState(ctx, tokenID)
|
||||||
return map[string]interface{}{
|
return map[string]any{
|
||||||
"name": ns.Name,
|
"name": ns.Name,
|
||||||
"expiration": ns.Expiration,
|
"expiration": ns.Expiration,
|
||||||
}
|
}
|
||||||
|
@ -166,7 +166,7 @@ func TokensOf(owner interop.Hash160) iterator.Iterator {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transfer transfers the domain with the specified name to a new owner.
|
// Transfer transfers the domain with the specified name to a new owner.
|
||||||
func Transfer(to interop.Hash160, tokenID []byte, data interface{}) bool {
|
func Transfer(to interop.Hash160, tokenID []byte, data any) bool {
|
||||||
if !isValid(to) {
|
if !isValid(to) {
|
||||||
panic(`invalid receiver`)
|
panic(`invalid receiver`)
|
||||||
}
|
}
|
||||||
|
@ -478,7 +478,7 @@ func updateBalance(ctx storage.Context, tokenId []byte, acc interop.Hash160, dif
|
||||||
|
|
||||||
// postTransfer sends Transfer notification to the network and calls onNEP11Payment
|
// postTransfer sends Transfer notification to the network and calls onNEP11Payment
|
||||||
// method.
|
// method.
|
||||||
func postTransfer(from, to interop.Hash160, tokenID []byte, data interface{}) {
|
func postTransfer(from, to interop.Hash160, tokenID []byte, data any) {
|
||||||
runtime.Notify("Transfer", from, to, 1, tokenID)
|
runtime.Notify("Transfer", from, to, 1, tokenID)
|
||||||
if management.GetContract(to) != nil {
|
if management.GetContract(to) != nil {
|
||||||
contract.Call(to, "onNEP11Payment", contract.All, from, 1, tokenID, data)
|
contract.Call(to, "onNEP11Payment", contract.All, from, 1, tokenID, data)
|
||||||
|
|
|
@ -17,7 +17,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// _deploy function sets up initial list of inner ring public keys.
|
// _deploy function sets up initial list of inner ring public keys.
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func storageKey(prefix Kind, entityName, name string) []byte {
|
func storageKey(prefix Kind, entityName, name string) []byte {
|
||||||
|
|
|
@ -21,9 +21,8 @@ Processing contract does not produce notifications to process.
|
||||||
|
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
| Key | Value | Description |
|
| Key | Value | Description |
|
||||||
|-----------------------------|------------|----------------------------------|
|
|-----------------------------|------------|----------------------------------|
|
||||||
| `frostfsScriptHash` | Hash160 | frostFS contract hash |
|
| `frostfsScriptHash` | Hash160 | frostFS contract hash |
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package processing
|
package processing
|
||||||
|
|
|
@ -19,16 +19,16 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
|
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
|
||||||
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
func OnNEP17Payment(from interop.Hash160, amount int, data any) {
|
||||||
caller := runtime.GetCallingScriptHash()
|
caller := runtime.GetCallingScriptHash()
|
||||||
if !common.BytesEqual(caller, []byte(gas.Hash)) {
|
if !common.BytesEqual(caller, []byte(gas.Hash)) {
|
||||||
common.AbortWithMessage("processing contract accepts GAS only")
|
common.AbortWithMessage("processing contract accepts GAS only")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by the sidechain committee.
|
// only by the sidechain committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
blockHeight := ledger.CurrentIndex()
|
blockHeight := ledger.CurrentIndex()
|
||||||
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
alphabetKeys := roles.GetDesignatedByRole(roles.NeoFSAlphabet, uint32(blockHeight+1))
|
||||||
alphabetCommittee := common.Multiaddress(alphabetKeys, true)
|
alphabetCommittee := common.Multiaddress(alphabetKeys, true)
|
||||||
|
|
|
@ -21,6 +21,5 @@ Proxy contract does not produce notifications to process.
|
||||||
# Contract storage scheme
|
# Contract storage scheme
|
||||||
|
|
||||||
Proxy contract does not use storage
|
Proxy contract does not use storage
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package proxy
|
package proxy
|
||||||
|
|
|
@ -10,16 +10,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
|
// OnNEP17Payment is a callback for NEP-17 compatible native GAS contract.
|
||||||
func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
|
func OnNEP17Payment(from interop.Hash160, amount int, data any) {
|
||||||
caller := runtime.GetCallingScriptHash()
|
caller := runtime.GetCallingScriptHash()
|
||||||
if !common.BytesEqual(caller, []byte(gas.Hash)) {
|
if !common.BytesEqual(caller, []byte(gas.Hash)) {
|
||||||
common.AbortWithMessage("proxy contract accepts GAS only")
|
common.AbortWithMessage("proxy contract accepts GAS only")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
func _deploy(data any, isUpdate bool) {
|
||||||
if isUpdate {
|
if isUpdate {
|
||||||
args := data.([]interface{})
|
args := data.([]any)
|
||||||
common.CheckVersion(args[len(args)-1].(int))
|
common.CheckVersion(args[len(args)-1].(int))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func _deploy(data interface{}, isUpdate bool) {
|
||||||
|
|
||||||
// Update method updates contract source code and manifest. It can be invoked
|
// Update method updates contract source code and manifest. It can be invoked
|
||||||
// only by committee.
|
// only by committee.
|
||||||
func Update(script []byte, manifest []byte, data interface{}) {
|
func Update(script []byte, manifest []byte, data any) {
|
||||||
if !common.HasUpdateAccess() {
|
if !common.HasUpdateAccess() {
|
||||||
panic("only committee can update contract")
|
panic("only committee can update contract")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
|
@ -1,25 +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
|
|
|
@ -1,122 +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 (
|
|
||||||
notaryDisabledKey = "notary"
|
|
||||||
reputationValuePrefix = 'r'
|
|
||||||
reputationCountPrefix = 'c'
|
|
||||||
)
|
|
||||||
|
|
||||||
func _deploy(data interface{}, isUpdate bool) {
|
|
||||||
common.RmAndCheckNotaryDisabledKey(data, notaryDisabledKey)
|
|
||||||
|
|
||||||
if isUpdate {
|
|
||||||
args := data.([]interface{})
|
|
||||||
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 interface{}) {
|
|
||||||
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 interface{} = epoch
|
|
||||||
|
|
||||||
return append(buf.([]byte), peerID...)
|
|
||||||
}
|
|
|
@ -1,128 +0,0 @@
|
||||||
// Package audit contains RPC wrappers for Audit contract.
|
|
||||||
//
|
|
||||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <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)
|
|
||||||
}
|
|
|
@ -1,207 +0,0 @@
|
||||||
// Package reputation contains RPC wrappers for Reputation contract.
|
|
||||||
//
|
|
||||||
// Code generated by neo-go contract generate-rpcwrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <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
|
|
||||||
}
|
|
|
@ -21,13 +21,12 @@ const alphabetPath = "../alphabet"
|
||||||
func deployAlphabetContract(t *testing.T, e *neotest.Executor, addrNetmap, addrProxy util.Uint160, name string, index, total int64) util.Uint160 {
|
func deployAlphabetContract(t *testing.T, e *neotest.Executor, addrNetmap, addrProxy util.Uint160, name string, index, total int64) util.Uint160 {
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, alphabetPath, path.Join(alphabetPath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, alphabetPath, path.Join(alphabetPath, "config.yml"))
|
||||||
|
|
||||||
args := make([]interface{}, 6)
|
args := make([]any, 5)
|
||||||
args[0] = false
|
args[0] = addrNetmap
|
||||||
args[1] = addrNetmap
|
args[1] = addrProxy
|
||||||
args[2] = addrProxy
|
args[2] = name
|
||||||
args[3] = name
|
args[3] = index
|
||||||
args[4] = index
|
args[4] = total
|
||||||
args[5] = total
|
|
||||||
|
|
||||||
e.DeployContract(t, c, args)
|
e.DeployContract(t, c, args)
|
||||||
return c.Hash
|
return c.Hash
|
||||||
|
@ -88,8 +87,8 @@ func TestVote(t *testing.T) {
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
cNewAlphabet := c.WithSigners(newAlphabet)
|
cNewAlphabet := c.WithSigners(newAlphabet)
|
||||||
|
|
||||||
cNewAlphabet.InvokeFail(t, common.ErrAlphabetWitnessFailed, method, int64(0), []interface{}{newAlphabetPub})
|
cNewAlphabet.InvokeFail(t, common.ErrAlphabetWitnessFailed, method, int64(0), []any{newAlphabetPub})
|
||||||
c.InvokeFail(t, "invalid epoch", method, int64(1), []interface{}{newAlphabetPub})
|
c.InvokeFail(t, "invalid epoch", method, int64(1), []any{newAlphabetPub})
|
||||||
|
|
||||||
setAlphabetRole(t, e, newAlphabetPub)
|
setAlphabetRole(t, e, newAlphabetPub)
|
||||||
transferNeoToContract(t, c)
|
transferNeoToContract(t, c)
|
||||||
|
@ -109,7 +108,7 @@ func TestVote(t *testing.T) {
|
||||||
newInvoker := neoInvoker.WithSigners(newAlphabet)
|
newInvoker := neoInvoker.WithSigners(newAlphabet)
|
||||||
|
|
||||||
newInvoker.Invoke(t, stackitem.NewBool(true), "registerCandidate", newAlphabetPub)
|
newInvoker.Invoke(t, stackitem.NewBool(true), "registerCandidate", newAlphabetPub)
|
||||||
c.Invoke(t, stackitem.Null{}, method, int64(0), []interface{}{newAlphabetPub})
|
c.Invoke(t, stackitem.Null{}, method, int64(0), []any{newAlphabetPub})
|
||||||
|
|
||||||
// wait one block util
|
// wait one block util
|
||||||
// a new committee is accepted
|
// a new committee is accepted
|
||||||
|
@ -139,7 +138,7 @@ func setAlphabetRole(t *testing.T, e *neotest.Executor, new []byte) {
|
||||||
designInvoker := e.CommitteeInvoker(designSH)
|
designInvoker := e.CommitteeInvoker(designSH)
|
||||||
|
|
||||||
// set committee as NeoFSAlphabet
|
// set committee as NeoFSAlphabet
|
||||||
designInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(noderoles.NeoFSAlphabet), []interface{}{new})
|
designInvoker.Invoke(t, stackitem.Null{}, "designateAsRole", int64(noderoles.NeoFSAlphabet), []any{new})
|
||||||
}
|
}
|
||||||
|
|
||||||
func getAlphabetAcc(t *testing.T, e *neotest.Executor) *wallet.Account {
|
func getAlphabetAcc(t *testing.T, e *neotest.Executor) *wallet.Account {
|
||||||
|
|
|
@ -14,10 +14,9 @@ const balancePath = "../balance"
|
||||||
func deployBalanceContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
|
func deployBalanceContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
||||||
|
|
||||||
args := make([]interface{}, 3)
|
args := make([]any, 3)
|
||||||
args[0] = false
|
args[0] = addrNetmap
|
||||||
args[1] = addrNetmap
|
args[1] = addrContainer
|
||||||
args[2] = addrContainer
|
|
||||||
|
|
||||||
e.DeployContract(t, c, args)
|
e.DeployContract(t, c, args)
|
||||||
return c.Hash
|
return c.Hash
|
||||||
|
|
|
@ -24,18 +24,17 @@ import (
|
||||||
const containerPath = "../container"
|
const containerPath = "../container"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
containerFee = 0_0100_0000
|
containerFee = 0o_0100_0000
|
||||||
containerAliasFee = 0_0050_0000
|
containerAliasFee = 0o_0050_0000
|
||||||
)
|
)
|
||||||
|
|
||||||
func deployContainerContract(t *testing.T, e *neotest.Executor, addrNetmap, addrBalance, addrNNS util.Uint160) util.Uint160 {
|
func deployContainerContract(t *testing.T, e *neotest.Executor, addrNetmap, addrBalance, addrNNS util.Uint160) util.Uint160 {
|
||||||
args := make([]interface{}, 6)
|
args := make([]any, 5)
|
||||||
args[0] = int64(0)
|
args[0] = addrNetmap
|
||||||
args[1] = addrNetmap
|
args[1] = addrBalance
|
||||||
args[2] = addrBalance
|
args[2] = util.Uint160{} // not needed for now
|
||||||
args[3] = util.Uint160{} // not needed for now
|
args[3] = addrNNS
|
||||||
args[4] = addrNNS
|
args[4] = "frostfs"
|
||||||
args[5] = "frostfs"
|
|
||||||
|
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
||||||
e.DeployContract(t, c, args)
|
e.DeployContract(t, c, args)
|
||||||
|
@ -164,7 +163,6 @@ func checkContainerList(t *testing.T, c *neotest.ContractInvoker, expected [][]b
|
||||||
}
|
}
|
||||||
require.ElementsMatch(t, expected, actual)
|
require.ElementsMatch(t, expected, actual)
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestContainerPut(t *testing.T) {
|
func TestContainerPut(t *testing.T) {
|
||||||
|
@ -173,7 +171,7 @@ func TestContainerPut(t *testing.T) {
|
||||||
acc := c.NewAccount(t)
|
acc := c.NewAccount(t)
|
||||||
cnt := dummyContainer(acc)
|
cnt := dummyContainer(acc)
|
||||||
|
|
||||||
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token}
|
putArgs := []any{cnt.value, cnt.sig, cnt.pub, cnt.token}
|
||||||
c.InvokeFail(t, "insufficient balance to create container", "put", putArgs...)
|
c.InvokeFail(t, "insufficient balance to create container", "put", putArgs...)
|
||||||
|
|
||||||
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
||||||
|
@ -189,7 +187,7 @@ func TestContainerPut(t *testing.T) {
|
||||||
|
|
||||||
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
||||||
|
|
||||||
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token, "mycnt", ""}
|
putArgs := []any{cnt.value, cnt.sig, cnt.pub, cnt.token, "mycnt", ""}
|
||||||
t.Run("no fee for alias", func(t *testing.T) {
|
t.Run("no fee for alias", func(t *testing.T) {
|
||||||
c.InvokeFail(t, "insufficient balance to create container", "putNamed", putArgs...)
|
c.InvokeFail(t, "insufficient balance to create container", "putNamed", putArgs...)
|
||||||
})
|
})
|
||||||
|
@ -224,12 +222,13 @@ func TestContainerPut(t *testing.T) {
|
||||||
|
|
||||||
balanceMint(t, cBal, acc, (containerFee+containerAliasFee)*1, []byte{})
|
balanceMint(t, cBal, acc, (containerFee+containerAliasFee)*1, []byte{})
|
||||||
|
|
||||||
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token, "domain", "cdn"}
|
putArgs := []any{cnt.value, cnt.sig, cnt.pub, cnt.token, "domain", "cdn"}
|
||||||
c2 := c.WithSigners(c.Committee, acc)
|
c2 := c.WithSigners(c.Committee, acc)
|
||||||
c2.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
|
c2.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
|
||||||
|
|
||||||
expected = stackitem.NewArray([]stackitem.Item{
|
expected = stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray([]byte(base58.Encode(cnt.id[:])))})
|
stackitem.NewByteArray([]byte(base58.Encode(cnt.id[:]))),
|
||||||
|
})
|
||||||
cNNS.Invoke(t, expected, "resolve", "domain.cdn", int64(nns.TXT))
|
cNNS.Invoke(t, expected, "resolve", "domain.cdn", int64(nns.TXT))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -244,7 +243,7 @@ func TestContainerPut(t *testing.T) {
|
||||||
acc := c.NewAccount(t)
|
acc := c.NewAccount(t)
|
||||||
balanceMint(t, cBal, acc, totalPrice*totalContainers, []byte{})
|
balanceMint(t, cBal, acc, totalPrice*totalContainers, []byte{})
|
||||||
cnt := dummyContainer(acc)
|
cnt := dummyContainer(acc)
|
||||||
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token, "precreated", ""}
|
putArgs := []any{cnt.value, cnt.sig, cnt.pub, cnt.token, "precreated", ""}
|
||||||
c.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
|
c.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
|
||||||
|
|
||||||
txs := make([]*transaction.Transaction, 0, containerPerBlock)
|
txs := make([]*transaction.Transaction, 0, containerPerBlock)
|
||||||
|
@ -314,7 +313,7 @@ func TestContainerDelete(t *testing.T) {
|
||||||
|
|
||||||
t.Run("gas costs are the same for different epochs", func(t *testing.T) {
|
t.Run("gas costs are the same for different epochs", func(t *testing.T) {
|
||||||
_, cnt2 := addContainer(t, c, cBal)
|
_, cnt2 := addContainer(t, c, cBal)
|
||||||
args := []interface{}{cnt2.id[:], cnt2.sig, cnt2.pub, cnt2.token}
|
args := []any{cnt2.id[:], cnt2.sig, cnt2.pub, cnt2.token}
|
||||||
|
|
||||||
tx := c.PrepareInvoke(t, "delete", args...)
|
tx := c.PrepareInvoke(t, "delete", args...)
|
||||||
for _, e := range []int{126, 127, 128, 129, 65536} {
|
for _, e := range []int{126, 127, 128, 129, 65536} {
|
||||||
|
@ -405,7 +404,7 @@ func TestContainerSetEACL(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
e := dummyEACL(cnt.id)
|
e := dummyEACL(cnt.id)
|
||||||
setArgs := []interface{}{e.value, e.sig, e.pub, e.token}
|
setArgs := []any{e.value, e.sig, e.pub, e.token}
|
||||||
cAcc := c.WithSigners(acc)
|
cAcc := c.WithSigners(acc)
|
||||||
cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "setEACL", setArgs...)
|
cAcc.InvokeFail(t, common.ErrAlphabetWitnessFailed, "setEACL", setArgs...)
|
||||||
|
|
||||||
|
|
|
@ -21,24 +21,24 @@ import (
|
||||||
const frostfsPath = "../frostfs"
|
const frostfsPath = "../frostfs"
|
||||||
|
|
||||||
func deployFrostFSContract(t *testing.T, e *neotest.Executor, addrProc util.Uint160,
|
func deployFrostFSContract(t *testing.T, e *neotest.Executor, addrProc util.Uint160,
|
||||||
pubs keys.PublicKeys, config ...interface{}) util.Uint160 {
|
pubs keys.PublicKeys, config ...any,
|
||||||
args := make([]interface{}, 5)
|
) util.Uint160 {
|
||||||
args[0] = false
|
args := make([]any, 3)
|
||||||
args[1] = addrProc
|
args[0] = addrProc
|
||||||
|
|
||||||
arr := make([]interface{}, len(pubs))
|
arr := make([]any, len(pubs))
|
||||||
for i := range pubs {
|
for i := range pubs {
|
||||||
arr[i] = pubs[i].Bytes()
|
arr[i] = pubs[i].Bytes()
|
||||||
}
|
}
|
||||||
args[2] = arr
|
args[1] = arr
|
||||||
args[3] = append([]interface{}{}, config...)
|
args[2] = append([]any{}, config...)
|
||||||
|
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, frostfsPath, path.Join(frostfsPath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, frostfsPath, path.Join(frostfsPath, "config.yml"))
|
||||||
e.DeployContract(t, c, args)
|
e.DeployContract(t, c, args)
|
||||||
return c.Hash
|
return c.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
func newFrostFSInvoker(t *testing.T, n int, config ...interface{}) (*neotest.ContractInvoker, neotest.Signer, keys.PublicKeys) {
|
func newFrostFSInvoker(t *testing.T, n int, config ...any) (*neotest.ContractInvoker, neotest.Signer, keys.PublicKeys) {
|
||||||
e := newExecutor(t)
|
e := newExecutor(t)
|
||||||
|
|
||||||
accounts := make([]*wallet.Account, n)
|
accounts := make([]*wallet.Account, n)
|
||||||
|
|
|
@ -17,10 +17,9 @@ import (
|
||||||
const frostfsidPath = "../frostfsid"
|
const frostfsidPath = "../frostfsid"
|
||||||
|
|
||||||
func deployFrostFSIDContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
|
func deployFrostFSIDContract(t *testing.T, e *neotest.Executor, addrNetmap, addrContainer util.Uint160) util.Uint160 {
|
||||||
args := make([]interface{}, 5)
|
args := make([]any, 2)
|
||||||
args[0] = false
|
args[0] = addrNetmap
|
||||||
args[1] = addrNetmap
|
args[1] = addrContainer
|
||||||
args[2] = addrContainer
|
|
||||||
|
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, frostfsidPath, path.Join(frostfsidPath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, frostfsidPath, path.Join(frostfsidPath, "config.yml"))
|
||||||
e.DeployContract(t, c, args)
|
e.DeployContract(t, c, args)
|
||||||
|
@ -57,7 +56,7 @@ func TestFrostFSID_AddKey(t *testing.T) {
|
||||||
acc := e.NewAccount(t)
|
acc := e.NewAccount(t)
|
||||||
owner := signerToOwner(acc)
|
owner := signerToOwner(acc)
|
||||||
e.Invoke(t, stackitem.Null{}, "addKey", owner,
|
e.Invoke(t, stackitem.Null{}, "addKey", owner,
|
||||||
[]interface{}{pubs[0], pubs[1]})
|
[]any{pubs[0], pubs[1]})
|
||||||
|
|
||||||
sort.Slice(pubs[:2], func(i, j int) bool {
|
sort.Slice(pubs[:2], func(i, j int) bool {
|
||||||
return bytes.Compare(pubs[i], pubs[j]) == -1
|
return bytes.Compare(pubs[i], pubs[j]) == -1
|
||||||
|
@ -69,8 +68,8 @@ func TestFrostFSID_AddKey(t *testing.T) {
|
||||||
e.Invoke(t, stackitem.NewArray(arr), "key", owner)
|
e.Invoke(t, stackitem.NewArray(arr), "key", owner)
|
||||||
|
|
||||||
t.Run("multiple addKey per block", func(t *testing.T) {
|
t.Run("multiple addKey per block", func(t *testing.T) {
|
||||||
tx1 := e.PrepareInvoke(t, "addKey", owner, []interface{}{pubs[2]})
|
tx1 := e.PrepareInvoke(t, "addKey", owner, []any{pubs[2]})
|
||||||
tx2 := e.PrepareInvoke(t, "addKey", owner, []interface{}{pubs[3], pubs[4]})
|
tx2 := e.PrepareInvoke(t, "addKey", owner, []any{pubs[3], pubs[4]})
|
||||||
e.AddNewBlock(t, tx1, tx2)
|
e.AddNewBlock(t, tx1, tx2)
|
||||||
e.CheckHalt(t, tx1.Hash(), stackitem.Null{})
|
e.CheckHalt(t, tx1.Hash(), stackitem.Null{})
|
||||||
e.CheckHalt(t, tx2.Hash(), stackitem.Null{})
|
e.CheckHalt(t, tx2.Hash(), stackitem.Null{})
|
||||||
|
@ -89,7 +88,7 @@ func TestFrostFSID_AddKey(t *testing.T) {
|
||||||
})
|
})
|
||||||
|
|
||||||
e.Invoke(t, stackitem.Null{}, "removeKey", owner,
|
e.Invoke(t, stackitem.Null{}, "removeKey", owner,
|
||||||
[]interface{}{pubs[1], pubs[5]})
|
[]any{pubs[1], pubs[5]})
|
||||||
arr = []stackitem.Item{
|
arr = []stackitem.Item{
|
||||||
stackitem.NewBuffer(pubs[0]),
|
stackitem.NewBuffer(pubs[0]),
|
||||||
stackitem.NewBuffer(pubs[2]),
|
stackitem.NewBuffer(pubs[2]),
|
||||||
|
@ -99,8 +98,8 @@ func TestFrostFSID_AddKey(t *testing.T) {
|
||||||
e.Invoke(t, stackitem.NewArray(arr), "key", owner)
|
e.Invoke(t, stackitem.NewArray(arr), "key", owner)
|
||||||
|
|
||||||
t.Run("multiple removeKey per block", func(t *testing.T) {
|
t.Run("multiple removeKey per block", func(t *testing.T) {
|
||||||
tx1 := e.PrepareInvoke(t, "removeKey", owner, []interface{}{pubs[2]})
|
tx1 := e.PrepareInvoke(t, "removeKey", owner, []any{pubs[2]})
|
||||||
tx2 := e.PrepareInvoke(t, "removeKey", owner, []interface{}{pubs[0], pubs[4]})
|
tx2 := e.PrepareInvoke(t, "removeKey", owner, []any{pubs[0], pubs[4]})
|
||||||
e.AddNewBlock(t, tx1, tx2)
|
e.AddNewBlock(t, tx1, tx2)
|
||||||
e.CheckHalt(t, tx1.Hash(), stackitem.Null{})
|
e.CheckHalt(t, tx1.Hash(), stackitem.Null{})
|
||||||
e.CheckHalt(t, tx2.Hash(), stackitem.Null{})
|
e.CheckHalt(t, tx2.Hash(), stackitem.Null{})
|
||||||
|
|
|
@ -20,23 +20,22 @@ import (
|
||||||
|
|
||||||
const netmapPath = "../netmap"
|
const netmapPath = "../netmap"
|
||||||
|
|
||||||
func deployNetmapContract(t *testing.T, e *neotest.Executor, addrBalance, addrContainer util.Uint160, config ...interface{}) util.Uint160 {
|
func deployNetmapContract(t *testing.T, e *neotest.Executor, addrBalance, addrContainer util.Uint160, config ...any) util.Uint160 {
|
||||||
_, pubs, ok := vm.ParseMultiSigContract(e.Committee.Script())
|
_, pubs, ok := vm.ParseMultiSigContract(e.Committee.Script())
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
||||||
args := make([]interface{}, 5)
|
args := make([]any, 4)
|
||||||
args[0] = false
|
args[0] = addrBalance
|
||||||
args[1] = addrBalance
|
args[1] = addrContainer
|
||||||
args[2] = addrContainer
|
args[2] = []any{pubs[0]}
|
||||||
args[3] = []interface{}{pubs[0]}
|
args[3] = append([]any{}, config...)
|
||||||
args[4] = append([]interface{}{}, config...)
|
|
||||||
|
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
||||||
e.DeployContract(t, c, args)
|
e.DeployContract(t, c, args)
|
||||||
return c.Hash
|
return c.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
func newNetmapInvoker(t *testing.T, config ...interface{}) *neotest.ContractInvoker {
|
func newNetmapInvoker(t *testing.T, config ...any) *neotest.ContractInvoker {
|
||||||
e := newExecutor(t)
|
e := newExecutor(t)
|
||||||
|
|
||||||
ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
||||||
|
|
|
@ -115,7 +115,8 @@ func TestNNSRegister(t *testing.T) {
|
||||||
|
|
||||||
expected = stackitem.NewArray([]stackitem.Item{
|
expected = stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray([]byte("first TXT record")),
|
stackitem.NewByteArray([]byte("first TXT record")),
|
||||||
stackitem.NewByteArray([]byte("second TXT record"))})
|
stackitem.NewByteArray([]byte("second TXT record")),
|
||||||
|
})
|
||||||
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
|
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
|
||||||
|
|
||||||
cAcc.Invoke(t, stackitem.Null{}, "setRecord",
|
cAcc.Invoke(t, stackitem.Null{}, "setRecord",
|
||||||
|
@ -123,7 +124,8 @@ func TestNNSRegister(t *testing.T) {
|
||||||
|
|
||||||
expected = stackitem.NewArray([]stackitem.Item{
|
expected = stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray([]byte("replaced first")),
|
stackitem.NewByteArray([]byte("replaced first")),
|
||||||
stackitem.NewByteArray([]byte("second TXT record"))})
|
stackitem.NewByteArray([]byte("second TXT record")),
|
||||||
|
})
|
||||||
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
|
c.Invoke(t, expected, "getRecords", "testdomain.com", int64(nns.TXT))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,8 +141,8 @@ func TestTLDRecord(t *testing.T) {
|
||||||
func TestNNSRegisterMulti(t *testing.T) {
|
func TestNNSRegisterMulti(t *testing.T) {
|
||||||
c := newNNSInvoker(t, true)
|
c := newNNSInvoker(t, true)
|
||||||
|
|
||||||
newArgs := func(domain string, account neotest.Signer) []interface{} {
|
newArgs := func(domain string, account neotest.Signer) []any {
|
||||||
return []interface{}{
|
return []any{
|
||||||
domain, account.ScriptHash(), "doesnt@matter.com",
|
domain, account.ScriptHash(), "doesnt@matter.com",
|
||||||
int64(101), int64(102), int64(103), int64(104),
|
int64(101), int64(102), int64(103), int64(104),
|
||||||
}
|
}
|
||||||
|
@ -185,7 +187,8 @@ func TestNNSRegisterMulti(t *testing.T) {
|
||||||
c2.Invoke(t, stackitem.Null{}, "addRecord",
|
c2.Invoke(t, stackitem.Null{}, "addRecord",
|
||||||
"cdn.mainnet.fs.neo.com", int64(nns.A), "166.15.14.13")
|
"cdn.mainnet.fs.neo.com", int64(nns.A), "166.15.14.13")
|
||||||
result := stackitem.NewArray([]stackitem.Item{
|
result := stackitem.NewArray([]stackitem.Item{
|
||||||
stackitem.NewByteArray([]byte("166.15.14.13"))})
|
stackitem.NewByteArray([]byte("166.15.14.13")),
|
||||||
|
})
|
||||||
c2.Invoke(t, result, "resolve", "cdn.mainnet.fs.neo.com", int64(nns.A))
|
c2.Invoke(t, result, "resolve", "cdn.mainnet.fs.neo.com", int64(nns.A))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,7 +265,8 @@ func TestExpiration(t *testing.T) {
|
||||||
checkProperties := func(t *testing.T, expiration uint64) {
|
checkProperties := func(t *testing.T, expiration uint64) {
|
||||||
expected := stackitem.NewMapWithValue([]stackitem.MapElement{
|
expected := stackitem.NewMapWithValue([]stackitem.MapElement{
|
||||||
{Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")},
|
{Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")},
|
||||||
{Key: stackitem.Make("expiration"), Value: stackitem.Make(expiration)}})
|
{Key: stackitem.Make("expiration"), Value: stackitem.Make(expiration)},
|
||||||
|
})
|
||||||
s, err := c.TestInvoke(t, "properties", "testdomain.com")
|
s, err := c.TestInvoke(t, "properties", "testdomain.com")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, expected.Value(), s.Top().Item().Value())
|
require.Equal(t, expected.Value(), s.Top().Item().Value())
|
||||||
|
@ -351,7 +355,8 @@ func TestNNSRenew(t *testing.T) {
|
||||||
c1.Invoke(t, ts, "renew", "testdomain.com")
|
c1.Invoke(t, ts, "renew", "testdomain.com")
|
||||||
expected := stackitem.NewMapWithValue([]stackitem.MapElement{
|
expected := stackitem.NewMapWithValue([]stackitem.MapElement{
|
||||||
{Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")},
|
{Key: stackitem.Make("name"), Value: stackitem.Make("testdomain.com")},
|
||||||
{Key: stackitem.Make("expiration"), Value: stackitem.Make(ts)}})
|
{Key: stackitem.Make("expiration"), Value: stackitem.Make(ts)},
|
||||||
|
})
|
||||||
cAcc.Invoke(t, expected, "properties", "testdomain.com")
|
cAcc.Invoke(t, expected, "properties", "testdomain.com")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ const processingPath = "../processing"
|
||||||
func deployProcessingContract(t *testing.T, e *neotest.Executor, addrFrostFS util.Uint160) util.Uint160 {
|
func deployProcessingContract(t *testing.T, e *neotest.Executor, addrFrostFS util.Uint160) util.Uint160 {
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, processingPath, path.Join(processingPath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, processingPath, path.Join(processingPath, "config.yml"))
|
||||||
|
|
||||||
args := make([]interface{}, 1)
|
args := make([]any, 1)
|
||||||
args[0] = addrFrostFS
|
args[0] = addrFrostFS
|
||||||
|
|
||||||
e.DeployContract(t, c, args)
|
e.DeployContract(t, c, args)
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
const proxyPath = "../proxy"
|
const proxyPath = "../proxy"
|
||||||
|
|
||||||
func deployProxyContract(t *testing.T, e *neotest.Executor, addrNetmap util.Uint160) util.Uint160 {
|
func deployProxyContract(t *testing.T, e *neotest.Executor, addrNetmap util.Uint160) util.Uint160 {
|
||||||
args := make([]interface{}, 1)
|
args := make([]any, 1)
|
||||||
args[0] = addrNetmap
|
args[0] = addrNetmap
|
||||||
|
|
||||||
c := neotest.CompileFile(t, e.CommitteeHash, proxyPath, path.Join(proxyPath, "config.yml"))
|
c := neotest.CompileFile(t, e.CommitteeHash, proxyPath, path.Join(proxyPath, "config.yml"))
|
||||||
|
|
|
@ -1,80 +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"))
|
|
||||||
|
|
||||||
args := make([]interface{}, 1)
|
|
||||||
args[0] = false
|
|
||||||
|
|
||||||
e.DeployContract(t, c, args)
|
|
||||||
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))
|
|
||||||
}
|
|
Loading…
Add table
Reference in a new issue