From b7c1efe7e3b404f5ad2a3528156fb5a13c834c75 Mon Sep 17 00:00:00 2001 From: Roman Khimov Date: Mon, 30 Sep 2019 17:42:37 +0300 Subject: [PATCH] core: fix References() result key type If the block references two ouputs in some other transaction the code failed to verify it because of key collision. C# code implements it properly by using full CoinReference type as a key, so let's do it in a similar fashion. --- pkg/core/blockchain.go | 10 +++++----- pkg/core/blockchainer.go | 2 +- pkg/network/helper_test.go | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index fb7db4eaf..3f955fd06 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -663,20 +663,20 @@ func (bc *Blockchain) GetConfig() config.ProtocolConfiguration { return bc.config } -// References returns a map with input prevHash as key (util.Uint256) +// References returns a map with input coin reference (prevhash and index) as key // and transaction output as value from a transaction t. // @TODO: unfortunately we couldn't attach this method to the Transaction struct in the // transaction package because of a import cycle problem. Perhaps we should think to re-design // the code base to avoid this situation. -func (bc *Blockchain) References(t *transaction.Transaction) map[util.Uint256]*transaction.Output { - references := make(map[util.Uint256]*transaction.Output, 0) +func (bc *Blockchain) References(t *transaction.Transaction) map[transaction.Input]*transaction.Output { + references := make(map[transaction.Input]*transaction.Output) for prevHash, inputs := range t.GroupInputsByPrevHash() { if tx, _, err := bc.GetTransaction(prevHash); err != nil { tx = nil } else if tx != nil { for _, in := range inputs { - references[in.PrevHash] = tx.Outputs[in.PrevIndex] + references[*in] = tx.Outputs[in.PrevIndex] } } else { references = nil @@ -925,7 +925,7 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([ } hashes := make(map[util.Uint160]bool) for _, i := range t.Inputs { - h := references[i.PrevHash].ScriptHash + h := references[*i].ScriptHash if _, ok := hashes[h]; !ok { hashes[h] = true } diff --git a/pkg/core/blockchainer.go b/pkg/core/blockchainer.go index ba0b6d732..53f1d6400 100644 --- a/pkg/core/blockchainer.go +++ b/pkg/core/blockchainer.go @@ -24,7 +24,7 @@ type Blockchainer interface { GetAssetState(util.Uint256) *AssetState GetAccountState(util.Uint160) *AccountState GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error) - References(t *transaction.Transaction) map[util.Uint256]*transaction.Output + References(t *transaction.Transaction) map[transaction.Input]*transaction.Output Feer // fee interface Verify(t *transaction.Transaction) error GetMemPool() MemPool diff --git a/pkg/network/helper_test.go b/pkg/network/helper_test.go index 5580f3873..09fafb87d 100644 --- a/pkg/network/helper_test.go +++ b/pkg/network/helper_test.go @@ -22,7 +22,7 @@ func (chain testChain) GetConfig() config.ProtocolConfiguration { panic("TODO") } -func (chain testChain) References(t *transaction.Transaction) map[util.Uint256]*transaction.Output { +func (chain testChain) References(t *transaction.Transaction) map[transaction.Input]*transaction.Output { panic("TODO") }