forked from TrueCloudLab/neoneo-go
core/transaction: use new transaction.InOut for References
We don't need a map here, use simpler structures.
This commit is contained in:
parent
80de208a68
commit
9f7018503a
5 changed files with 46 additions and 41 deletions
|
@ -1009,28 +1009,28 @@ func (bc *Blockchain) GetConfig() config.ProtocolConfiguration {
|
||||||
return bc.config
|
return bc.config
|
||||||
}
|
}
|
||||||
|
|
||||||
// References returns a map with input coin reference (prevhash and index) as key
|
// References maps transaction's inputs into a slice of InOuts, effectively
|
||||||
// and transaction output as value from a transaction t.
|
// joining each Input with the corresponding Output.
|
||||||
// @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[transaction.Input]*transaction.Output {
|
func (bc *Blockchain) References(t *transaction.Transaction) ([]transaction.InOut, error) {
|
||||||
references := make(map[transaction.Input]*transaction.Output)
|
references := make([]transaction.InOut, 0, len(t.Inputs))
|
||||||
|
|
||||||
for _, inputs := range transaction.GroupInputsByPrevHash(t.Inputs) {
|
for _, inputs := range transaction.GroupInputsByPrevHash(t.Inputs) {
|
||||||
prevHash := inputs[0].PrevHash
|
prevHash := inputs[0].PrevHash
|
||||||
tx, _, err := bc.dao.GetTransaction(prevHash)
|
tx, _, err := bc.dao.GetTransaction(prevHash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil, errors.New("bad input reference")
|
||||||
}
|
}
|
||||||
for _, in := range inputs {
|
for _, in := range inputs {
|
||||||
if int(in.PrevIndex) > len(tx.Outputs)-1 {
|
if int(in.PrevIndex) > len(tx.Outputs)-1 {
|
||||||
return nil
|
return nil, errors.New("bad input reference")
|
||||||
}
|
}
|
||||||
references[*in] = &tx.Outputs[in.PrevIndex]
|
references = append(references, transaction.InOut{In: *in, Out: tx.Outputs[in.PrevIndex]})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return references
|
return references, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// FeePerByte returns network fee divided by the size of the transaction.
|
// FeePerByte returns network fee divided by the size of the transaction.
|
||||||
|
@ -1041,9 +1041,13 @@ func (bc *Blockchain) FeePerByte(t *transaction.Transaction) util.Fixed8 {
|
||||||
// NetworkFee returns network fee.
|
// NetworkFee returns network fee.
|
||||||
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
|
func (bc *Blockchain) NetworkFee(t *transaction.Transaction) util.Fixed8 {
|
||||||
inputAmount := util.Fixed8FromInt64(0)
|
inputAmount := util.Fixed8FromInt64(0)
|
||||||
for _, txOutput := range bc.References(t) {
|
refs, err := bc.References(t)
|
||||||
if txOutput.AssetID == UtilityTokenID() {
|
if err != nil {
|
||||||
inputAmount.Add(txOutput.Amount)
|
return inputAmount
|
||||||
|
}
|
||||||
|
for i := range refs {
|
||||||
|
if refs[i].Out.AssetID == UtilityTokenID() {
|
||||||
|
inputAmount.Add(refs[i].Out.Amount)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1310,14 +1314,14 @@ func (bc *Blockchain) GetTransactionResults(t *transaction.Transaction) []*trans
|
||||||
var results []*transaction.Result
|
var results []*transaction.Result
|
||||||
tempGroupResult := make(map[util.Uint256]util.Fixed8)
|
tempGroupResult := make(map[util.Uint256]util.Fixed8)
|
||||||
|
|
||||||
references := bc.References(t)
|
references, err := bc.References(t)
|
||||||
if references == nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
for _, output := range references {
|
for _, inout := range references {
|
||||||
tempResults = append(tempResults, &transaction.Result{
|
tempResults = append(tempResults, &transaction.Result{
|
||||||
AssetID: output.AssetID,
|
AssetID: inout.Out.AssetID,
|
||||||
Amount: output.Amount,
|
Amount: inout.Out.Amount,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
for _, output := range t.Outputs {
|
for _, output := range t.Outputs {
|
||||||
|
@ -1534,16 +1538,13 @@ func (bc *Blockchain) GetScriptHashesForVerifying(t *transaction.Transaction) ([
|
||||||
if t.Type == transaction.ClaimType {
|
if t.Type == transaction.ClaimType {
|
||||||
return bc.GetScriptHashesForVerifyingClaim(t)
|
return bc.GetScriptHashesForVerifyingClaim(t)
|
||||||
}
|
}
|
||||||
references := bc.References(t)
|
references, err := bc.References(t)
|
||||||
if references == nil {
|
if err != nil {
|
||||||
return nil, errors.New("invalid inputs")
|
return nil, err
|
||||||
}
|
}
|
||||||
hashes := make(map[util.Uint160]bool)
|
hashes := make(map[util.Uint160]bool)
|
||||||
for _, i := range t.Inputs {
|
for i := range references {
|
||||||
h := references[i].ScriptHash
|
hashes[references[i].Out.ScriptHash] = true
|
||||||
if _, ok := hashes[h]; !ok {
|
|
||||||
hashes[h] = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
for _, a := range t.Attributes {
|
for _, a := range t.Attributes {
|
||||||
if a.Usage == transaction.Script {
|
if a.Usage == transaction.Script {
|
||||||
|
|
|
@ -39,7 +39,7 @@ type Blockchainer interface {
|
||||||
GetTestVM() (*vm.VM, storage.Store)
|
GetTestVM() (*vm.VM, storage.Store)
|
||||||
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
||||||
GetUnspentCoinState(util.Uint256) *UnspentCoinState
|
GetUnspentCoinState(util.Uint256) *UnspentCoinState
|
||||||
References(t *transaction.Transaction) map[transaction.Input]*transaction.Output
|
References(t *transaction.Transaction) ([]transaction.InOut, error)
|
||||||
mempool.Feer // fee interface
|
mempool.Feer // fee interface
|
||||||
PoolTx(*transaction.Transaction) error
|
PoolTx(*transaction.Transaction) error
|
||||||
VerifyTx(*transaction.Transaction, *block.Block) error
|
VerifyTx(*transaction.Transaction, *block.Block) error
|
||||||
|
|
|
@ -34,12 +34,6 @@ const (
|
||||||
DefaultAssetLifetime = 1 + BlocksPerYear
|
DefaultAssetLifetime = 1 + BlocksPerYear
|
||||||
)
|
)
|
||||||
|
|
||||||
// txInOut is used to pushed one key-value pair from References() onto the stack.
|
|
||||||
type txInOut struct {
|
|
||||||
in transaction.Input
|
|
||||||
out transaction.Output
|
|
||||||
}
|
|
||||||
|
|
||||||
// headerGetVersion returns version from the header.
|
// headerGetVersion returns version from the header.
|
||||||
func (ic *interopContext) headerGetVersion(v *vm.VM) error {
|
func (ic *interopContext) headerGetVersion(v *vm.VM) error {
|
||||||
header, err := popHeaderFromVM(v)
|
header, err := popHeaderFromVM(v)
|
||||||
|
@ -141,14 +135,16 @@ func (ic *interopContext) txGetReferences(v *vm.VM) error {
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("type mismatch: %T is not a Transaction", txInterface)
|
return fmt.Errorf("type mismatch: %T is not a Transaction", txInterface)
|
||||||
}
|
}
|
||||||
refs := ic.bc.References(tx)
|
refs, err := ic.bc.References(tx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
if len(refs) > vm.MaxArraySize {
|
if len(refs) > vm.MaxArraySize {
|
||||||
return errors.New("too many references")
|
return errors.New("too many references")
|
||||||
}
|
}
|
||||||
|
|
||||||
stackrefs := make([]vm.StackItem, 0, len(refs))
|
stackrefs := make([]vm.StackItem, 0, len(refs))
|
||||||
for _, k := range tx.Inputs {
|
for _, tio := range refs {
|
||||||
tio := txInOut{k, *refs[k]}
|
|
||||||
stackrefs = append(stackrefs, vm.NewInteropItem(tio))
|
stackrefs = append(stackrefs, vm.NewInteropItem(tio))
|
||||||
}
|
}
|
||||||
v.Estack().PushVal(stackrefs)
|
v.Estack().PushVal(stackrefs)
|
||||||
|
@ -243,11 +239,11 @@ func popInputFromVM(v *vm.VM) (*transaction.Input, error) {
|
||||||
inInterface := v.Estack().Pop().Value()
|
inInterface := v.Estack().Pop().Value()
|
||||||
input, ok := inInterface.(*transaction.Input)
|
input, ok := inInterface.(*transaction.Input)
|
||||||
if !ok {
|
if !ok {
|
||||||
txio, ok := inInterface.(txInOut)
|
txio, ok := inInterface.(transaction.InOut)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("type mismatch: %T is not an Input or txInOut", inInterface)
|
return nil, fmt.Errorf("type mismatch: %T is not an Input or InOut", inInterface)
|
||||||
}
|
}
|
||||||
input = &txio.in
|
input = &txio.In
|
||||||
}
|
}
|
||||||
return input, nil
|
return input, nil
|
||||||
}
|
}
|
||||||
|
@ -277,11 +273,11 @@ func popOutputFromVM(v *vm.VM) (*transaction.Output, error) {
|
||||||
outInterface := v.Estack().Pop().Value()
|
outInterface := v.Estack().Pop().Value()
|
||||||
output, ok := outInterface.(*transaction.Output)
|
output, ok := outInterface.(*transaction.Output)
|
||||||
if !ok {
|
if !ok {
|
||||||
txio, ok := outInterface.(txInOut)
|
txio, ok := outInterface.(transaction.InOut)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("type mismatch: %T is not an Output or txInOut", outInterface)
|
return nil, fmt.Errorf("type mismatch: %T is not an Output or InOut", outInterface)
|
||||||
}
|
}
|
||||||
output = &txio.out
|
output = &txio.Out
|
||||||
}
|
}
|
||||||
return output, nil
|
return output, nil
|
||||||
}
|
}
|
||||||
|
|
8
pkg/core/transaction/inout.go
Normal file
8
pkg/core/transaction/inout.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package transaction
|
||||||
|
|
||||||
|
// InOut represents an Input bound to its corresponding Output which is a useful
|
||||||
|
// combination for many purposes.
|
||||||
|
type InOut struct {
|
||||||
|
In Input
|
||||||
|
Out Output
|
||||||
|
}
|
|
@ -33,7 +33,7 @@ func (chain testChain) GetConfig() config.ProtocolConfiguration {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (chain testChain) References(t *transaction.Transaction) map[transaction.Input]*transaction.Output {
|
func (chain testChain) References(t *transaction.Transaction) ([]transaction.InOut, error) {
|
||||||
panic("TODO")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue