github.com/arieschain/arieschain@v0.0.0-20191023063405-37c074544356/signer/core/abihelper_test.go (about)

     1  
     2  package core
     3  
     4  import (
     5  	"fmt"
     6  	"strings"
     7  	"testing"
     8  
     9  	"io/ioutil"
    10  	"math/big"
    11  	"reflect"
    12  
    13  	"github.com/quickchainproject/quickchain/accounts/abi"
    14  	"github.com/quickchainproject/quickchain/common"
    15  )
    16  
    17  func verify(t *testing.T, jsondata, calldata string, exp []interface{}) {
    18  
    19  	abispec, err := abi.JSON(strings.NewReader(jsondata))
    20  	if err != nil {
    21  		t.Fatal(err)
    22  	}
    23  	cd := common.Hex2Bytes(calldata)
    24  	sigdata, argdata := cd[:4], cd[4:]
    25  	method, err := abispec.MethodById(sigdata)
    26  
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	data, err := method.Inputs.UnpackValues(argdata)
    32  
    33  	if len(data) != len(exp) {
    34  		t.Fatalf("Mismatched length, expected %d, got %d", len(exp), len(data))
    35  	}
    36  	for i, elem := range data {
    37  		if !reflect.DeepEqual(elem, exp[i]) {
    38  			t.Fatalf("Unpack error, arg %d, got %v, want %v", i, elem, exp[i])
    39  		}
    40  	}
    41  }
    42  func TestNewUnpacker(t *testing.T) {
    43  	type unpackTest struct {
    44  		jsondata string
    45  		calldata string
    46  		exp      []interface{}
    47  	}
    48  	testcases := []unpackTest{
    49  		{ // https://solidity.readthedocs.io/en/develop/abi-spec.html#use-of-dynamic-types
    50  			`[{"type":"function","name":"f", "inputs":[{"type":"uint256"},{"type":"uint32[]"},{"type":"bytes10"},{"type":"bytes"}]}]`,
    51  			// 0x123, [0x456, 0x789], "1234567890", "Hello, world!"
    52  			"8be65246" + "00000000000000000000000000000000000000000000000000000000000001230000000000000000000000000000000000000000000000000000000000000080313233343536373839300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000004560000000000000000000000000000000000000000000000000000000000000789000000000000000000000000000000000000000000000000000000000000000d48656c6c6f2c20776f726c642100000000000000000000000000000000000000",
    53  			[]interface{}{
    54  				big.NewInt(0x123),
    55  				[]uint32{0x456, 0x789},
    56  				[10]byte{49, 50, 51, 52, 53, 54, 55, 56, 57, 48},
    57  				common.Hex2Bytes("48656c6c6f2c20776f726c6421"),
    58  			},
    59  		}, { // https://github.com/quickchain/wiki/wiki/Ethereum-Contract-ABI#examples
    60  			`[{"type":"function","name":"sam","inputs":[{"type":"bytes"},{"type":"bool"},{"type":"uint256[]"}]}]`,
    61  			//  "dave", true and [1,2,3]
    62  			"a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003",
    63  			[]interface{}{
    64  				[]byte{0x64, 0x61, 0x76, 0x65},
    65  				true,
    66  				[]*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)},
    67  			},
    68  		}, {
    69  			`[{"type":"function","name":"send","inputs":[{"type":"uint256"}]}]`,
    70  			"a52c101e0000000000000000000000000000000000000000000000000000000000000012",
    71  			[]interface{}{big.NewInt(0x12)},
    72  		}, {
    73  			`[{"type":"function","name":"compareAndApprove","inputs":[{"type":"address"},{"type":"uint256"},{"type":"uint256"}]}]`,
    74  			"751e107900000000000000000000000000000133700000deadbeef00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
    75  			[]interface{}{
    76  				common.HexToAddress("0x00000133700000deadbeef000000000000000000"),
    77  				new(big.Int).SetBytes([]byte{0x00}),
    78  				big.NewInt(0x1),
    79  			},
    80  		},
    81  	}
    82  	for _, c := range testcases {
    83  		verify(t, c.jsondata, c.calldata, c.exp)
    84  	}
    85  
    86  }
    87  
    88  /*
    89  func TestReflect(t *testing.T) {
    90  	a := big.NewInt(0)
    91  	b := new(big.Int).SetBytes([]byte{0x00})
    92  	if !reflect.DeepEqual(a, b) {
    93  		t.Fatalf("Nope, %v != %v", a, b)
    94  	}
    95  }
    96  */
    97  
    98  func TestCalldataDecoding(t *testing.T) {
    99  
   100  	// send(uint256)                              : a52c101e
   101  	// compareAndApprove(address,uint256,uint256) : 751e1079
   102  	// issue(address[],uint256)                   : 42958b54
   103  	jsondata := `
   104  [
   105  	{"type":"function","name":"send","inputs":[{"name":"a","type":"uint256"}]},
   106  	{"type":"function","name":"compareAndApprove","inputs":[{"name":"a","type":"address"},{"name":"a","type":"uint256"},{"name":"a","type":"uint256"}]},
   107  	{"type":"function","name":"issue","inputs":[{"name":"a","type":"address[]"},{"name":"a","type":"uint256"}]},
   108  	{"type":"function","name":"sam","inputs":[{"name":"a","type":"bytes"},{"name":"a","type":"bool"},{"name":"a","type":"uint256[]"}]}
   109  ]`
   110  	//Expected failures
   111  	for _, hexdata := range []string{
   112  		"a52c101e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042",
   113  		"a52c101e000000000000000000000000000000000000000000000000000000000000001200",
   114  		"a52c101e00000000000000000000000000000000000000000000000000000000000000",
   115  		"a52c101e",
   116  		"a52c10",
   117  		"",
   118  		// Too short
   119  		"751e10790000000000000000000000000000000000000000000000000000000000000012",
   120  		"751e1079FFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   121  		//Not valid multiple of 32
   122  		"deadbeef00000000000000000000000000000000000000000000000000000000000000",
   123  		//Too short 'issue'
   124  		"42958b5400000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042",
   125  		// Too short compareAndApprove
   126  		"a52c101e00ff0000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000042",
   127  		// From https://github.com/quickchain/wiki/wiki/Ethereum-Contract-ABI
   128  		// contains a bool with illegal values
   129  		"a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000001100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003",
   130  	} {
   131  		_, err := parseCallData(common.Hex2Bytes(hexdata), jsondata)
   132  		if err == nil {
   133  			t.Errorf("Expected decoding to fail: %s", hexdata)
   134  		}
   135  	}
   136  
   137  	//Expected success
   138  	for _, hexdata := range []string{
   139  		// From https://github.com/quickchain/wiki/wiki/Ethereum-Contract-ABI
   140  		"a5643bf20000000000000000000000000000000000000000000000000000000000000060000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000464617665000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000003",
   141  		"a52c101e0000000000000000000000000000000000000000000000000000000000000012",
   142  		"a52c101eFFffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",
   143  		"751e1079000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
   144  		"42958b54" +
   145  			// start of dynamic type
   146  			"0000000000000000000000000000000000000000000000000000000000000040" +
   147  			//uint256
   148  			"0000000000000000000000000000000000000000000000000000000000000001" +
   149  			// length of  array
   150  			"0000000000000000000000000000000000000000000000000000000000000002" +
   151  			// array values
   152  			"000000000000000000000000000000000000000000000000000000000000dead" +
   153  			"000000000000000000000000000000000000000000000000000000000000beef",
   154  	} {
   155  		_, err := parseCallData(common.Hex2Bytes(hexdata), jsondata)
   156  		if err != nil {
   157  			t.Errorf("Unexpected failure on input %s:\n %v (%d bytes) ", hexdata, err, len(common.Hex2Bytes(hexdata)))
   158  		}
   159  	}
   160  }
   161  
   162  func TestSelectorUnmarshalling(t *testing.T) {
   163  	var (
   164  		db        *AbiDb
   165  		err       error
   166  		abistring []byte
   167  		abistruct abi.ABI
   168  	)
   169  
   170  	db, err = NewAbiDBFromFile("../../cmd/clef/4byte.json")
   171  	if err != nil {
   172  		t.Fatal(err)
   173  	}
   174  	fmt.Printf("DB size %v\n", db.Size())
   175  	for id, selector := range db.db {
   176  
   177  		abistring, err = MethodSelectorToAbi(selector)
   178  		if err != nil {
   179  			t.Error(err)
   180  			return
   181  		}
   182  		abistruct, err = abi.JSON(strings.NewReader(string(abistring)))
   183  		if err != nil {
   184  			t.Error(err)
   185  			return
   186  		}
   187  		m, err := abistruct.MethodById(common.Hex2Bytes(id[2:]))
   188  		if err != nil {
   189  			t.Error(err)
   190  			return
   191  		}
   192  		if m.Sig() != selector {
   193  			t.Errorf("Expected equality: %v != %v", m.Sig(), selector)
   194  		}
   195  	}
   196  
   197  }
   198  
   199  func TestCustomABI(t *testing.T) {
   200  	d, err := ioutil.TempDir("", "signer-4byte-test")
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  	filename := fmt.Sprintf("%s/4byte_custom.json", d)
   205  	abidb, err := NewAbiDBFromFiles("../../cmd/clef/4byte.json", filename)
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  	// Now we'll remove all existing signatures
   210  	abidb.db = make(map[string]string)
   211  	calldata := common.Hex2Bytes("a52c101edeadbeef")
   212  	_, err = abidb.LookupMethodSelector(calldata)
   213  	if err == nil {
   214  		t.Fatalf("Should not find a match on empty db")
   215  	}
   216  	if err = abidb.AddSignature("send(uint256)", calldata); err != nil {
   217  		t.Fatalf("Failed to save file: %v", err)
   218  	}
   219  	_, err = abidb.LookupMethodSelector(calldata)
   220  	if err != nil {
   221  		t.Fatalf("Should find a match for abi signature, got: %v", err)
   222  	}
   223  	//Check that it wrote to file
   224  	abidb2, err := NewAbiDBFromFile(filename)
   225  	if err != nil {
   226  		t.Fatalf("Failed to create new abidb: %v", err)
   227  	}
   228  	_, err = abidb2.LookupMethodSelector(calldata)
   229  	if err != nil {
   230  		t.Fatalf("Save failed: should find a match for abi signature after loading from disk")
   231  	}
   232  }