You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
291 lines
14 KiB
291 lines
14 KiB
package vm
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"math/big"
|
|
"testing"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
"github.com/ethereum/go-ethereum/ethdb"
|
|
"github.com/harmony-one/harmony/core/state"
|
|
"github.com/harmony-one/harmony/core/types"
|
|
"github.com/harmony-one/harmony/internal/params"
|
|
stakingTypes "github.com/harmony-one/harmony/staking/types"
|
|
)
|
|
|
|
type writeCapablePrecompileTest struct {
|
|
input, expected []byte
|
|
name string
|
|
expectedError error
|
|
p *WriteCapablePrecompiledContract
|
|
value *big.Int
|
|
}
|
|
|
|
func CollectRewardsFn() CollectRewardsFunc {
|
|
return func(db StateDB, rosettaTracer RosettaTracer, collectRewards *stakingTypes.CollectRewards) error {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func DelegateFn() DelegateFunc {
|
|
return func(db StateDB, rosettaTracer RosettaTracer, delegate *stakingTypes.Delegate) error {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func UndelegateFn() UndelegateFunc {
|
|
return func(db StateDB, rosettaTracer RosettaTracer, undelegate *stakingTypes.Undelegate) error {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func CreateValidatorFn() CreateValidatorFunc {
|
|
return func(db StateDB, rosettaTracer RosettaTracer, createValidator *stakingTypes.CreateValidator) error {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
func EditValidatorFn() EditValidatorFunc {
|
|
return func(db StateDB, rosettaTracer RosettaTracer, editValidator *stakingTypes.EditValidator) error {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
//func MigrateDelegationsFn() MigrateDelegationsFunc {
|
|
// return func(db StateDB, migrationMsg *stakingTypes.MigrationMsg) ([]interface{}, error) {
|
|
// return nil, nil
|
|
// }
|
|
//}
|
|
|
|
func CalculateMigrationGasFn() CalculateMigrationGasFunc {
|
|
return func(db StateDB, migrationMsg *stakingTypes.MigrationMsg, homestead bool, istanbul bool) (uint64, error) {
|
|
return 0, nil
|
|
}
|
|
}
|
|
|
|
func testWriteCapablePrecompile(test writeCapablePrecompileTest, t *testing.T, env *EVM, p WriteCapablePrecompiledContract) {
|
|
t.Run(fmt.Sprintf("%s", test.name), func(t *testing.T) {
|
|
contract := NewContract(AccountRef(common.HexToAddress("1337")), AccountRef(common.HexToAddress("1338")), new(big.Int), 0)
|
|
gas, err := p.RequiredGas(env, contract, test.input)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
contract.Gas = gas
|
|
if res, err := RunWriteCapablePrecompiledContract(p, env, contract, test.input, false, test.value); err != nil {
|
|
if test.expectedError != nil {
|
|
if test.expectedError.Error() != err.Error() {
|
|
t.Errorf("Expected error %v, got %v", test.expectedError, err)
|
|
}
|
|
} else {
|
|
t.Error(err)
|
|
}
|
|
} else {
|
|
if test.expectedError != nil {
|
|
t.Errorf("Expected an error %v but instead got result %v", test.expectedError, res)
|
|
}
|
|
if bytes.Compare(res, test.expected) != 0 {
|
|
t.Errorf("Expected %v, got %v", test.expected, res)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func testStakingPrecompile(test writeCapablePrecompileTest, t *testing.T) {
|
|
var env = NewEVM(Context{CollectRewards: CollectRewardsFn(),
|
|
Delegate: DelegateFn(),
|
|
Undelegate: UndelegateFn(),
|
|
CreateValidator: CreateValidatorFn(),
|
|
EditValidator: EditValidatorFn(),
|
|
ShardID: 0,
|
|
//MigrateDelegations: MigrateDelegationsFn(),
|
|
CalculateMigrationGas: CalculateMigrationGasFn(),
|
|
}, nil, params.TestChainConfig, Config{})
|
|
p := &stakingPrecompile{}
|
|
testWriteCapablePrecompile(test, t, env, p)
|
|
}
|
|
|
|
var StakingPrecompileTests = []writeCapablePrecompileTest{
|
|
{
|
|
input: []byte{109, 107, 47, 120},
|
|
expectedError: errors.New("no method with id: 0x6d6b2f78"),
|
|
name: "badStakingKind",
|
|
},
|
|
{
|
|
input: []byte{0, 0},
|
|
expectedError: errors.New("data too short (2 bytes) for abi method lookup"),
|
|
name: "malformedInput",
|
|
},
|
|
{
|
|
input: []byte{109, 107, 47, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55},
|
|
expected: nil,
|
|
name: "collectRewardsSuccess",
|
|
},
|
|
{
|
|
input: []byte{109, 107, 47, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56},
|
|
expectedError: errors.New("[StakingPrecompile] Address mismatch, expected 0x0000000000000000000000000000000000001337 have 0x0000000000000000000000000000000000001338"),
|
|
name: "collectRewardsAddressMismatch",
|
|
},
|
|
{
|
|
input: []byte{109, 107, 47, 119, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19},
|
|
expectedError: errors.New("abi: cannot marshal in to go type: length insufficient 31 require 32"),
|
|
name: "collectRewardsInvalidABI",
|
|
},
|
|
{
|
|
input: []byte{81, 11, 17, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0},
|
|
expected: nil,
|
|
name: "delegateSuccess",
|
|
},
|
|
{
|
|
input: []byte{81, 11, 17, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0},
|
|
expectedError: errors.New("abi: cannot marshal in to go type: length insufficient 95 require 96"),
|
|
name: "delegateInvalidABI",
|
|
},
|
|
{
|
|
input: []byte{81, 11, 17, 187, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0},
|
|
expectedError: errors.New("[StakingPrecompile] Address mismatch, expected 0x0000000000000000000000000000000000001337 have 0x0000000000000000000000000000000000001338"),
|
|
name: "delegateAddressMismatch",
|
|
},
|
|
|
|
{
|
|
input: []byte{189, 168, 192, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0},
|
|
expected: nil,
|
|
name: "undelegateSuccess",
|
|
},
|
|
{
|
|
input: []byte{189, 168, 192, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0},
|
|
expectedError: errors.New("abi: cannot marshal in to go type: length insufficient 95 require 96"),
|
|
name: "undelegateInvalidABI",
|
|
},
|
|
{
|
|
input: []byte{189, 168, 192, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0},
|
|
expectedError: errors.New("[StakingPrecompile] Address mismatch, expected 0x0000000000000000000000000000000000001337 have 0x0000000000000000000000000000000000001338"),
|
|
name: "undelegateAddressMismatch",
|
|
},
|
|
{
|
|
input: []byte{189, 168, 192, 233, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0},
|
|
expectedError: errors.New("[StakingPrecompile] Address mismatch, expected 0x0000000000000000000000000000000000001337 have 0x0000000000000000000000000000000000001338"),
|
|
name: "undelegateAddressMismatch",
|
|
},
|
|
//{
|
|
// input: []byte{42, 5, 187, 113},
|
|
// expectedError: errors.New("abi: attempting to unmarshall an empty string while arguments are expected"),
|
|
// name: "yesMethodNoData",
|
|
//},
|
|
//{
|
|
// input: []byte{0, 0},
|
|
// expectedError: errors.New("data too short (2 bytes) for abi method lookup"),
|
|
// name: "malformedInput",
|
|
//},
|
|
//{
|
|
// input: []byte{42, 5, 187, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56},
|
|
// expected: nil,
|
|
// name: "migrationSuccess",
|
|
//},
|
|
//{
|
|
// input: []byte{42, 5, 187, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55},
|
|
// expectedError: errors.New("[StakingPrecompile] Address mismatch, expected 0x0000000000000000000000000000000000001337 have 0x0000000000000000000000000000000000001338"),
|
|
// name: "migrationAddressMismatch",
|
|
//},
|
|
//{
|
|
// input: []byte{42, 6, 187, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55},
|
|
// expectedError: errors.New("no method with id: 0x2a06bb71"),
|
|
// name: "migrationNoMatchingMethod",
|
|
//},
|
|
//{
|
|
// input: []byte{42, 5, 187, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19},
|
|
// expectedError: errors.New("abi: cannot marshal in to go type: length insufficient 63 require 64"),
|
|
// name: "migrationAddressMismatch",
|
|
//},
|
|
}
|
|
|
|
func TestStakingPrecompiles(t *testing.T) {
|
|
for _, test := range StakingPrecompileTests {
|
|
testStakingPrecompile(test, t)
|
|
}
|
|
}
|
|
|
|
func TestWriteCapablePrecompilesReadOnly(t *testing.T) {
|
|
p := &stakingPrecompile{}
|
|
expectedError := errWriteProtection
|
|
res, err := RunWriteCapablePrecompiledContract(p, nil, nil, []byte{}, true, nil)
|
|
if err != nil {
|
|
if err.Error() != expectedError.Error() {
|
|
t.Errorf("Expected error %v, got %v", expectedError, err)
|
|
}
|
|
} else {
|
|
t.Errorf("Expected an error %v but instead got result %v", expectedError, res)
|
|
}
|
|
}
|
|
|
|
func transfer(db StateDB, sender, recipient common.Address, amount *big.Int, txType types.TransactionType) {
|
|
}
|
|
|
|
func testCrossShardXferPrecompile(test writeCapablePrecompileTest, t *testing.T) {
|
|
// this EVM needs stateDB, Transfer, and NumShards
|
|
var db ethdb.Database
|
|
var err error
|
|
defer func() {
|
|
if db != nil {
|
|
db.Close()
|
|
}
|
|
}()
|
|
if db, err = rawdb.NewLevelDBDatabase("/tmp/harmony_shard_0", 256, 1024, ""); err != nil {
|
|
db = nil
|
|
t.Fatalf("Could not initialize db %s", err)
|
|
}
|
|
stateCache := state.NewDatabase(db)
|
|
state, err := state.New(common.Hash{}, stateCache)
|
|
if err != nil {
|
|
t.Fatalf("Error while initializing state %s", err)
|
|
}
|
|
var env = NewEVM(Context{
|
|
NumShards: 4,
|
|
Transfer: transfer,
|
|
}, state, params.TestChainConfig, Config{})
|
|
p := &crossShardXferPrecompile{}
|
|
testWriteCapablePrecompile(test, t, env, p)
|
|
}
|
|
|
|
func TestCrossShardXferPrecompile(t *testing.T) {
|
|
for _, test := range CrossShardXferPrecompileTests {
|
|
testCrossShardXferPrecompile(test, t)
|
|
}
|
|
}
|
|
|
|
var CrossShardXferPrecompileTests = []writeCapablePrecompileTest{
|
|
{
|
|
input: []byte{40, 72, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 36, 21, 19, 218, 159, 68, 99, 241, 212, 135, 75, 84, 141, 251, 172, 41, 217, 31, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
expected: nil,
|
|
name: "crossShardSuccess",
|
|
value: new(big.Int).Mul(big.NewInt(100), big.NewInt(1e18)),
|
|
},
|
|
{
|
|
input: []byte{40, 72, 8, 1},
|
|
expectedError: errors.New("no method with id: 0x28480801"),
|
|
name: "crossShardMethodSigFail",
|
|
},
|
|
{
|
|
input: []byte{40, 72, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 36, 21, 19, 218, 159, 68, 99, 241, 212, 135, 75, 84, 141, 251, 172, 41, 217, 31, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
expectedError: errors.New("abi: cannot marshal in to go type: length insufficient 95 require 96"),
|
|
name: "crossShardMalformedInputFail",
|
|
},
|
|
{
|
|
input: []byte{40, 72, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 36, 21, 19, 218, 159, 68, 99, 241, 212, 135, 75, 84, 141, 251, 172, 41, 217, 31, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6},
|
|
expectedError: errors.New("toShardId out of bounds"),
|
|
name: "crossShardOutOfBoundsFail",
|
|
},
|
|
{
|
|
input: []byte{40, 72, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 36, 21, 19, 218, 159, 68, 99, 241, 212, 135, 75, 84, 141, 251, 172, 41, 217, 31, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
|
expectedError: errors.New("from and to shard id can't be equal"),
|
|
name: "crossShardSameShardFail",
|
|
},
|
|
{
|
|
input: []byte{40, 72, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 107, 199, 94, 45, 99, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 165, 36, 21, 19, 218, 159, 68, 99, 241, 212, 135, 75, 84, 141, 251, 172, 41, 217, 31, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1},
|
|
expectedError: errors.New("argument value and msg.value not equal"),
|
|
name: "crossShardDiffValueFail",
|
|
value: new(big.Int).Mul(big.NewInt(1000), big.NewInt(1e18)),
|
|
},
|
|
}
|
|
|