Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/support meta with big objects #457

Merged
merged 4 commits into from
Dec 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 57 additions & 18 deletions contracts/container/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,37 +248,67 @@ func Update(script []byte, manifest []byte, data any) {
// created using [Put] ([PutMeta]) with enabled meta-on-chain option.
func SubmitObjectPut(metaInformation []byte, sigs [][]interop.Signature) {
metaMap := std.Deserialize(metaInformation).(map[string]any)
cID := getFromMap(metaMap, "cid").(interop.Hash256)

// required

cID := requireMapValue(metaMap, "cid").(interop.Hash256)
if len(cID) != interop.Hash256Len {
panic("incorrect container ID")
}
if storage.Get(storage.GetContext(), append([]byte{containersWithMetaPrefix}, cID...)) == nil {
panic("container does not support meta-on-chain")
}
oID := getFromMap(metaMap, "oid").(interop.Hash256)
oID := requireMapValue(metaMap, "oid").(interop.Hash256)
if len(oID) != interop.Hash256Len {
panic("incorrect object ID")
}
magic := getFromMap(metaMap, "network").(int)
_ = requireMapValue(metaMap, "size").(int)
vub := requireMapValue(metaMap, "validUntil").(int)
if vub <= ledger.CurrentIndex() {
panic("incorrect vub: exceeded")
}
magic := requireMapValue(metaMap, "network").(int)
if magic != runtime.GetNetwork() {
panic("incorrect network magic")
}
_ = getFromMap(metaMap, "size").(int)
deleted := getFromMap(metaMap, "deleted").([]interop.Hash256)
for i, d := range deleted {
if len(d) != interop.Hash256Len {
panic("incorrect " + std.Itoa10(i) + " deleted object")

// optional

if v, ok := getFromMap(metaMap, "type"); ok {
typ := v.(int)
switch typ {
case 0, 1, 2, 3, 4: // regular, tombstone, storage group, lock, link
default:
panic("incorrect object type")
}
}
locked := getFromMap(metaMap, "locked").([]interop.Hash256)
for i, l := range locked {
if len(l) != interop.Hash256Len {
panic("incorrect " + std.Itoa10(i) + " locked object")
if v, ok := getFromMap(metaMap, "firstPart"); ok {
firstPart := v.(interop.Hash256)
if len(firstPart) != interop.Hash256Len {
panic("incorrect first part object ID")
}
}
vub := getFromMap(metaMap, "validuntil").(int)
if vub <= ledger.CurrentIndex() {
panic("incorrect vub: exceeded")
if v, ok := getFromMap(metaMap, "previousPart"); ok {
previousPart := v.(interop.Hash256)
if len(previousPart) != interop.Hash256Len {
panic("incorrect previous part object ID")
}
}
if v, ok := getFromMap(metaMap, "locked"); ok {
locked := v.([]interop.Hash256)
for i, l := range locked {
if len(l) != interop.Hash256Len {
panic("incorrect " + std.Itoa10(i) + " locked object")
}
}
}
if v, ok := getFromMap(metaMap, "deleted"); ok {
deleted := v.([]interop.Hash256)
for i, d := range deleted {
if len(d) != interop.Hash256Len {
panic("incorrect " + std.Itoa10(i) + " deleted object")
}
}
}

if !VerifyPlacementSignatures(cID, metaInformation, sigs) {
Expand All @@ -288,12 +318,21 @@ func SubmitObjectPut(metaInformation []byte, sigs [][]interop.Signature) {
runtime.Notify("ObjectPut", cID, oID, metaMap)
}

func getFromMap(m map[string]any, key string) any {
if !neogointernal.Opcode2("HASKEY", m, key).(bool) { // https://github.com/nspcc-dev/neo-go/issues/3716
func requireMapValue(m map[string]any, key string) any {
v, ok := getFromMap(m, key)
if !ok {
panic("'" + key + "'" + " not found")
}

return m[key]
return v
}

func getFromMap(m map[string]any, key string) (any, bool) {
if neogointernal.Opcode2("HASKEY", m, key).(bool) { // https://github.com/nspcc-dev/neo-go/issues/3716
return m[key], true
}

return nil, false
}

// PutMeta is the same as [Put] and [PutNamed] (and exposed as put from
Expand Down
Binary file modified contracts/container/contract.nef
Binary file not shown.
2 changes: 1 addition & 1 deletion contracts/container/manifest.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"name":"NeoFS Container","abi":{"methods":[{"name":"_initialize","offset":0,"parameters":[],"returntype":"Void","safe":false},{"name":"_deploy","offset":83,"parameters":[{"name":"data","type":"Any"},{"name":"isUpdate","type":"Boolean"}],"returntype":"Void","safe":false},{"name":"addNextEpochNodes","offset":4717,"parameters":[{"name":"cID","type":"Hash256"},{"name":"placementVector","type":"Integer"},{"name":"publicKeys","type":"Array"}],"returntype":"Void","safe":false},{"name":"alias","offset":4427,"parameters":[{"name":"cid","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"commitContainerListUpdate","offset":5483,"parameters":[{"name":"cID","type":"Hash256"},{"name":"replicas","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"containersOf","offset":4567,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"InteropInterface","safe":true},{"name":"count","offset":4522,"parameters":[],"returntype":"Integer","safe":true},{"name":"delete","offset":3924,"parameters":[{"name":"containerID","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"eACL","offset":6419,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"get","offset":4314,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"getContainerSize","offset":6679,"parameters":[{"name":"id","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"iterateAllContainerSizes","offset":7052,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"InteropInterface","safe":true},{"name":"iterateContainerSizes","offset":6954,"parameters":[{"name":"epoch","type":"Integer"},{"name":"cid","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"list","offset":4621,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"listContainerSizes","offset":6793,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Array","safe":true},{"name":"newEpoch","offset":7104,"parameters":[{"name":"epochNum","type":"Integer"}],"returntype":"Void","safe":false},{"name":"nodes","offset":6042,"parameters":[{"name":"cID","type":"Hash256"},{"name":"placementVector","type":"Integer"}],"returntype":"InteropInterface","safe":true},{"name":"onNEP11Payment","offset":1647,"parameters":[{"name":"a","type":"Hash160"},{"name":"b","type":"Integer"},{"name":"c","type":"ByteArray"},{"name":"d","type":"Any"}],"returntype":"Void","safe":false},{"name":"owner","offset":4376,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"ByteArray","safe":true},{"name":"put","offset":2753,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"putContainerSize","offset":6477,"parameters":[{"name":"epoch","type":"Integer"},{"name":"cid","type":"ByteArray"},{"name":"usedSize","type":"Integer"},{"name":"pubKey","type":"PublicKey"}],"returntype":"Void","safe":false},{"name":"put","offset":2690,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"},{"name":"name","type":"String"},{"name":"zone","type":"String"},{"name":"metaOnChain","type":"Boolean"}],"returntype":"Void","safe":false},{"name":"putNamed","offset":2783,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"},{"name":"name","type":"String"},{"name":"zone","type":"String"}],"returntype":"Void","safe":false},{"name":"put","offset":2769,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"},{"name":"name","type":"String"},{"name":"zone","type":"String"}],"returntype":"Void","safe":false},{"name":"replicasNumbers","offset":5944,"parameters":[{"name":"cID","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"setEACL","offset":6166,"parameters":[{"name":"eACL","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"startContainerEstimation","offset":7127,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Void","safe":false},{"name":"stopContainerEstimation","offset":7201,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Void","safe":false},{"name":"submitObjectPut","offset":2038,"parameters":[{"name":"metaInformation","type":"ByteArray"},{"name":"sigs","type":"Array"}],"returntype":"Void","safe":false},{"name":"update","offset":1905,"parameters":[{"name":"script","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false},{"name":"verifyPlacementSignatures","offset":5315,"parameters":[{"name":"cid","type":"Hash256"},{"name":"msg","type":"ByteArray"},{"name":"sigs","type":"Array"}],"returntype":"Boolean","safe":true},{"name":"version","offset":7274,"parameters":[],"returntype":"Integer","safe":true}],"events":[{"name":"PutSuccess","parameters":[{"name":"containerID","type":"Hash256"},{"name":"publicKey","type":"PublicKey"}]},{"name":"DeleteSuccess","parameters":[{"name":"containerID","type":"ByteArray"}]},{"name":"SetEACLSuccess","parameters":[{"name":"containerID","type":"ByteArray"},{"name":"publicKey","type":"PublicKey"}]},{"name":"StartEstimation","parameters":[{"name":"epoch","type":"Integer"}]},{"name":"StopEstimation","parameters":[{"name":"epoch","type":"Integer"}]},{"name":"NodesUpdate","parameters":[{"name":"ContainerID","type":"Hash256"}]},{"name":"ObjectPut","parameters":[{"name":"ContainerID","type":"Hash256"},{"name":"ObjectID","type":"Hash256"},{"name":"Meta","type":"Map"}]}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":["update","addKey","transferX","register","registerTLD","addRecord","deleteRecords","subscribeForNewEpoch"]}],"supportedstandards":[],"trusts":[],"extra":null}
{"name":"NeoFS Container","abi":{"methods":[{"name":"_initialize","offset":0,"parameters":[],"returntype":"Void","safe":false},{"name":"_deploy","offset":83,"parameters":[{"name":"data","type":"Any"},{"name":"isUpdate","type":"Boolean"}],"returntype":"Void","safe":false},{"name":"addNextEpochNodes","offset":5018,"parameters":[{"name":"cID","type":"Hash256"},{"name":"placementVector","type":"Integer"},{"name":"publicKeys","type":"Array"}],"returntype":"Void","safe":false},{"name":"alias","offset":4728,"parameters":[{"name":"cid","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"commitContainerListUpdate","offset":5784,"parameters":[{"name":"cID","type":"Hash256"},{"name":"replicas","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"containersOf","offset":4868,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"InteropInterface","safe":true},{"name":"count","offset":4823,"parameters":[],"returntype":"Integer","safe":true},{"name":"delete","offset":4225,"parameters":[{"name":"containerID","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"eACL","offset":6720,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"get","offset":4615,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"getContainerSize","offset":6980,"parameters":[{"name":"id","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"iterateAllContainerSizes","offset":7353,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"InteropInterface","safe":true},{"name":"iterateContainerSizes","offset":7255,"parameters":[{"name":"epoch","type":"Integer"},{"name":"cid","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"list","offset":4922,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"listContainerSizes","offset":7094,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Array","safe":true},{"name":"newEpoch","offset":7405,"parameters":[{"name":"epochNum","type":"Integer"}],"returntype":"Void","safe":false},{"name":"nodes","offset":6343,"parameters":[{"name":"cID","type":"Hash256"},{"name":"placementVector","type":"Integer"}],"returntype":"InteropInterface","safe":true},{"name":"onNEP11Payment","offset":1647,"parameters":[{"name":"a","type":"Hash160"},{"name":"b","type":"Integer"},{"name":"c","type":"ByteArray"},{"name":"d","type":"Any"}],"returntype":"Void","safe":false},{"name":"owner","offset":4677,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"ByteArray","safe":true},{"name":"put","offset":3054,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"putContainerSize","offset":6778,"parameters":[{"name":"epoch","type":"Integer"},{"name":"cid","type":"ByteArray"},{"name":"usedSize","type":"Integer"},{"name":"pubKey","type":"PublicKey"}],"returntype":"Void","safe":false},{"name":"put","offset":2991,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"},{"name":"name","type":"String"},{"name":"zone","type":"String"},{"name":"metaOnChain","type":"Boolean"}],"returntype":"Void","safe":false},{"name":"putNamed","offset":3084,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"},{"name":"name","type":"String"},{"name":"zone","type":"String"}],"returntype":"Void","safe":false},{"name":"put","offset":3070,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"},{"name":"name","type":"String"},{"name":"zone","type":"String"}],"returntype":"Void","safe":false},{"name":"replicasNumbers","offset":6245,"parameters":[{"name":"cID","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"setEACL","offset":6467,"parameters":[{"name":"eACL","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"startContainerEstimation","offset":7428,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Void","safe":false},{"name":"stopContainerEstimation","offset":7502,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Void","safe":false},{"name":"submitObjectPut","offset":2038,"parameters":[{"name":"metaInformation","type":"ByteArray"},{"name":"sigs","type":"Array"}],"returntype":"Void","safe":false},{"name":"update","offset":1905,"parameters":[{"name":"script","type":"ByteArray"},{"name":"manifest","type":"ByteArray"},{"name":"data","type":"Any"}],"returntype":"Void","safe":false},{"name":"verifyPlacementSignatures","offset":5616,"parameters":[{"name":"cid","type":"Hash256"},{"name":"msg","type":"ByteArray"},{"name":"sigs","type":"Array"}],"returntype":"Boolean","safe":true},{"name":"version","offset":7575,"parameters":[],"returntype":"Integer","safe":true}],"events":[{"name":"PutSuccess","parameters":[{"name":"containerID","type":"Hash256"},{"name":"publicKey","type":"PublicKey"}]},{"name":"DeleteSuccess","parameters":[{"name":"containerID","type":"ByteArray"}]},{"name":"SetEACLSuccess","parameters":[{"name":"containerID","type":"ByteArray"},{"name":"publicKey","type":"PublicKey"}]},{"name":"StartEstimation","parameters":[{"name":"epoch","type":"Integer"}]},{"name":"StopEstimation","parameters":[{"name":"epoch","type":"Integer"}]},{"name":"NodesUpdate","parameters":[{"name":"ContainerID","type":"Hash256"}]},{"name":"ObjectPut","parameters":[{"name":"ContainerID","type":"Hash256"},{"name":"ObjectID","type":"Hash256"},{"name":"Meta","type":"Map"}]}]},"features":{},"groups":[],"permissions":[{"contract":"*","methods":["update","addKey","transferX","register","registerTLD","addRecord","deleteRecords","subscribeForNewEpoch"]}],"supportedstandards":[],"trusts":[],"extra":null}
16 changes: 9 additions & 7 deletions tests/container_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ func TestPutMeta(t *testing.T) {
c.InvokeFail(t, "invalid type", "submitObjectPut", []byte{1}, nil)
})

t.Run("missing values", func(t *testing.T) {
t.Run("missing required values", func(t *testing.T) {
testFunc := func(key string) {
meta := testMeta(cnt.id[:], oid)
meta.Drop(meta.Index(stackitem.Make(key)))
Expand All @@ -872,11 +872,9 @@ func TestPutMeta(t *testing.T) {

testFunc("cid")
testFunc("oid")
testFunc("network")
testFunc("size")
testFunc("deleted")
testFunc("locked")
testFunc("validuntil")
testFunc("validUntil")
testFunc("network")
})

t.Run("incorrect values", func(t *testing.T) {
Expand All @@ -890,10 +888,13 @@ func TestPutMeta(t *testing.T) {

testFunc("cid", []byte{1})
testFunc("oid", []byte{1})
testFunc("validUntil", 1) // tested chain will have some blocks for sure
testFunc("network", netmode.UnitTestNet+1)
testFunc("type", math.MaxInt64)
testFunc("firstPart", []byte{1})
testFunc("previousPart", []byte{1})
testFunc("deleted", []any{[]byte{1}})
testFunc("locked", []any{[]byte{1}})
testFunc("validuntil", 1) // tested chain will have some blocks for sure
})
})
}
Expand All @@ -904,9 +905,10 @@ func testMeta(cid, oid []byte) *stackitem.Map {
{Key: stackitem.Make("network"), Value: stackitem.Make(netmode.UnitTestNet)},
{Key: stackitem.Make("cid"), Value: stackitem.Make(cid)},
{Key: stackitem.Make("oid"), Value: stackitem.Make(oid)},
{Key: stackitem.Make("firstPart"), Value: stackitem.Make(oid)},
{Key: stackitem.Make("size"), Value: stackitem.Make(123)},
{Key: stackitem.Make("deleted"), Value: stackitem.Make([]any{randomBytes(sha256.Size)})},
{Key: stackitem.Make("locked"), Value: stackitem.Make([]any{randomBytes(sha256.Size)})},
{Key: stackitem.Make("validuntil"), Value: stackitem.Make(math.MaxInt)},
{Key: stackitem.Make("validUntil"), Value: stackitem.Make(math.MaxInt)},
})
}
Loading