From bb26a4fac6ed11aec80c4b0ae926051ee0eef061 Mon Sep 17 00:00:00 2001
From: Jens W <8270201+DragonDev1906@users.noreply.github.com>
Date: Thu, 14 Jul 2022 10:34:16 +0200
Subject: [PATCH] accounts/abi/bind/backends: return hash of new blocks
 (#25163)

Co-authored-by: Jens <jmw.1906@gmx.de>
---
 accounts/abi/bind/backends/simulated.go      |  6 ++-
 accounts/abi/bind/backends/simulated_test.go | 39 ++++++++++++++++++++
 2 files changed, 44 insertions(+), 1 deletion(-)

diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 8b1e1c46d..01f31931f 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -106,16 +106,20 @@ func (b *SimulatedBackend) Close() error {
 
 // Commit imports all the pending transactions as a single block and starts a
 // fresh new state.
-func (b *SimulatedBackend) Commit() {
+func (b *SimulatedBackend) Commit() common.Hash {
 	b.mu.Lock()
 	defer b.mu.Unlock()
 
 	if _, err := b.blockchain.InsertChain([]*types.Block{b.pendingBlock}, nil); err != nil {
 		panic(err) // This cannot happen unless the simulator is wrong, fail in that case
 	}
+	blockHash := b.pendingBlock.Hash()
+
 	// Using the last inserted block here makes it possible to build on a side
 	// chain after a fork.
 	b.rollback(b.pendingBlock)
+
+	return blockHash
 }
 
 // Rollback aborts all pending transactions, reverting to the last committed state.
diff --git a/accounts/abi/bind/backends/simulated_test.go b/accounts/abi/bind/backends/simulated_test.go
index 3b7f81df7..b23e75a66 100644
--- a/accounts/abi/bind/backends/simulated_test.go
+++ b/accounts/abi/bind/backends/simulated_test.go
@@ -1390,3 +1390,42 @@ func TestForkResendTx(t *testing.T) {
 		t.Errorf("TX included in wrong block: %d", h)
 	}
 }
+
+func TestCommitReturnValue(t *testing.T) {
+	testAddr := crypto.PubkeyToAddress(testKey.PublicKey)
+	sim := simTestBackend(testAddr)
+	defer sim.Close()
+
+	startBlockHeight := sim.blockchain.CurrentBlock().NumberU64()
+
+	// Test if Commit returns the correct block hash
+	h1 := sim.Commit()
+	if h1 != sim.blockchain.CurrentBlock().Hash() {
+		t.Error("Commit did not return the hash of the last block.")
+	}
+
+	// Create a block in the original chain (containing a transaction to force different block hashes)
+	head, _ := sim.HeaderByNumber(context.Background(), nil) // Should be child's, good enough
+	gasPrice := new(big.Int).Add(head.BaseFee, big.NewInt(1))
+	_tx := types.NewTransaction(0, testAddr, big.NewInt(1000), params.TxGas, gasPrice, nil)
+	tx, _ := types.SignTx(_tx, types.HomesteadSigner{}, testKey)
+	sim.SendTransaction(context.Background(), tx)
+	h2 := sim.Commit()
+
+	// Create another block in the original chain
+	sim.Commit()
+
+	// Fork at the first bock
+	if err := sim.Fork(context.Background(), h1); err != nil {
+		t.Errorf("forking: %v", err)
+	}
+
+	// Test if Commit returns the correct block hash after the reorg
+	h2fork := sim.Commit()
+	if h2 == h2fork {
+		t.Error("The block in the fork and the original block are the same block!")
+	}
+	if sim.blockchain.GetHeader(h2fork, startBlockHeight+2) == nil {
+		t.Error("Could not retrieve the just created block (side-chain)")
+	}
+}