From 7fe7188e7dceb4977f33d75d7b96c7ba0d193c5e Mon Sep 17 00:00:00 2001 From: Evgenii Stratonikov Date: Tue, 19 Oct 2021 11:23:35 +0300 Subject: [PATCH] [#150] container: allow only alphabet calls in `SetEACL` Signed-off-by: Evgenii Stratonikov --- container/container_contract.go | 46 ++++++++++++++------------------- tests/container_test.go | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/container/container_contract.go b/container/container_contract.go index 37112ac..7458b4b 100644 --- a/container/container_contract.go +++ b/container/container_contract.go @@ -392,24 +392,28 @@ func SetEACL(eACL []byte, signature interop.Signature, publicKey interop.PublicK panic("container does not exist") } - var ( // for invocation collection without notary - alphabet []common.IRNode - nodeKey []byte - alphabetCall bool - ) - if notaryDisabled { - alphabet = common.AlphabetNodes() - nodeKey = common.InnerRingInvoker(alphabet) - alphabetCall = len(nodeKey) != 0 + alphabet := common.AlphabetNodes() + nodeKey := common.InnerRingInvoker(alphabet) + if len(nodeKey) == 0 { + runtime.Notify("setEACL", eACL, signature, publicKey, token) + return + } + + threshold := len(alphabet)*2/3 + 1 + id := common.InvokeID([]interface{}{eACL}, []byte("setEACL")) + + n := common.Vote(ctx, id, nodeKey) + if n < threshold { + return + } + + common.RemoveVotes(ctx, id) } else { multiaddr := common.AlphabetAddress() - alphabetCall = runtime.CheckWitness(multiaddr) - } - - if !alphabetCall { - runtime.Notify("setEACL", eACL, signature, publicKey, token) - return + if !runtime.CheckWitness(multiaddr) { + panic("setEACL: alphabet witness check failed") + } } rule := ExtendedACL{ @@ -421,18 +425,6 @@ func SetEACL(eACL []byte, signature interop.Signature, publicKey interop.PublicK key := append(eACLPrefix, containerID...) - if notaryDisabled { - threshold := len(alphabet)*2/3 + 1 - id := common.InvokeID([]interface{}{eACL}, []byte("setEACL")) - - n := common.Vote(ctx, id, nodeKey) - if n < threshold { - return - } - - common.RemoveVotes(ctx, id) - } - common.SetSerialized(ctx, key, rule) runtime.Log("setEACL: success") diff --git a/tests/container_test.go b/tests/container_test.go index 2b77ce7..0d95bb5 100644 --- a/tests/container_test.go +++ b/tests/container_test.go @@ -172,3 +172,49 @@ func TestContainerDelete(t *testing.T) { stackitem.NewBuffer([]byte{}), })) } + +type eacl struct { + value []byte + sig []byte + pub []byte + token []byte +} + +func dummyEACL(containerID [32]byte) eacl { + e := make([]byte, 50) + copy(e[6:], containerID[:]) + return eacl{ + value: e, + sig: randomBytes(64), + pub: randomBytes(33), + token: randomBytes(42), + } +} + +func TestContainerSetEACL(t *testing.T) { + bc := NewChain(t) + h, balanceHash := prepareContainerContract(t, bc) + + acc := NewAccount(t, bc) + balanceMint(t, bc, acc, balanceHash, containerFee*1, []byte{}) + + c := dummyContainer(acc) + tx := PrepareInvoke(t, bc, CommitteeAcc, h, "put", c.value, c.sig, c.pub, c.token) + AddBlockCheckHalt(t, bc, tx) + + e := dummyEACL(c.id) + tx = PrepareInvoke(t, bc, acc, h, "setEACL", e.value, e.sig, e.pub, e.token) + AddBlock(t, bc, tx) + CheckFault(t, bc, tx.Hash(), "setEACL: alphabet witness check failed") + + tx = PrepareInvoke(t, bc, CommitteeAcc, h, "setEACL", e.value, e.sig, e.pub, e.token) + AddBlockCheckHalt(t, bc, tx) + + tx = PrepareInvoke(t, bc, CommitteeAcc, h, "eACL", c.id[:]) + CheckTestInvoke(t, bc, tx, stackitem.NewStruct([]stackitem.Item{ + stackitem.NewByteArray(e.value), + stackitem.NewByteArray(e.sig), + stackitem.NewByteArray(e.pub), + stackitem.NewByteArray(e.token), + })) +}