2020-10-01 15:17:09 +00:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/config/netmode"
|
2020-11-05 16:34:48 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
2020-10-01 15:17:09 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/native"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/internal/testchain"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
2020-11-05 16:34:48 +00:00
|
|
|
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
2020-10-01 15:17:09 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
)
|
|
|
|
|
|
|
|
func (bc *Blockchain) setNodesByRole(t *testing.T, ok bool, r native.Role, nodes keys.PublicKeys) {
|
|
|
|
w := io.NewBufBinWriter()
|
|
|
|
for _, pub := range nodes {
|
|
|
|
emit.Bytes(w.BinWriter, pub.Bytes())
|
|
|
|
}
|
|
|
|
emit.Int(w.BinWriter, int64(len(nodes)))
|
2020-10-02 08:30:15 +00:00
|
|
|
emit.Opcodes(w.BinWriter, opcode.PACK)
|
2020-10-01 15:17:09 +00:00
|
|
|
emit.Int(w.BinWriter, int64(r))
|
|
|
|
emit.Int(w.BinWriter, 2)
|
2020-10-02 08:30:15 +00:00
|
|
|
emit.Opcodes(w.BinWriter, opcode.PACK)
|
2020-10-01 15:17:09 +00:00
|
|
|
emit.String(w.BinWriter, "designateAsRole")
|
|
|
|
emit.AppCall(w.BinWriter, bc.contracts.Designate.Hash)
|
|
|
|
require.NoError(t, w.Err)
|
|
|
|
tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 0)
|
|
|
|
tx.NetworkFee = 10_000_000
|
|
|
|
tx.SystemFee = 10_000_000
|
|
|
|
tx.ValidUntilBlock = 100
|
|
|
|
tx.Signers = []transaction.Signer{
|
|
|
|
{
|
|
|
|
Account: testchain.MultisigScriptHash(),
|
2020-10-02 13:23:48 +00:00
|
|
|
Scopes: transaction.None,
|
2020-10-01 15:17:09 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Account: testchain.CommitteeScriptHash(),
|
|
|
|
Scopes: transaction.CalledByEntry,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
require.NoError(t, signTx(bc, tx))
|
|
|
|
tx.Scripts = append(tx.Scripts, transaction.Witness{
|
|
|
|
InvocationScript: testchain.SignCommittee(tx.GetSignedPart()),
|
|
|
|
VerificationScript: testchain.CommitteeVerificationScript(),
|
|
|
|
})
|
|
|
|
require.NoError(t, bc.AddBlock(bc.newBlock(tx)))
|
|
|
|
|
2020-11-11 15:43:28 +00:00
|
|
|
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)
|
2020-10-01 15:17:09 +00:00
|
|
|
require.NoError(t, err)
|
2020-11-11 15:43:28 +00:00
|
|
|
require.Equal(t, 1, len(aer))
|
2020-10-01 15:17:09 +00:00
|
|
|
if ok {
|
2020-11-11 15:43:28 +00:00
|
|
|
require.Equal(t, vm.HaltState, aer[0].VMState)
|
2020-10-01 15:17:09 +00:00
|
|
|
} else {
|
2020-11-11 15:43:28 +00:00
|
|
|
require.Equal(t, vm.FaultState, aer[0].VMState)
|
2020-10-01 15:17:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-05 16:34:48 +00:00
|
|
|
func (bc *Blockchain) getNodesByRole(t *testing.T, ok bool, r native.Role, index uint32, resLen int) {
|
|
|
|
w := io.NewBufBinWriter()
|
|
|
|
emit.AppCallWithOperationAndArgs(w.BinWriter, bc.contracts.Designate.Hash, "getDesignatedByRole", int64(r), int64(index))
|
|
|
|
require.NoError(t, w.Err)
|
|
|
|
tx := transaction.New(netmode.UnitTestNet, w.Bytes(), 0)
|
|
|
|
tx.NetworkFee = 10_000_000
|
|
|
|
tx.SystemFee = 10_000_000
|
|
|
|
tx.ValidUntilBlock = 100
|
|
|
|
tx.Signers = []transaction.Signer{
|
|
|
|
{
|
|
|
|
Account: testchain.MultisigScriptHash(),
|
|
|
|
Scopes: transaction.None,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
require.NoError(t, signTx(bc, tx))
|
|
|
|
require.NoError(t, bc.AddBlock(bc.newBlock(tx)))
|
|
|
|
|
2020-11-11 15:43:28 +00:00
|
|
|
aer, err := bc.GetAppExecResults(tx.Hash(), trigger.Application)
|
2020-11-05 16:34:48 +00:00
|
|
|
require.NoError(t, err)
|
2020-11-11 15:43:28 +00:00
|
|
|
require.Equal(t, 1, len(aer))
|
2020-11-05 16:34:48 +00:00
|
|
|
if ok {
|
2020-11-11 15:43:28 +00:00
|
|
|
require.Equal(t, vm.HaltState, aer[0].VMState)
|
|
|
|
require.Equal(t, 1, len(aer[0].Stack))
|
|
|
|
arrItem := aer[0].Stack[0]
|
2020-11-05 16:34:48 +00:00
|
|
|
require.Equal(t, stackitem.ArrayT, arrItem.Type())
|
|
|
|
arr := arrItem.(*stackitem.Array)
|
|
|
|
require.Equal(t, resLen, arr.Len())
|
|
|
|
} else {
|
2020-11-11 15:43:28 +00:00
|
|
|
require.Equal(t, vm.FaultState, aer[0].VMState)
|
2020-11-05 16:34:48 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-10-01 15:17:09 +00:00
|
|
|
func TestDesignate_DesignateAsRoleTx(t *testing.T) {
|
|
|
|
bc := newTestChain(t)
|
|
|
|
defer bc.Close()
|
|
|
|
|
|
|
|
priv, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
pubs := keys.PublicKeys{priv.PublicKey()}
|
|
|
|
|
|
|
|
bc.setNodesByRole(t, false, 0xFF, pubs)
|
|
|
|
bc.setNodesByRole(t, true, native.RoleOracle, pubs)
|
2020-11-05 16:34:48 +00:00
|
|
|
index := bc.BlockHeight() + 1
|
|
|
|
bc.getNodesByRole(t, false, 0xFF, 0, 0)
|
|
|
|
bc.getNodesByRole(t, false, native.RoleOracle, 100500, 0)
|
|
|
|
bc.getNodesByRole(t, true, native.RoleOracle, 0, 0) // returns an empty list
|
|
|
|
bc.getNodesByRole(t, true, native.RoleOracle, index, 1) // returns pubs
|
2020-10-01 15:17:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDesignate_DesignateAsRole(t *testing.T) {
|
|
|
|
bc := newTestChain(t)
|
|
|
|
defer bc.Close()
|
|
|
|
|
|
|
|
des := bc.contracts.Designate
|
|
|
|
tx := transaction.New(netmode.UnitTestNet, []byte{}, 0)
|
2020-11-05 16:34:48 +00:00
|
|
|
bl := block.New(netmode.UnitTestNet)
|
|
|
|
bl.Index = bc.BlockHeight() + 1
|
|
|
|
ic := bc.newInteropContext(trigger.OnPersist, bc.dao, bl, tx)
|
2020-10-29 16:10:28 +00:00
|
|
|
ic.SpawnVM()
|
2020-10-01 15:17:09 +00:00
|
|
|
ic.VM.LoadScript([]byte{byte(opcode.RET)})
|
|
|
|
|
2020-11-05 16:34:48 +00:00
|
|
|
pubs, index, err := des.GetDesignatedByRole(bc.dao, 0xFF, 255)
|
2020-10-01 15:17:09 +00:00
|
|
|
require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err)
|
|
|
|
|
2020-11-05 16:34:48 +00:00
|
|
|
pubs, index, err = des.GetDesignatedByRole(bc.dao, native.RoleOracle, 255)
|
2020-10-01 15:17:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 0, len(pubs))
|
2020-11-05 16:34:48 +00:00
|
|
|
require.Equal(t, uint32(0), index)
|
2020-10-01 15:17:09 +00:00
|
|
|
|
|
|
|
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{})
|
|
|
|
require.True(t, errors.Is(err, native.ErrEmptyNodeList), "got: %v", err)
|
|
|
|
|
2020-10-21 09:50:26 +00:00
|
|
|
err = des.DesignateAsRole(ic, native.RoleOracle, make(keys.PublicKeys, 32+1))
|
|
|
|
require.True(t, errors.Is(err, native.ErrLargeNodeList), "got: %v", err)
|
|
|
|
|
2020-10-01 15:17:09 +00:00
|
|
|
priv, err := keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
pub := priv.PublicKey()
|
|
|
|
|
|
|
|
err = des.DesignateAsRole(ic, 0xFF, keys.PublicKeys{pub})
|
|
|
|
require.True(t, errors.Is(err, native.ErrInvalidRole), "got: %v", err)
|
|
|
|
|
|
|
|
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub})
|
|
|
|
require.True(t, errors.Is(err, native.ErrInvalidWitness), "got: %v", err)
|
|
|
|
|
|
|
|
setSigner(tx, testchain.CommitteeScriptHash())
|
|
|
|
err = des.DesignateAsRole(ic, native.RoleOracle, keys.PublicKeys{pub})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, des.OnPersistEnd(ic.DAO))
|
|
|
|
|
2020-11-05 16:34:48 +00:00
|
|
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle, bl.Index+1)
|
2020-10-01 15:17:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
2020-11-05 16:34:48 +00:00
|
|
|
require.Equal(t, bl.Index+1, index)
|
2020-10-01 15:17:09 +00:00
|
|
|
|
2020-11-05 16:34:48 +00:00
|
|
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator, 255)
|
2020-10-01 15:17:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 0, len(pubs))
|
2020-11-05 16:34:48 +00:00
|
|
|
require.Equal(t, uint32(0), index)
|
2020-10-01 15:17:09 +00:00
|
|
|
|
|
|
|
// Set another role.
|
|
|
|
_, err = keys.NewPrivateKey()
|
|
|
|
require.NoError(t, err)
|
|
|
|
pub1 := priv.PublicKey()
|
|
|
|
err = des.DesignateAsRole(ic, native.RoleStateValidator, keys.PublicKeys{pub1})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NoError(t, des.OnPersistEnd(ic.DAO))
|
|
|
|
|
2020-11-05 16:34:48 +00:00
|
|
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleOracle, 255)
|
2020-10-01 15:17:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, keys.PublicKeys{pub}, pubs)
|
2020-11-05 16:34:48 +00:00
|
|
|
require.Equal(t, bl.Index+1, index)
|
2020-10-01 15:17:09 +00:00
|
|
|
|
2020-11-05 16:34:48 +00:00
|
|
|
pubs, index, err = des.GetDesignatedByRole(ic.DAO, native.RoleStateValidator, 255)
|
2020-10-01 15:17:09 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, keys.PublicKeys{pub1}, pubs)
|
2020-11-05 16:34:48 +00:00
|
|
|
require.Equal(t, bl.Index+1, index)
|
2020-10-01 15:17:09 +00:00
|
|
|
}
|