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.
This commit is contained in:
Roman Khimov 2019-09-30 17:42:37 +03:00
parent 8537700b7b
commit b7c1efe7e3
3 changed files with 7 additions and 7 deletions

View file

@ -663,20 +663,20 @@ func (bc *Blockchain) GetConfig() config.ProtocolConfiguration {
return bc.config 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. // and transaction output as value from a transaction t.
// @TODO: unfortunately we couldn't attach this method to the Transaction struct in the // @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 // transaction package because of a import cycle problem. Perhaps we should think to re-design
// the code base to avoid this situation. // the code base to avoid this situation.
func (bc *Blockchain) References(t *transaction.Transaction) map[util.Uint256]*transaction.Output { func (bc *Blockchain) References(t *transaction.Transaction) map[transaction.Input]*transaction.Output {
references := make(map[util.Uint256]*transaction.Output, 0) references := make(map[transaction.Input]*transaction.Output)
for prevHash, inputs := range t.GroupInputsByPrevHash() { for prevHash, inputs := range t.GroupInputsByPrevHash() {
if tx, _, err := bc.GetTransaction(prevHash); err != nil { if tx, _, err := bc.GetTransaction(prevHash); err != nil {
tx = nil tx = nil
} else if tx != nil { } else if tx != nil {
for _, in := range inputs { for _, in := range inputs {
references[in.PrevHash] = tx.Outputs[in.PrevIndex] references[*in] = tx.Outputs[in.PrevIndex]
} }
} else { } else {
references = nil references = nil
@ -925,7 +925,7 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
} }
hashes := make(map[util.Uint160]bool) hashes := make(map[util.Uint160]bool)
for _, i := range t.Inputs { for _, i := range t.Inputs {
h := references[i.PrevHash].ScriptHash h := references[*i].ScriptHash
if _, ok := hashes[h]; !ok { if _, ok := hashes[h]; !ok {
hashes[h] = true hashes[h] = true
} }

View file

@ -24,7 +24,7 @@ type Blockchainer interface {
GetAssetState(util.Uint256) *AssetState GetAssetState(util.Uint256) *AssetState
GetAccountState(util.Uint160) *AccountState GetAccountState(util.Uint160) *AccountState
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error) 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 Feer // fee interface
Verify(t *transaction.Transaction) error Verify(t *transaction.Transaction) error
GetMemPool() MemPool GetMemPool() MemPool

View file

@ -22,7 +22,7 @@ func (chain testChain) GetConfig() config.ProtocolConfiguration {
panic("TODO") 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") panic("TODO")
} }