-
Notifications
You must be signed in to change notification settings - Fork 17
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
container: add object meta notification support #448
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -6,8 +6,10 @@ import ( | |
"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/crypto" | ||
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger" | ||
"github.com/nspcc-dev/neo-go/pkg/interop/native/management" | ||
"github.com/nspcc-dev/neo-go/pkg/interop/native/std" | ||
"github.com/nspcc-dev/neo-go/pkg/interop/neogointernal" | ||
"github.com/nspcc-dev/neo-go/pkg/interop/runtime" | ||
"github.com/nspcc-dev/neo-go/pkg/interop/storage" | ||
"github.com/nspcc-dev/neofs-contract/common" | ||
|
@@ -61,15 +63,16 @@ const ( | |
// V2 format. | ||
containerIDSize = interop.Hash256Len // SHA256 size | ||
|
||
singleEstimatePrefix = "est" | ||
estimateKeyPrefix = "cnr" | ||
containerKeyPrefix = 'x' | ||
ownerKeyPrefix = 'o' | ||
deletedKeyPrefix = 'd' | ||
nodesPrefix = 'n' | ||
replicasNumberPrefix = 'r' | ||
nextEpochNodesPrefix = 'u' | ||
estimatePostfixSize = 10 | ||
singleEstimatePrefix = "est" | ||
estimateKeyPrefix = "cnr" | ||
containersWithMetaPrefix = 'm' | ||
containerKeyPrefix = 'x' | ||
ownerKeyPrefix = 'o' | ||
deletedKeyPrefix = 'd' | ||
nodesPrefix = 'n' | ||
replicasNumberPrefix = 'r' | ||
nextEpochNodesPrefix = 'u' | ||
estimatePostfixSize = 10 | ||
|
||
// default SOA record field values. | ||
defaultRefresh = 3600 // 1 hour | ||
|
@@ -238,6 +241,73 @@ func Update(script []byte, manifest []byte, data any) { | |
runtime.Log("container contract updated") | ||
} | ||
|
||
// SubmitObjectPut registers successful object PUT operation and notifies about | ||
// it. metaInformation must be signed by container nodes according to | ||
// container's placement, see [VerifyPlacementSignatures]. metaInformation | ||
// must contain information about an object placed to a container that was | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
i think this will somehow appear somewhere. at least it should appear before node's 0.44.0 release and contract's 0.21. however, currently node also uses it as is and the format is not fixed or described |
||
// 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) | ||
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) | ||
if len(oID) != interop.Hash256Len { | ||
panic("incorrect object ID") | ||
} | ||
magic := getFromMap(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") | ||
} | ||
} | ||
locked := getFromMap(metaMap, "locked").([]interop.Hash256) | ||
for i, l := range locked { | ||
if len(l) != interop.Hash256Len { | ||
panic("incorrect " + std.Itoa10(i) + " locked object") | ||
} | ||
} | ||
vub := getFromMap(metaMap, "validuntil").(int) | ||
if vub <= ledger.CurrentIndex() { | ||
panic("incorrect vub: exceeded") | ||
} | ||
|
||
if !VerifyPlacementSignatures(cID, metaInformation, sigs) { | ||
roman-khimov marked this conversation as resolved.
Show resolved
Hide resolved
|
||
panic("signature verification failed") | ||
} | ||
|
||
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 | ||
panic("'" + key + "'" + " not found") | ||
} | ||
|
||
return m[key] | ||
} | ||
|
||
// PutMeta is the same as [Put] (and exposed as put from the contract via | ||
// overload), but allows container's meta-information be handled and notified | ||
// using the chain. | ||
func PutMeta(container []byte, signature interop.Signature, publicKey interop.PublicKey, token []byte, metaOnChain bool) { | ||
roman-khimov marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we put container and just configure meta support, with this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i have adopted @roman-khimov's approach with method overloading. no one will call it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if metaOnChain { | ||
ctx := storage.GetContext() | ||
cID := crypto.Sha256(container) | ||
storage.Put(ctx, append([]byte{containersWithMetaPrefix}, cID...), []byte{}) | ||
} | ||
Put(container, signature, publicKey, token) | ||
} | ||
|
||
// Put method creates a new container if it has been invoked by Alphabet nodes | ||
// of the Inner Ring. Otherwise, it produces containerPut notification. | ||
// | ||
|
@@ -950,6 +1020,7 @@ func removeContainer(ctx storage.Context, id []byte, owner []byte) { | |
storage.Delete(ctx, containerListKey) | ||
|
||
storage.Delete(ctx, append([]byte{containerKeyPrefix}, id...)) | ||
storage.Delete(ctx, append([]byte{containersWithMetaPrefix}, id...)) | ||
storage.Delete(ctx, append(eACLPrefix, id...)) | ||
storage.Put(ctx, append([]byte{deletedKeyPrefix}, id...), []byte{}) | ||
} | ||
|
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":3988,"parameters":[{"name":"cID","type":"Hash256"},{"name":"placementVector","type":"Integer"},{"name":"publicKeys","type":"Array"}],"returntype":"Void","safe":false},{"name":"alias","offset":3698,"parameters":[{"name":"cid","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"commitContainerListUpdate","offset":4752,"parameters":[{"name":"cID","type":"Hash256"},{"name":"replicas","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"containersOf","offset":3838,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"InteropInterface","safe":true},{"name":"count","offset":3793,"parameters":[],"returntype":"Integer","safe":true},{"name":"delete","offset":3195,"parameters":[{"name":"containerID","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"eACL","offset":5688,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"get","offset":3585,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"getContainerSize","offset":5948,"parameters":[{"name":"id","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"iterateAllContainerSizes","offset":6321,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"InteropInterface","safe":true},{"name":"iterateContainerSizes","offset":6223,"parameters":[{"name":"epoch","type":"Integer"},{"name":"cid","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"list","offset":3892,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"listContainerSizes","offset":6062,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Array","safe":true},{"name":"newEpoch","offset":6373,"parameters":[{"name":"epochNum","type":"Integer"}],"returntype":"Void","safe":false},{"name":"nodes","offset":5311,"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":3647,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"ByteArray","safe":true},{"name":"put","offset":2038,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"putContainerSize","offset":5746,"parameters":[{"name":"epoch","type":"Integer"},{"name":"cid","type":"ByteArray"},{"name":"usedSize","type":"Integer"},{"name":"pubKey","type":"PublicKey"}],"returntype":"Void","safe":false},{"name":"putNamed","offset":2054,"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":5213,"parameters":[{"name":"cID","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"setEACL","offset":5435,"parameters":[{"name":"eACL","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"startContainerEstimation","offset":6396,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Void","safe":false},{"name":"stopContainerEstimation","offset":6470,"parameters":[{"name":"epoch","type":"Integer"}],"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":4586,"parameters":[{"name":"cid","type":"Hash256"},{"name":"msg","type":"ByteArray"},{"name":"sigs","type":"Array"}],"returntype":"Boolean","safe":true},{"name":"version","offset":6543,"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"}]}]},"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":4700,"parameters":[{"name":"cID","type":"Hash256"},{"name":"placementVector","type":"Integer"},{"name":"publicKeys","type":"Array"}],"returntype":"Void","safe":false},{"name":"alias","offset":4410,"parameters":[{"name":"cid","type":"ByteArray"}],"returntype":"String","safe":true},{"name":"commitContainerListUpdate","offset":5464,"parameters":[{"name":"cID","type":"Hash256"},{"name":"replicas","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"containersOf","offset":4550,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"InteropInterface","safe":true},{"name":"count","offset":4505,"parameters":[],"returntype":"Integer","safe":true},{"name":"delete","offset":3907,"parameters":[{"name":"containerID","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"eACL","offset":6400,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"get","offset":4297,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"getContainerSize","offset":6660,"parameters":[{"name":"id","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"iterateAllContainerSizes","offset":7033,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"InteropInterface","safe":true},{"name":"iterateContainerSizes","offset":6935,"parameters":[{"name":"epoch","type":"Integer"},{"name":"cid","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"list","offset":4604,"parameters":[{"name":"owner","type":"ByteArray"}],"returntype":"Array","safe":true},{"name":"listContainerSizes","offset":6774,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Array","safe":true},{"name":"newEpoch","offset":7085,"parameters":[{"name":"epochNum","type":"Integer"}],"returntype":"Void","safe":false},{"name":"nodes","offset":6023,"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":4359,"parameters":[{"name":"containerID","type":"ByteArray"}],"returntype":"ByteArray","safe":true},{"name":"put","offset":2750,"parameters":[{"name":"container","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"putContainerSize","offset":6458,"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":"metaOnChain","type":"Boolean"}],"returntype":"Void","safe":false},{"name":"putNamed","offset":2766,"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":5925,"parameters":[{"name":"cID","type":"Hash256"}],"returntype":"InteropInterface","safe":true},{"name":"setEACL","offset":6147,"parameters":[{"name":"eACL","type":"ByteArray"},{"name":"signature","type":"Signature"},{"name":"publicKey","type":"PublicKey"},{"name":"token","type":"ByteArray"}],"returntype":"Void","safe":false},{"name":"startContainerEstimation","offset":7108,"parameters":[{"name":"epoch","type":"Integer"}],"returntype":"Void","safe":false},{"name":"stopContainerEstimation","offset":7182,"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":5298,"parameters":[{"name":"cid","type":"Hash256"},{"name":"msg","type":"ByteArray"},{"name":"sigs","type":"Array"}],"returntype":"Boolean","safe":true},{"name":"version","offset":7255,"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} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just a remark
i very like (no) how gofmt makes a 10-line change when one is actually added/changed. Takin bout why linebreaks are good sometimes, and const/var blocks aint