frostfs-contract/tests/nns_test.go
Evgenii Stratonikov 552def9322 [#139] nns: require admin signature for registering subdomain
Signed-off-by: Evgenii Stratonikov <evgeniy@nspcc.ru>
2021-10-26 14:00:28 +03:00

286 lines
10 KiB
Go

package tests
import (
"fmt"
"math/big"
"strings"
"testing"
"time"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/wallet"
"github.com/nspcc-dev/neofs-contract/nns"
"github.com/stretchr/testify/require"
)
const nnsPath = "../nns"
func TestNNSGeneric(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "symbol")
CheckTestInvoke(t, bc, tx, "NNS")
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "decimals")
CheckTestInvoke(t, bc, tx, 0)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "totalSupply")
CheckTestInvoke(t, bc, tx, 0)
}
func TestNNSRegisterTLD(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"0com", CommitteeAcc.Contract.ScriptHash(),
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "invalid domain name format")
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, acc, h, "register",
"com", acc.Contract.ScriptHash(),
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "not witnessed by committee")
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckHalt(t, bc, tx.Hash())
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
"email@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "TLD already exists")
}
func TestNNSRegister(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
accTop := NewAccount(t, bc)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, accTop}, h, "register",
"com", accTop.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "register",
"testdomain.com", acc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "not witnessed by admin")
tx = PrepareInvoke(t, bc, []*wallet.Account{accTop, acc}, h, "register",
"testdomain.com", acc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
b := AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "getRecords", "testdomain.com", int64(nns.SOA))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
[]byte(fmt.Sprintf("testdomain.com myemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)))}))
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
"testdomain.com", int64(nns.TXT), "first TXT record")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
"testdomain.com", int64(nns.TXT), "second TXT record")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "getRecords", "testdomain.com", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte("first TXT record")),
stackitem.NewByteArray([]byte("second TXT record"))}))
tx = PrepareInvoke(t, bc, acc, h, "setRecord",
"testdomain.com", int64(nns.TXT), int64(0), "replaced first")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "getRecords", "testdomain.com", int64(nns.TXT))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray([]byte("replaced first")),
stackitem.NewByteArray([]byte("second TXT record"))}))
}
func TestNNSUpdateSOA(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"testdomain.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
refresh *= 2
retry *= 2
expire *= 2
ttl *= 2
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "updateSOA",
"testdomain.com", "newemail@nspcc.ru", refresh, retry, expire, ttl)
b := AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "getRecords", "testdomain.com", int64(nns.SOA))
CheckTestInvoke(t, bc, tx, stackitem.NewArray([]stackitem.Item{stackitem.NewBuffer(
[]byte(fmt.Sprintf("testdomain.com newemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)))}))
}
func TestNNSGetAllRecords(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"testdomain.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "addRecord",
"testdomain.com", int64(nns.TXT), "first TXT record")
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "addRecord",
"testdomain.com", int64(nns.A), "1.2.3.4")
b := AddBlockCheckHalt(t, bc, tx)
expSOA := fmt.Sprintf("testdomain.com myemail@nspcc.ru %d %d %d %d %d",
b.Timestamp, refresh, retry, expire, ttl)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "getAllRecords", "testdomain.com")
v, err := TestInvoke(bc, tx)
require.NoError(t, err)
iter := v.Estack().Pop().Value().(*storage.Iterator)
require.True(t, iter.Next())
require.Equal(t, stackitem.NewStruct([]stackitem.Item{
stackitem.Make("testdomain.com"), stackitem.Make(int64(nns.A)),
stackitem.Make("1.2.3.4"), stackitem.Make(new(big.Int)),
}), iter.Value())
require.True(t, iter.Next())
require.Equal(t, stackitem.NewStruct([]stackitem.Item{
stackitem.Make("testdomain.com"), stackitem.Make(int64(nns.SOA)),
stackitem.NewBuffer([]byte(expSOA)), stackitem.Make(new(big.Int)),
}), iter.Value())
require.True(t, iter.Next())
require.Equal(t, stackitem.NewStruct([]stackitem.Item{
stackitem.Make("testdomain.com"), stackitem.Make(int64(nns.TXT)),
stackitem.Make("first TXT record"), stackitem.Make(new(big.Int)),
}), iter.Value())
require.False(t, iter.Next())
}
func TestNNSSetAdmin(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"testdomain.com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
"testdomain.com", int64(nns.TXT), "won't be added")
AddBlock(t, bc, tx)
CheckFault(t, bc, tx.Hash(), "not witnessed by admin")
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "setAdmin",
"testdomain.com", acc.Contract.ScriptHash())
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "addRecord",
"testdomain.com", int64(nns.TXT), "will be added")
AddBlockCheckHalt(t, bc, tx)
}
func TestNNSIsAvailable(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "com")
CheckTestInvoke(t, bc, tx, true)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "domain.com")
_, err := TestInvoke(bc, tx)
require.Error(t, err)
require.True(t, strings.Contains(err.Error(), "TLD not found"))
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "com")
CheckTestInvoke(t, bc, tx, false)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "domain.com")
CheckTestInvoke(t, bc, tx, true)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "register",
"domain.com", acc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, CommitteeAcc, h, "isAvailable", "domain.com")
CheckTestInvoke(t, bc, tx, false)
}
func TestNNSRenew(t *testing.T) {
bc := NewChain(t)
h := DeployContract(t, bc, nnsPath, nil)
refresh, retry, expire, ttl := int64(101), int64(102), int64(103), int64(104)
tx := PrepareInvoke(t, bc, CommitteeAcc, h, "register",
"com", CommitteeAcc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
AddBlockCheckHalt(t, bc, tx)
acc := NewAccount(t, bc)
tx = PrepareInvoke(t, bc, []*wallet.Account{CommitteeAcc, acc}, h, "register",
"testdomain.com", acc.Contract.ScriptHash(),
"myemail@nspcc.ru", refresh, retry, expire, ttl)
b := AddBlockCheckHalt(t, bc, tx)
tx = PrepareInvoke(t, bc, acc, h, "renew", "testdomain.com")
AddBlockCheckHalt(t, bc, tx)
const msPerYear = 365 * 24 * time.Hour / time.Millisecond
tx = PrepareInvoke(t, bc, acc, h, "properties", "testdomain.com")
CheckTestInvoke(t, bc, tx, stackitem.NewMapWithValue([]stackitem.MapElement{
{stackitem.Make("name"), stackitem.Make("testdomain.com")},
{stackitem.Make("expiration"), stackitem.Make(b.Timestamp + 2*uint64(msPerYear))},
}))
}