tgo icon indicating copy to clipboard operation
tgo copied to clipboard

panic: runtime error: hash of unhashable type tracee.arrayValue

Open nkbai opened this issue 5 years ago • 7 comments

nkbai avatar May 05 '19 07:05 nkbai

my go version is 1.12 os is mac 10.13.6

nkbai avatar May 05 '19 07:05 nkbai

Thank you for opening the issue. Can you share the stack trace? The code snippet to reproduce the issue is best.

ks888 avatar May 05 '19 08:05 ks888

	for i, tt := range tests {
		// Create the account pool and generate the initial set of signers
		accounts := newTesterAccountPool()

		signers := make([]common.Address, len(tt.signers))
		for j, signer := range tt.signers {
			signers[j] = accounts.address(signer)
		}
		//对signer进行排序
		for j := 0; j < len(signers); j++ {
			for k := j + 1; k < len(signers); k++ {
				if bytes.Compare(signers[j][:], signers[k][:]) > 0 {
					signers[j], signers[k] = signers[k], signers[j]
				}
			}
		}
		// Create the genesis block with the initial set of signers
		genesis := &core.Genesis{
			ExtraData: make([]byte, extraVanity+common.AddressLength*len(signers)+extraSeal),
		}
		//放到Extra中
		for j, signer := range signers {
			copy(genesis.ExtraData[extraVanity+j*common.AddressLength:], signer[:])
		}
		// Create a pristine blockchain with the genesis injected
		db := ethdb.NewMemDatabase()
		genesis.Commit(db)

		// Assemble a chain of headers from the cast votes
		config := *params.TestChainConfig
		config.Clique = &params.CliqueConfig{
			Period: 1,
			Epoch:  tt.epoch,
		}
		engine := New(config.Clique, db)
		engine.fakeDiff = true

		blocks, _ := core.GenerateChain(&config, genesis.ToBlock(db), engine, db, len(tt.votes), func(j int, gen *core.BlockGen) {
			// Cast the vote contained in this block
			gen.SetCoinbase(accounts.address(tt.votes[j].voted))
			if tt.votes[j].auth {
				var nonce types.BlockNonce
				copy(nonce[:], nonceAuthVote)
				gen.SetNonce(nonce)
			}
		})
		// Iterate through the blocks and seal them individually
		for j, block := range blocks {
			// Geth the header and prepare it for signing
			header := block.Header()
			if j > 0 {
				header.ParentHash = blocks[j-1].Hash()
			}
			header.Extra = make([]byte, extraVanity+extraSeal)
			if auths := tt.votes[j].checkpoint; auths != nil {
				header.Extra = make([]byte, extraVanity+len(auths)*common.AddressLength+extraSeal)
				accounts.checkpoint(header, auths)
			}
			header.Difficulty = diffInTurn // Ignored, we just need a valid number

			// Generate the signature, embed it into the header and the block
			accounts.sign(header, tt.votes[j].signer)
			blocks[j] = block.WithSeal(header)
		}
		// Split the blocks up into individual import batches (cornercase testing)
		batches := [][]*types.Block{nil}
		for j, block := range blocks {
			if tt.votes[j].newbatch {
				batches = append(batches, nil)
			}
			batches[len(batches)-1] = append(batches[len(batches)-1], block)
		}
		tracer.SetTraceLevel(4)
		//tracer.SetParseLevel(5)
		tracer.SetVerboseOption(true)
		tracer.Start()
		// Pass all the headers through clique and ensure tallying succeeds
		chain, err := core.NewBlockChain(db, nil, &config, engine, vm.Config{}, nil)
		if err != nil {
			t.Errorf("test %d: failed to create test chain: %v", i, err)
			continue
		}
		failed := false
		for j := 0; j < len(batches)-1; j++ {
			if k, err := chain.InsertChain(batches[j]); err != nil {
				t.Errorf("test %d: failed to import batch %d, block %d: %v", i, j, k, err)
				failed = true
				break
			}
		}
		if failed {
			continue
		}
		if _, err = chain.InsertChain(batches[len(batches)-1]); err != tt.failure {
			t.Errorf("test %d: failure mismatch: have %v, want %v", i, err, tt.failure)
			return
		}
		if tt.failure != nil {
			continue
		}
		// No failure was produced or requested, generate the final voting snapshot
		head := blocks[len(blocks)-1]

		snap, err := engine.snapshot(chain, head.NumberU64(), head.Hash(), nil)
		if err != nil {
			t.Errorf("test %d: failed to retrieve voting snapshot: %v", i, err)
			continue
		}
		// Verify the final list of signers against the expected ones
		signers = make([]common.Address, len(tt.results))
		for j, signer := range tt.results {
			signers[j] = accounts.address(signer)
		}
		//插入排序
		for j := 0; j < len(signers); j++ {
			for k := j + 1; k < len(signers); k++ {
				if bytes.Compare(signers[j][:], signers[k][:]) > 0 {
					signers[j], signers[k] = signers[k], signers[j]
				}
			}
		}
		result := snap.signers()
		if len(result) != len(signers) {
			t.Errorf("test %d: signers mismatch: have %x, want %x", i, result, signers)
			continue
		}
		for j := 0; j < len(result); j++ {
			if !bytes.Equal(result[j][:], signers[j][:]) {
				t.Errorf("test %d, signer %d: signer mismatch: have %x, want %x", i, j, result[j], signers[j])
			}
		}
		tracer.Stop()
		break
	}

