forked from TrueCloudLab/frostfs-contract
ac89694eeb
Signed-off-by: Pavel Karpy <carpawell@nspcc.ru>
270 lines
8 KiB
Go
270 lines
8 KiB
Go
package tests
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"path"
|
|
"testing"
|
|
|
|
"github.com/mr-tron/base58"
|
|
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
|
|
"github.com/nspcc-dev/neo-go/pkg/neotest"
|
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
|
"github.com/nspcc-dev/neofs-contract/container"
|
|
"github.com/nspcc-dev/neofs-contract/nns"
|
|
)
|
|
|
|
const containerPath = "../container"
|
|
|
|
const (
|
|
containerFee = 0_0100_0000
|
|
containerAliasFee = 0_0050_0000
|
|
)
|
|
|
|
func deployContainerContract(t *testing.T, e *neotest.Executor, addrNetmap, addrBalance, addrNNS util.Uint160) util.Uint160 {
|
|
args := make([]interface{}, 6)
|
|
args[0] = int64(0)
|
|
args[1] = addrNetmap
|
|
args[2] = addrBalance
|
|
args[3] = util.Uint160{} // not needed for now
|
|
args[4] = addrNNS
|
|
args[5] = "neofs"
|
|
|
|
c := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
|
e.DeployContract(t, c, args)
|
|
return c.Hash
|
|
}
|
|
|
|
func newContainerInvoker(t *testing.T) (*neotest.ContractInvoker, *neotest.ContractInvoker) {
|
|
e := newExecutor(t)
|
|
|
|
ctrNNS := neotest.CompileFile(t, e.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
|
ctrNetmap := neotest.CompileFile(t, e.CommitteeHash, netmapPath, path.Join(netmapPath, "config.yml"))
|
|
ctrBalance := neotest.CompileFile(t, e.CommitteeHash, balancePath, path.Join(balancePath, "config.yml"))
|
|
ctrContainer := neotest.CompileFile(t, e.CommitteeHash, containerPath, path.Join(containerPath, "config.yml"))
|
|
|
|
e.DeployContract(t, ctrNNS, nil)
|
|
deployNetmapContract(t, e, ctrBalance.Hash, ctrContainer.Hash,
|
|
container.RegistrationFeeKey, int64(containerFee),
|
|
container.AliasFeeKey, int64(containerAliasFee))
|
|
deployBalanceContract(t, e, ctrNetmap.Hash, ctrContainer.Hash)
|
|
deployContainerContract(t, e, ctrNetmap.Hash, ctrBalance.Hash, ctrNNS.Hash)
|
|
return e.CommitteeInvoker(ctrContainer.Hash), e.CommitteeInvoker(ctrBalance.Hash)
|
|
}
|
|
|
|
func setContainerOwner(c []byte, acc neotest.Signer) {
|
|
owner, _ := base58.Decode(address.Uint160ToString(acc.ScriptHash()))
|
|
copy(c[6:], owner)
|
|
}
|
|
|
|
type testContainer struct {
|
|
id [32]byte
|
|
value, sig, pub, token []byte
|
|
}
|
|
|
|
func dummyContainer(owner neotest.Signer) testContainer {
|
|
value := randomBytes(100)
|
|
value[1] = 0 // zero offset
|
|
setContainerOwner(value, owner)
|
|
|
|
return testContainer{
|
|
id: sha256.Sum256(value),
|
|
value: value,
|
|
sig: randomBytes(64),
|
|
pub: randomBytes(33),
|
|
token: randomBytes(42),
|
|
}
|
|
}
|
|
|
|
func TestContainerPut(t *testing.T) {
|
|
c, cBal := newContainerInvoker(t)
|
|
|
|
acc := c.NewAccount(t)
|
|
cnt := dummyContainer(acc)
|
|
|
|
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token}
|
|
c.InvokeFail(t, "insufficient balance to create container", "put", putArgs...)
|
|
|
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
|
|
|
cAcc := c.WithSigners(acc)
|
|
cAcc.InvokeFail(t, "alphabet witness check failed", "put", putArgs...)
|
|
|
|
c.Invoke(t, stackitem.Null{}, "put", putArgs...)
|
|
|
|
t.Run("with nice names", func(t *testing.T) {
|
|
ctrNNS := neotest.CompileFile(t, c.CommitteeHash, nnsPath, path.Join(nnsPath, "config.yml"))
|
|
nnsHash := ctrNNS.Hash
|
|
|
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
|
|
|
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token, "mycnt", ""}
|
|
t.Run("no fee for alias", func(t *testing.T) {
|
|
c.InvokeFail(t, "insufficient balance to create container", "putNamed", putArgs...)
|
|
})
|
|
|
|
balanceMint(t, cBal, acc, containerAliasFee*1, []byte{})
|
|
c.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
|
|
|
|
expected := stackitem.NewArray([]stackitem.Item{
|
|
stackitem.NewByteArray([]byte(base58.Encode(cnt.id[:]))),
|
|
})
|
|
cNNS := c.CommitteeInvoker(nnsHash)
|
|
cNNS.Invoke(t, expected, "resolve", "mycnt.neofs", int64(nns.TXT))
|
|
|
|
t.Run("name is already taken", func(t *testing.T) {
|
|
c.InvokeFail(t, "name is already taken", "putNamed", putArgs...)
|
|
})
|
|
|
|
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.token)
|
|
cNNS.Invoke(t, stackitem.Null{}, "resolve", "mycnt.neofs", int64(nns.TXT))
|
|
|
|
t.Run("register in advance", func(t *testing.T) {
|
|
cnt.value[len(cnt.value)-1] = 10
|
|
cnt.id = sha256.Sum256(cnt.value)
|
|
|
|
t.Run("bad domain owner", func(t *testing.T) {
|
|
c1 := cNNS.WithSigners(acc, c.Committee)
|
|
c1.Invoke(t, true, "register",
|
|
"baddomain.neofs", acc.ScriptHash(),
|
|
"whateveriwant@world.com", int64(0), int64(0), int64(0), int64(0))
|
|
|
|
cAcc.InvokeFail(t, "committee or container contract must own registered domain",
|
|
"putNamed",
|
|
cnt.value, cnt.sig, cnt.pub, cnt.token, "baddomain", "neofs")
|
|
})
|
|
|
|
cNNS.Invoke(t, true, "register",
|
|
"second.neofs", c.CommitteeHash,
|
|
"whateveriwant@world.com", int64(0), int64(0), int64(0), int64(0))
|
|
|
|
balanceMint(t, cBal, acc, (containerFee+containerAliasFee)*1, []byte{})
|
|
|
|
putArgs := []interface{}{cnt.value, cnt.sig, cnt.pub, cnt.token, "second", "neofs"}
|
|
c2 := c.WithSigners(c.Committee, acc)
|
|
c2.Invoke(t, stackitem.Null{}, "putNamed", putArgs...)
|
|
|
|
expected = stackitem.NewArray([]stackitem.Item{
|
|
stackitem.NewByteArray([]byte(base58.Encode(cnt.id[:])))})
|
|
cNNS.Invoke(t, expected, "resolve", "second.neofs", int64(nns.TXT))
|
|
})
|
|
})
|
|
}
|
|
|
|
func TestContainerDelete(t *testing.T) {
|
|
c, cBal := newContainerInvoker(t)
|
|
|
|
acc := c.NewAccount(t)
|
|
cnt := dummyContainer(acc)
|
|
|
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
|
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
|
|
|
|
cAcc := c.WithSigners(acc)
|
|
cAcc.InvokeFail(t, "alphabet witness check failed", "delete",
|
|
cnt.id[:], cnt.sig, cnt.token)
|
|
|
|
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.token)
|
|
|
|
t.Run("missing container", func(t *testing.T) {
|
|
id := cnt.id
|
|
id[0] ^= 0xFF
|
|
c.Invoke(t, stackitem.Null{}, "delete", cnt.id[:], cnt.sig, cnt.token)
|
|
})
|
|
|
|
c.InvokeFail(t, container.NotFoundError, "get", cnt.id[:])
|
|
}
|
|
|
|
func TestContainerOwner(t *testing.T) {
|
|
c, cBal := newContainerInvoker(t)
|
|
|
|
acc := c.NewAccount(t)
|
|
cnt := dummyContainer(acc)
|
|
|
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
|
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
|
|
|
|
t.Run("missing container", func(t *testing.T) {
|
|
id := cnt.id
|
|
id[0] ^= 0xFF
|
|
c.InvokeFail(t, container.NotFoundError, "owner", id[:])
|
|
})
|
|
|
|
owner, _ := base58.Decode(address.Uint160ToString(acc.ScriptHash()))
|
|
c.Invoke(t, stackitem.NewBuffer(owner), "owner", cnt.id[:])
|
|
}
|
|
|
|
func TestContainerGet(t *testing.T) {
|
|
c, cBal := newContainerInvoker(t)
|
|
|
|
acc := c.NewAccount(t)
|
|
cnt := dummyContainer(acc)
|
|
|
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
|
|
|
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
|
|
|
|
t.Run("missing container", func(t *testing.T) {
|
|
id := cnt.id
|
|
id[0] ^= 0xFF
|
|
c.InvokeFail(t, container.NotFoundError, "get", id[:])
|
|
})
|
|
|
|
expected := stackitem.NewStruct([]stackitem.Item{
|
|
stackitem.NewByteArray(cnt.value),
|
|
stackitem.NewByteArray(cnt.sig),
|
|
stackitem.NewByteArray(cnt.pub),
|
|
stackitem.NewByteArray(cnt.token),
|
|
})
|
|
c.Invoke(t, expected, "get", cnt.id[:])
|
|
}
|
|
|
|
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) {
|
|
c, cBal := newContainerInvoker(t)
|
|
|
|
acc := c.NewAccount(t)
|
|
cnt := dummyContainer(acc)
|
|
balanceMint(t, cBal, acc, containerFee*1, []byte{})
|
|
|
|
c.Invoke(t, stackitem.Null{}, "put", cnt.value, cnt.sig, cnt.pub, cnt.token)
|
|
|
|
t.Run("missing container", func(t *testing.T) {
|
|
id := cnt.id
|
|
id[0] ^= 0xFF
|
|
e := dummyEACL(id)
|
|
c.InvokeFail(t, container.NotFoundError, "setEACL", e.value, e.sig, e.pub, e.token)
|
|
})
|
|
|
|
e := dummyEACL(cnt.id)
|
|
setArgs := []interface{}{e.value, e.sig, e.pub, e.token}
|
|
cAcc := c.WithSigners(acc)
|
|
cAcc.InvokeFail(t, "alphabet witness check failed", "setEACL", setArgs...)
|
|
|
|
c.Invoke(t, stackitem.Null{}, "setEACL", setArgs...)
|
|
|
|
expected := stackitem.NewStruct([]stackitem.Item{
|
|
stackitem.NewByteArray(e.value),
|
|
stackitem.NewByteArray(e.sig),
|
|
stackitem.NewByteArray(e.pub),
|
|
stackitem.NewByteArray(e.token),
|
|
})
|
|
c.Invoke(t, expected, "eACL", cnt.id[:])
|
|
}
|