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 }