github.com/codysnider/go-ethereum@v1.10.18-0.20220420071915-14f4ae99222a/cmd/evm/t8n_test.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 "reflect" 8 "strings" 9 "testing" 10 11 "github.com/docker/docker/pkg/reexec" 12 "github.com/ethereum/go-ethereum/cmd/evm/internal/t8ntool" 13 "github.com/ethereum/go-ethereum/internal/cmdtest" 14 ) 15 16 func TestMain(m *testing.M) { 17 // Run the app if we've been exec'd as "ethkey-test" in runEthkey. 18 reexec.Register("evm-test", func() { 19 if err := app.Run(os.Args); err != nil { 20 fmt.Fprintln(os.Stderr, err) 21 os.Exit(1) 22 } 23 os.Exit(0) 24 }) 25 // check if we have been reexec'd 26 if reexec.Init() { 27 return 28 } 29 os.Exit(m.Run()) 30 } 31 32 type testT8n struct { 33 *cmdtest.TestCmd 34 } 35 36 type t8nInput struct { 37 inAlloc string 38 inTxs string 39 inEnv string 40 stFork string 41 stReward string 42 } 43 44 func (args *t8nInput) get(base string) []string { 45 var out []string 46 if opt := args.inAlloc; opt != "" { 47 out = append(out, "--input.alloc") 48 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 49 } 50 if opt := args.inTxs; opt != "" { 51 out = append(out, "--input.txs") 52 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 53 } 54 if opt := args.inEnv; opt != "" { 55 out = append(out, "--input.env") 56 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 57 } 58 if opt := args.stFork; opt != "" { 59 out = append(out, "--state.fork", opt) 60 } 61 if opt := args.stReward; opt != "" { 62 out = append(out, "--state.reward", opt) 63 } 64 return out 65 } 66 67 type t8nOutput struct { 68 alloc bool 69 result bool 70 body bool 71 } 72 73 func (args *t8nOutput) get() (out []string) { 74 if args.body { 75 out = append(out, "--output.body", "stdout") 76 } else { 77 out = append(out, "--output.body", "") // empty means ignore 78 } 79 if args.result { 80 out = append(out, "--output.result", "stdout") 81 } else { 82 out = append(out, "--output.result", "") 83 } 84 if args.alloc { 85 out = append(out, "--output.alloc", "stdout") 86 } else { 87 out = append(out, "--output.alloc", "") 88 } 89 return out 90 } 91 92 func TestT8n(t *testing.T) { 93 tt := new(testT8n) 94 tt.TestCmd = cmdtest.NewTestCmd(t, tt) 95 for i, tc := range []struct { 96 base string 97 input t8nInput 98 output t8nOutput 99 expExitCode int 100 expOut string 101 }{ 102 { // Test exit (3) on bad config 103 base: "./testdata/1", 104 input: t8nInput{ 105 "alloc.json", "txs.json", "env.json", "Frontier+1346", "", 106 }, 107 output: t8nOutput{alloc: true, result: true}, 108 expExitCode: 3, 109 }, 110 { 111 base: "./testdata/1", 112 input: t8nInput{ 113 "alloc.json", "txs.json", "env.json", "Byzantium", "", 114 }, 115 output: t8nOutput{alloc: true, result: true}, 116 expOut: "exp.json", 117 }, 118 { // blockhash test 119 base: "./testdata/3", 120 input: t8nInput{ 121 "alloc.json", "txs.json", "env.json", "Berlin", "", 122 }, 123 output: t8nOutput{alloc: true, result: true}, 124 expOut: "exp.json", 125 }, 126 { // missing blockhash test 127 base: "./testdata/4", 128 input: t8nInput{ 129 "alloc.json", "txs.json", "env.json", "Berlin", "", 130 }, 131 output: t8nOutput{alloc: true, result: true}, 132 expExitCode: 4, 133 }, 134 { // Uncle test 135 base: "./testdata/5", 136 input: t8nInput{ 137 "alloc.json", "txs.json", "env.json", "Byzantium", "0x80", 138 }, 139 output: t8nOutput{alloc: true, result: true}, 140 expOut: "exp.json", 141 }, 142 { // Sign json transactions 143 base: "./testdata/13", 144 input: t8nInput{ 145 "alloc.json", "txs.json", "env.json", "London", "", 146 }, 147 output: t8nOutput{body: true}, 148 expOut: "exp.json", 149 }, 150 { // Already signed transactions 151 base: "./testdata/13", 152 input: t8nInput{ 153 "alloc.json", "signed_txs.rlp", "env.json", "London", "", 154 }, 155 output: t8nOutput{result: true}, 156 expOut: "exp2.json", 157 }, 158 { // Difficulty calculation - no uncles 159 base: "./testdata/14", 160 input: t8nInput{ 161 "alloc.json", "txs.json", "env.json", "London", "", 162 }, 163 output: t8nOutput{result: true}, 164 expOut: "exp.json", 165 }, 166 { // Difficulty calculation - with uncles 167 base: "./testdata/14", 168 input: t8nInput{ 169 "alloc.json", "txs.json", "env.uncles.json", "London", "", 170 }, 171 output: t8nOutput{result: true}, 172 expOut: "exp2.json", 173 }, 174 { // Difficulty calculation - with ommers + Berlin 175 base: "./testdata/14", 176 input: t8nInput{ 177 "alloc.json", "txs.json", "env.uncles.json", "Berlin", "", 178 }, 179 output: t8nOutput{result: true}, 180 expOut: "exp_berlin.json", 181 }, 182 { // Difficulty calculation on arrow glacier 183 base: "./testdata/19", 184 input: t8nInput{ 185 "alloc.json", "txs.json", "env.json", "London", "", 186 }, 187 output: t8nOutput{result: true}, 188 expOut: "exp_london.json", 189 }, 190 { // Difficulty calculation on arrow glacier 191 base: "./testdata/19", 192 input: t8nInput{ 193 "alloc.json", "txs.json", "env.json", "ArrowGlacier", "", 194 }, 195 output: t8nOutput{result: true}, 196 expOut: "exp_arrowglacier.json", 197 }, 198 { // Sign unprotected (pre-EIP155) transaction 199 base: "./testdata/23", 200 input: t8nInput{ 201 "alloc.json", "txs.json", "env.json", "Berlin", "", 202 }, 203 output: t8nOutput{result: true}, 204 expOut: "exp.json", 205 }, 206 } { 207 208 args := []string{"t8n"} 209 args = append(args, tc.output.get()...) 210 args = append(args, tc.input.get(tc.base)...) 211 var qArgs []string // quoted args for debugging purposes 212 for _, arg := range args { 213 if len(arg) == 0 { 214 qArgs = append(qArgs, `""`) 215 } else { 216 qArgs = append(qArgs, arg) 217 } 218 } 219 tt.Logf("args: %v\n", strings.Join(qArgs, " ")) 220 tt.Run("evm-test", args...) 221 // Compare the expected output, if provided 222 if tc.expOut != "" { 223 want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut)) 224 if err != nil { 225 t.Fatalf("test %d: could not read expected output: %v", i, err) 226 } 227 have := tt.Output() 228 ok, err := cmpJson(have, want) 229 switch { 230 case err != nil: 231 t.Fatalf("test %d, json parsing failed: %v", i, err) 232 case !ok: 233 t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want)) 234 } 235 } 236 tt.WaitExit() 237 if have, want := tt.ExitStatus(), tc.expExitCode; have != want { 238 t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) 239 } 240 } 241 } 242 243 type t9nInput struct { 244 inTxs string 245 stFork string 246 } 247 248 func (args *t9nInput) get(base string) []string { 249 var out []string 250 if opt := args.inTxs; opt != "" { 251 out = append(out, "--input.txs") 252 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 253 } 254 if opt := args.stFork; opt != "" { 255 out = append(out, "--state.fork", opt) 256 } 257 return out 258 } 259 260 func TestT9n(t *testing.T) { 261 tt := new(testT8n) 262 tt.TestCmd = cmdtest.NewTestCmd(t, tt) 263 for i, tc := range []struct { 264 base string 265 input t9nInput 266 expExitCode int 267 expOut string 268 }{ 269 { // London txs on homestead 270 base: "./testdata/15", 271 input: t9nInput{ 272 inTxs: "signed_txs.rlp", 273 stFork: "Homestead", 274 }, 275 expOut: "exp.json", 276 }, 277 { // London txs on London 278 base: "./testdata/15", 279 input: t9nInput{ 280 inTxs: "signed_txs.rlp", 281 stFork: "London", 282 }, 283 expOut: "exp2.json", 284 }, 285 { // An RLP list (a blockheader really) 286 base: "./testdata/15", 287 input: t9nInput{ 288 inTxs: "blockheader.rlp", 289 stFork: "London", 290 }, 291 expOut: "exp3.json", 292 }, 293 { // Transactions with too low gas 294 base: "./testdata/16", 295 input: t9nInput{ 296 inTxs: "signed_txs.rlp", 297 stFork: "London", 298 }, 299 expOut: "exp.json", 300 }, 301 { // Transactions with value exceeding 256 bits 302 base: "./testdata/17", 303 input: t9nInput{ 304 inTxs: "signed_txs.rlp", 305 stFork: "London", 306 }, 307 expOut: "exp.json", 308 }, 309 { // Invalid RLP 310 base: "./testdata/18", 311 input: t9nInput{ 312 inTxs: "invalid.rlp", 313 stFork: "London", 314 }, 315 expExitCode: t8ntool.ErrorIO, 316 }, 317 } { 318 319 args := []string{"t9n"} 320 args = append(args, tc.input.get(tc.base)...) 321 322 tt.Run("evm-test", args...) 323 tt.Logf("args:\n go run . %v\n", strings.Join(args, " ")) 324 // Compare the expected output, if provided 325 if tc.expOut != "" { 326 want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut)) 327 if err != nil { 328 t.Fatalf("test %d: could not read expected output: %v", i, err) 329 } 330 have := tt.Output() 331 ok, err := cmpJson(have, want) 332 switch { 333 case err != nil: 334 t.Logf(string(have)) 335 t.Fatalf("test %d, json parsing failed: %v", i, err) 336 case !ok: 337 t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want)) 338 } 339 } 340 tt.WaitExit() 341 if have, want := tt.ExitStatus(), tc.expExitCode; have != want { 342 t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) 343 } 344 } 345 } 346 347 type b11rInput struct { 348 inEnv string 349 inOmmersRlp string 350 inTxsRlp string 351 inClique string 352 ethash bool 353 ethashMode string 354 ethashDir string 355 } 356 357 func (args *b11rInput) get(base string) []string { 358 var out []string 359 if opt := args.inEnv; opt != "" { 360 out = append(out, "--input.header") 361 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 362 } 363 if opt := args.inOmmersRlp; opt != "" { 364 out = append(out, "--input.ommers") 365 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 366 } 367 if opt := args.inTxsRlp; opt != "" { 368 out = append(out, "--input.txs") 369 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 370 } 371 if opt := args.inClique; opt != "" { 372 out = append(out, "--seal.clique") 373 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 374 } 375 if args.ethash { 376 out = append(out, "--seal.ethash") 377 } 378 if opt := args.ethashMode; opt != "" { 379 out = append(out, "--seal.ethash.mode") 380 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 381 } 382 if opt := args.ethashDir; opt != "" { 383 out = append(out, "--seal.ethash.dir") 384 out = append(out, fmt.Sprintf("%v/%v", base, opt)) 385 } 386 out = append(out, "--output.block") 387 out = append(out, "stdout") 388 return out 389 } 390 391 func TestB11r(t *testing.T) { 392 tt := new(testT8n) 393 tt.TestCmd = cmdtest.NewTestCmd(t, tt) 394 for i, tc := range []struct { 395 base string 396 input b11rInput 397 expExitCode int 398 expOut string 399 }{ 400 { // unsealed block 401 base: "./testdata/20", 402 input: b11rInput{ 403 inEnv: "header.json", 404 inOmmersRlp: "ommers.json", 405 inTxsRlp: "txs.rlp", 406 }, 407 expOut: "exp.json", 408 }, 409 { // ethash test seal 410 base: "./testdata/21", 411 input: b11rInput{ 412 inEnv: "header.json", 413 inOmmersRlp: "ommers.json", 414 inTxsRlp: "txs.rlp", 415 }, 416 expOut: "exp.json", 417 }, 418 { // clique test seal 419 base: "./testdata/21", 420 input: b11rInput{ 421 inEnv: "header.json", 422 inOmmersRlp: "ommers.json", 423 inTxsRlp: "txs.rlp", 424 inClique: "clique.json", 425 }, 426 expOut: "exp-clique.json", 427 }, 428 { // block with ommers 429 base: "./testdata/22", 430 input: b11rInput{ 431 inEnv: "header.json", 432 inOmmersRlp: "ommers.json", 433 inTxsRlp: "txs.rlp", 434 }, 435 expOut: "exp.json", 436 }, 437 } { 438 439 args := []string{"b11r"} 440 args = append(args, tc.input.get(tc.base)...) 441 442 tt.Run("evm-test", args...) 443 tt.Logf("args:\n go run . %v\n", strings.Join(args, " ")) 444 // Compare the expected output, if provided 445 if tc.expOut != "" { 446 want, err := os.ReadFile(fmt.Sprintf("%v/%v", tc.base, tc.expOut)) 447 if err != nil { 448 t.Fatalf("test %d: could not read expected output: %v", i, err) 449 } 450 have := tt.Output() 451 ok, err := cmpJson(have, want) 452 switch { 453 case err != nil: 454 t.Logf(string(have)) 455 t.Fatalf("test %d, json parsing failed: %v", i, err) 456 case !ok: 457 t.Fatalf("test %d: output wrong, have \n%v\nwant\n%v\n", i, string(have), string(want)) 458 } 459 } 460 tt.WaitExit() 461 if have, want := tt.ExitStatus(), tc.expExitCode; have != want { 462 t.Fatalf("test %d: wrong exit code, have %d, want %d", i, have, want) 463 } 464 } 465 } 466 467 // cmpJson compares the JSON in two byte slices. 468 func cmpJson(a, b []byte) (bool, error) { 469 var j, j2 interface{} 470 if err := json.Unmarshal(a, &j); err != nil { 471 return false, err 472 } 473 if err := json.Unmarshal(b, &j2); err != nil { 474 return false, err 475 } 476 return reflect.DeepEqual(j2, j), nil 477 }