nkbai avatar May 05 '19 08:05 nkbai

// Tests that Clique signer voting is evaluated correctly for various simple and
// complex scenarios, as well as that a few special corner cases fail correctly.
func TestClique(t *testing.T) {

this function of https://github.com/ethereum/go-ethereum in this file : consensus/clique/snapshot_test.go

nkbai avatar May 05 '19 08:05 nkbai

stack: panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x135f586]

goroutine 11 [running]: github.com/nkbai/tgo/tracee.(*moduleData).retrieveUint64(0x0, 0x14d8bc0, 0xc00012a180, 0x144c2b0, 0x5, 0x46bb2e0) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/moduledata.go:141 +0x26 github.com/nkbai/tgo/tracee.(*moduleData).types(...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/moduledata.go:84 github.com/nkbai/tgo/tracee.(*Process).mapRuntimeType(0xc00015e400, 0x202020202020202, 0xc0001b6240, 0xc001428200, 0xc0001b6248, 0xc001428180) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/process.go:116 +0xf8 github.com/nkbai/tgo/tracee.valueParser.parseEmptyInterfaceValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0xc0014260c0, 0xc0006c6420, 0x10, 0x10, 0x0, 0x0, 0x0, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:484 +0x196 github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0500, 0xc0014260c0, 0xc0006c6420, 0x10, 0x10, 0x0, 0x17daa20, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:376 +0xc5e github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0540, 0xc001422cf0, 0xc0006c6420, 0x10, 0x10, 0x0, 0xc000376400, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:396 +0x12e6 github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0540, 0xc001422c90, 0xc0006c6420, 0x10, 0x10, 0x0, 0xc000376630, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:396 +0x12e6 github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0540, 0xc001422c30, 0xc0006c6420, 0x10, 0x10, 0x0, 0x203000, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:396 +0x12e6 github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0480, 0xc0014feb10, 0xc0013baf00, 0x8, 0x20, 0x0, 0xc0019f6450, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:359 +0x767 github.com/nkbai/tgo/tracee.valueParser.parseStructValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0xc001680480, 0xc0013baf00, 0x18, 0x20, 0x1, 0x0, 0x58, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:513 +0x17b github.com/nkbai/tgo/tracee.valueParser.parseSliceValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0xc001680480, 0xc0013baf00, 0x18, 0x20, 0x0, 0xc000376da8, 0x100d2c9, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:415 +0x9f github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0500, 0xc001680480, 0xc0013baf00, 0x18, 0x20, 0x0, 0xc00068ec88, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:372 +0xe23 github.com/nkbai/tgo/tracee.valueParser.parseStructValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0xc001680420, 0xc0013baf00, 0x20, 0x20, 0x1, 0xa, 0xa, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:513 +0x17b github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0500, 0xc001680420, 0xc0013baf00, 0x20, 0x20, 0x1, 0xc0003773d0, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:378 +0xb8d github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0540, 0xc0019f6150, 0xc0013baf00, 0x20, 0x20, 0x1, 0xc0003776b0, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:396 +0x12e6 github.com/nkbai/tgo/tracee.valueParser.parseValue(0x14d8bc0, 0xc00012a180, 0xc001450000, 0x14e0480, 0xc0019f60f0, 0xc0006c63e8, 0x8, 0x8, 0x1, 0xc0006fecb8, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/value.go:359 +0x767 github.com/nkbai/tgo/tracee.(*Process).currentArgs.func1(0x1, 0x1042c92, 0xc0006c63e0) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/process.go:674 +0x230 github.com/nkbai/tgo/tracee.Argument.ParseValue(0x177ce2c, 0x1, 0x14e0480, 0xc0019f60f0, 0xc0000c0550, 0x1, 0x1, 0xeabff1b3f1ea634) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracee/process.go:929 +0x3a github.com/nkbai/tgo/tracer.(*Controller).printFunctionInput(0xc0001266c0, 0x2a, 0xc0017d9f40, 0x3, 0xc0001ecb00, 0x40f8d30) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracer/controller.go:572 +0xf4 github.com/nkbai/tgo/tracer.(*Controller).handleTrapAtFunctionCall(0xc0001266c0, 0x100753b, 0x41eddb0, 0x2a, 0x3500, 0x41eddb0, 0xc0001ecb00, 0x40f8d30, 0x0, 0xc00066f850, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracer/controller.go:437 +0x3f4 github.com/nkbai/tgo/tracer.(*Controller).handleTrapBeforeFunctionCall(0xc0001266c0, 0x100753b, 0x2a, 0x3500, 0x41eddb0, 0xc0001ecb00, 0x40f8d30, 0x0, 0xc00066f850, 0x0, ...) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracer/controller.go:394 +0x205 github.com/nkbai/tgo/tracer.(*Controller).handleTrapEventOfThread(0xc0001266c0, 0x100753b, 0x13b0020, 0xc001b11340) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracer/controller.go:269 +0x247 github.com/nkbai/tgo/tracer.(*Controller).handleTrapEvent(0xc0001266c0, 0xc00066f2e0, 0x1, 0x1, 0x0, 0x13b0020, 0xc001b11340, 0x0, 0x0) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracer/controller.go:230 +0x79 github.com/nkbai/tgo/tracer.(*Controller).MainLoop(0xc0001266c0, 0x0, 0x0) /Volumes/dev/godev/src/github.com/nkbai/tgo/tracer/controller.go:171 +0x1f4 github.com/nkbai/tgo/service.(*Tracer).Attach.func1(0xc0000aa0e0) /Volumes/dev/godev/src/github.com/nkbai/tgo/service/service.go:65 +0x32 created by github.com/nkbai/tgo/service.(*Tracer).Attach /Volumes/dev/godev/src/github.com/nkbai/tgo/service/service.go:64 +0x366

nkbai avatar May 05 '19 08:05 nkbai

Thank you. I will take a look.

ks888 avatar May 05 '19 10:05 ks888

Sorry for being late. I tried to reproduce the bug, but it works as expected.

$ go version
go version go1.12.1 darwin/amd64
$ go test -v -run='TestClique' .
=== RUN   TestClique
Start tracing of go routine #34
// Too long. Skipped.
End tracing of go routine #34
--- PASS: TestClique (34.16s)
PASS
ok      github.com/ethereum/go-ethereum/consensus/clique        34.199s

Mac version is 10.14.4.

It's like the argument to *Process.mapRuntimeType() is strange (runtimeTypeAddr is 0x202020202020202). Maybe the dwarf.StructType is not parsed correctly, but it's difficult to investigate further without reproducing the bug.

ks888 avatar Aug 28 '19 15:08 ks888