From d5e22debac1dc07f9fde09d35ea5620a66fa2040 Mon Sep 17 00:00:00 2001 From: Pavel Karpy Date: Tue, 15 Oct 2024 23:33:11 +0300 Subject: [PATCH] container: add container placement verification The new `VerifyPlacementSignatures` checks if a message was signed by a suitable number of nodes. Number is taken from the contract storage, their relevance should be ensured and maintained by the Alphabet nodes every epoch. Closes #413. Signed-off-by: Pavel Karpy --- contracts/container/config.yml | 2 +- contracts/container/contract.go | 42 ++++++++++++++ contracts/container/contract.nef | Bin 8037 -> 8243 bytes contracts/container/manifest.json | 2 +- rpc/container/rpcbinding.go | 5 ++ tests/container_test.go | 90 ++++++++++++++++++++++++++++++ 6 files changed, 139 insertions(+), 2 deletions(-) diff --git a/contracts/container/config.yml b/contracts/container/config.yml index 95c62cd8..4cd139a9 100644 --- a/contracts/container/config.yml +++ b/contracts/container/config.yml @@ -1,5 +1,5 @@ name: "NeoFS Container" -safemethods: ["alias", "count", "containersOf", "get", "owner", "list", "nodes", "replicasNumbers", "eACL", "getContainerSize", "listContainerSizes", "iterateContainerSizes", "iterateAllContainerSizes", "version"] +safemethods: ["alias", "count", "containersOf", "get", "owner", "list", "nodes", "replicasNumbers", "verifyPlacementSignatures", "eACL", "getContainerSize", "listContainerSizes", "iterateContainerSizes", "iterateAllContainerSizes", "version"] permissions: - methods: ["update", "addKey", "transferX", "register", "registerTLD", "addRecord", "deleteRecords", "subscribeForNewEpoch"] diff --git a/contracts/container/contract.go b/contracts/container/contract.go index 64b58435..94b6ed34 100644 --- a/contracts/container/contract.go +++ b/contracts/container/contract.go @@ -582,6 +582,48 @@ func validatePlacementIndex(ctx storage.Context, cID interop.Hash256, inx uint8) } } +// VerifyPlacementSignatures verifies that message has been signed by container +// members according to container's placement policy: there should be at least +// REP number of signatures for every placement vector. sigs must be container's +// number of SELECTs length. +func VerifyPlacementSignatures(cid interop.Hash256, msg []byte, sigs [][]interop.Signature) bool { + sigsLen := len(sigs) + var i int + repsI := ReplicasNumbers(cid) +repsLoop: + for iterator.Next(repsI) { + if sigsLen == i { + return false + } + + m := iterator.Value(repsI).(int) + if len(sigs[i]) < m { + return false + } + + var counter int + for _, sig := range sigs[i] { + pubsI := Nodes(cid, uint8(i)) + for iterator.Next(pubsI) { + pub := iterator.Value(pubsI).(interop.PublicKey) + if crypto.VerifyWithECDsa(msg, pub, sig, crypto.Secp256r1Sha256) { + counter++ + break + } + } + + if counter == m { + i++ + continue repsLoop + } + } + + return false + } + + return true +} + // CommitContainerListUpdate commits container list changes made by // [AddNextEpochNodes] calls in advance. Replicas must correspond to // ordered placement policy (REP clauses). If no [AddNextEpochNodes] diff --git a/contracts/container/contract.nef b/contracts/container/contract.nef index aee3607136686749585a2c009a1d8218e07e5233..781fa283f4ba94d722f26578785d1f8591cbf97d 100755 GIT binary patch delta 414 zcmaEAx7lHW8zbLF_ic=V{AH;{nQ4{bnI##n&Mw7?ERz!$#V7w|6lDCqnV(6JgQ;D3 zvl3Sl6O$kR<~ANKCdTiRC-NmR>GE#=%BR7|#K${XUciP)hj;P>0j0_H0{o0WC-)1S zVY1`i94oklsh)$m%Ik&->nSA`SAhb7!V1$ICI*J0EXO$;&RPvw( z7yu10C}*$CXU}C24>4EeVNhewnNy;~qI4rCTZ=1mPNA!-s}k27rR_kP(?Pl7|Ns9S zlm82QaK?T3|GzNPH0$%`01*LZ4%fH;|Ci>P22RcpS7dtfZgRKyY^K@oH)}|EF)0|o z0xPu#D#@q_FfC jD{h`E-N?wuyIEeA4@gbclRLyz`+V{zxqOzBF=aCVc9WC9 delta 252 zcmdn&@YHUC8zb*V_ic=mRha}C12>y9334z!6x!^?mBhrff^YLW9xf)vz{xxLl9<|g zHp}vBFfwKEOm-KrVQb@IU?|L-%r7A~dAR^TTQGuqOJF7U3@!!+2kycQ9>)C1@5RJ7 zFBNQIntWcwjg#f$|Nn)VrUG9!%ZUmwbG&~0|9@$&>G#QI5{gV+?; oGEe>^t++W`rje16XY*TGJ|H#ukK7?9