From 5e56919f11e31bed3f77cc322b9116f87cee13e5 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Wed, 2 Aug 2023 13:42:44 +0200 Subject: [PATCH 1/2] Unify ContextInput and Input --- api_v3.go | 6 +++--- builder/transaction_builder.go | 2 +- input.go | 10 +++++++--- input_block_issuance_credit.go | 4 ++-- input_commitment.go | 4 ++-- input_context.go | 30 ++++++------------------------ input_reward.go | 4 ++-- input_test.go | 12 ++++++------ transaction_essence.go | 2 +- 9 files changed, 30 insertions(+), 44 deletions(-) diff --git a/api_v3.go b/api_v3.go index 169d4656d..511282849 100644 --- a/api_v3.go +++ b/api_v3.go @@ -437,13 +437,13 @@ func V3API(protoParams ProtocolParameters) API { must(api.RegisterTypeSettings(TransactionEssence{}, serix.TypeSettings{}.WithObjectType(TransactionEssenceNormal))) must(api.RegisterTypeSettings(CommitmentInput{}, - serix.TypeSettings{}.WithObjectType(uint8(ContextInputCommitment))), + serix.TypeSettings{}.WithObjectType(uint8(InputCommitment))), ) must(api.RegisterTypeSettings(BlockIssuanceCreditInput{}, - serix.TypeSettings{}.WithObjectType(uint8(ContextInputBlockIssuanceCredit))), + serix.TypeSettings{}.WithObjectType(uint8(InputBlockIssuanceCredit))), ) must(api.RegisterTypeSettings(RewardInput{}, - serix.TypeSettings{}.WithObjectType(uint8(ContextInputReward))), + serix.TypeSettings{}.WithObjectType(uint8(InputReward))), ) must(api.RegisterTypeSettings(TxEssenceContextInputs{}, diff --git a/builder/transaction_builder.go b/builder/transaction_builder.go index 7c13a6f4b..ad5c9d5df 100644 --- a/builder/transaction_builder.go +++ b/builder/transaction_builder.go @@ -54,7 +54,7 @@ func (b *TransactionBuilder) AddInput(input *TxInput) *TransactionBuilder { type TransactionBuilderInputFilter func(outputID iotago.OutputID, input iotago.Output) bool // AddContextInput adds the given context input to the builder. -func (b *TransactionBuilder) AddContextInput(contextInput iotago.ContextInput) *TransactionBuilder { +func (b *TransactionBuilder) AddContextInput(contextInput iotago.Input) *TransactionBuilder { b.essence.ContextInputs = append(b.essence.ContextInputs, contextInput) return b diff --git a/input.go b/input.go index edd7695f5..057228750 100644 --- a/input.go +++ b/input.go @@ -13,6 +13,12 @@ type InputType byte const ( // InputUTXO is a type of input which references an unspent transaction output. InputUTXO InputType = iota + // InputCommitment is a type of input which references a commitment. + InputCommitment + // InputBlockIssuanceCredit is a type of input which references the block issuance credit from a specific account and commitment, the latter being provided by a commitment input. + InputBlockIssuanceCredit + // InputReward is a type of input which references an Account or Delegation Input for which to claim rewards. + InputReward ) func (inputType InputType) String() string { @@ -23,9 +29,7 @@ func (inputType InputType) String() string { return inputNames[inputType] } -var ( - inputNames = [InputUTXO + 1]string{"UTXOInput"} -) +var inputNames = [InputUTXO + 1]string{"UTXOInput"} var ( // ErrRefUTXOIndexInvalid gets returned on invalid UTXO indices. diff --git a/input_block_issuance_credit.go b/input_block_issuance_credit.go index e6b5425d3..9cc8b3fe2 100644 --- a/input_block_issuance_credit.go +++ b/input_block_issuance_credit.go @@ -8,8 +8,8 @@ type BlockIssuanceCreditInput struct { AccountID AccountID `serix:"0,mapKey=accountId"` } -func (b *BlockIssuanceCreditInput) Type() ContextInputType { - return ContextInputBlockIssuanceCredit +func (b *BlockIssuanceCreditInput) Type() InputType { + return InputBlockIssuanceCredit } func (b *BlockIssuanceCreditInput) Size() int { diff --git a/input_commitment.go b/input_commitment.go index 3df476885..72530f1c5 100644 --- a/input_commitment.go +++ b/input_commitment.go @@ -8,8 +8,8 @@ type CommitmentInput struct { CommitmentID CommitmentID `serix:"0,mapKey=commitmentId"` } -func (c *CommitmentInput) Type() ContextInputType { - return ContextInputCommitment +func (c *CommitmentInput) Type() InputType { + return InputCommitment } func (c *CommitmentInput) Size() int { diff --git a/input_context.go b/input_context.go index ff6f15cfc..b99d4c775 100644 --- a/input_context.go +++ b/input_context.go @@ -10,15 +10,6 @@ import ( // ContextInputType defines the type of context inputs. type ContextInputType byte -const ( - // ContextInputCommitment is a type of input which references a commitment. - ContextInputCommitment ContextInputType = iota - // ContextInputBlockIssuanceCredit is a type of input which references the block issuance credit from a specific account and commitment, the latter being provided by a commitment input. - ContextInputBlockIssuanceCredit - // ContextInputReward is a type of input which references an Account or Delegation Input for which to claim rewards. - ContextInputReward -) - func (inputType ContextInputType) String() string { if int(inputType) >= len(contextInputNames) { return fmt.Sprintf("unknown input type: %d", inputType) @@ -27,12 +18,10 @@ func (inputType ContextInputType) String() string { return contextInputNames[inputType] } -var ( - contextInputNames = [ContextInputReward + 1]string{"CommitmentInput", "BlockIssuanceCreditInput", "RewardInput"} -) +var contextInputNames = [InputReward + 1]string{"CommitmentInput", "BlockIssuanceCreditInput", "RewardInput"} // ContextInputs is a slice of ContextInput. -type ContextInputs[T ContextInput] []T +type ContextInputs[T Input] []T func (in ContextInputs[T]) WorkScore(workScoreStructure *WorkScoreStructure) (WorkScore, error) { // LengthPrefixType @@ -65,18 +54,9 @@ func (in ContextInputs[T]) Size() int { return sum } -// ContextInput provides an additional contextual input for transaction validation. -type ContextInput interface { - Sizer - ProcessableObject - - // Type returns the type of ContextInput. - Type() ContextInputType -} - // ContextInputsSyntacticalValidationFunc which given the index of an input and the input itself, // runs syntactical validations and returns an error if any should fail. -type ContextInputsSyntacticalValidationFunc func(index int, input ContextInput) error +type ContextInputsSyntacticalValidationFunc func(index int, input Input) error // ContextInputsSyntacticalUnique returns a ContextInputsSyntacticalValidationFunc // which checks that @@ -88,7 +68,7 @@ func ContextInputsSyntacticalUnique() ContextInputsSyntacticalValidationFunc { bicSet := map[string]int{} rewardSet := map[uint16]int{} - return func(index int, input ContextInput) error { + return func(index int, input Input) error { switch castInput := input.(type) { case *BlockIssuanceCreditInput: accountID := castInput.AccountID @@ -111,6 +91,8 @@ func ContextInputsSyntacticalUnique() ContextInputsSyntacticalValidationFunc { return ierrors.Wrapf(ErrMultipleInputCommitments, "input %d is the second commitment input", index) } hasCommitment = true + case *UTXOInput: + // ignore as we are evaluating context inputs only default: return ierrors.Wrapf(ErrUnknownContextInputType, "context input %d, tx can only contain CommitmentInputs, BlockIssuanceCreditInputs or RewardInputs", index) } diff --git a/input_reward.go b/input_reward.go index 550697d11..be1d873a2 100644 --- a/input_reward.go +++ b/input_reward.go @@ -9,8 +9,8 @@ type RewardInput struct { Index uint16 `serix:"0,mapKey=index"` } -func (r *RewardInput) Type() ContextInputType { - return ContextInputReward +func (r *RewardInput) Type() InputType { + return InputReward } func (r *RewardInput) Size() int { diff --git a/input_test.go b/input_test.go index 3a4b887c0..72a14d210 100644 --- a/input_test.go +++ b/input_test.go @@ -62,12 +62,12 @@ func TestInputsSyntacticalUnique(t *testing.T) { func TestContextInputsSyntacticalUnique(t *testing.T) { tests := []struct { name string - inputs iotago.ContextInputs[iotago.ContextInput] + inputs iotago.ContextInputs[iotago.Input] wantErr error }{ { name: "ok", - inputs: iotago.ContextInputs[iotago.ContextInput]{ + inputs: iotago.ContextInputs[iotago.Input]{ &iotago.CommitmentInput{ CommitmentID: tpkg.Rand40ByteArray(), }, @@ -88,7 +88,7 @@ func TestContextInputsSyntacticalUnique(t *testing.T) { }, { name: "fail - multiple commitment inputs", - inputs: iotago.ContextInputs[iotago.ContextInput]{ + inputs: iotago.ContextInputs[iotago.Input]{ &iotago.CommitmentInput{ CommitmentID: tpkg.Rand40ByteArray(), }, @@ -100,7 +100,7 @@ func TestContextInputsSyntacticalUnique(t *testing.T) { }, { name: "fail - block issuance credit inputs not unique", - inputs: iotago.ContextInputs[iotago.ContextInput]{ + inputs: iotago.ContextInputs[iotago.Input]{ &iotago.BlockIssuanceCreditInput{ AccountID: [32]byte{}, }, @@ -112,7 +112,7 @@ func TestContextInputsSyntacticalUnique(t *testing.T) { }, { name: "fail - reward input not unique", - inputs: iotago.ContextInputs[iotago.ContextInput]{ + inputs: iotago.ContextInputs[iotago.Input]{ &iotago.RewardInput{ Index: 1, }, @@ -124,7 +124,7 @@ func TestContextInputsSyntacticalUnique(t *testing.T) { }, { name: "fail - reward input references index greater than max inputs count", - inputs: iotago.ContextInputs[iotago.ContextInput]{ + inputs: iotago.ContextInputs[iotago.Input]{ &iotago.RewardInput{ Index: 1, }, diff --git a/transaction_essence.go b/transaction_essence.go index 836fa448b..78f240ca5 100644 --- a/transaction_essence.go +++ b/transaction_essence.go @@ -88,7 +88,7 @@ func TransactionEssenceSelector(txType uint32) (*TransactionEssence, error) { type InputsCommitment = [InputsCommitmentLength]byte type ( - txEssenceContextInput interface{ ContextInput } + txEssenceContextInput interface{ Input } txEssenceInput interface{ Input } TxEssenceOutput interface{ Output } TxEssencePayload interface{ Payload } From 236a1eaa10de781637b9dbd4f7c0ca85182dcd07 Mon Sep 17 00:00:00 2001 From: Andrea V <1577639+karimodm@users.noreply.github.com> Date: Thu, 3 Aug 2023 13:11:37 +0200 Subject: [PATCH 2/2] Resolve all generic inputs --- builder/transaction_builder.go | 4 ++-- builder/transaction_builder_test.go | 16 +++++++------- commitment.go | 9 ++++++++ input.go | 34 +++++++++++------------------ input_block_issuance_credit.go | 6 ++++- input_commitment.go | 6 ++++- input_reward.go | 10 ++++++++- input_utxo.go | 20 ++++++++--------- nodeclient/http_api_client_test.go | 12 +++++----- output.go | 2 +- transaction.go | 24 ++++++++++++++++---- vm/vm.go | 10 ++++----- 12 files changed, 93 insertions(+), 60 deletions(-) diff --git a/builder/transaction_builder.go b/builder/transaction_builder.go index ad5c9d5df..0e5aec5c1 100644 --- a/builder/transaction_builder.go +++ b/builder/transaction_builder.go @@ -120,7 +120,7 @@ func (b *TransactionBuilder) Build(signer iotago.AddressSigner) (*iotago.Transac var inputIDs iotago.OutputIDs for _, input := range b.essence.Inputs { //nolint:forcetypeassert // we can safely assume that this is an UTXOInput - inputIDs = append(inputIDs, input.(*iotago.UTXOInput).ID()) + inputIDs = append(inputIDs, input.(*iotago.UTXOInput).OutputID()) } inputs := inputIDs.OrderedSet(b.inputs) @@ -139,7 +139,7 @@ func (b *TransactionBuilder) Build(signer iotago.AddressSigner) (*iotago.Transac unlocks := iotago.Unlocks{} for i, inputRef := range b.essence.Inputs { //nolint:forcetypeassert // we can safely assume that this is an UTXOInput - addr := b.inputOwner[inputRef.(*iotago.UTXOInput).ID()] + addr := b.inputOwner[inputRef.(*iotago.UTXOInput).OutputID()] addrKey := addr.Key() pos, unlocked := unlockPos[addrKey] diff --git a/builder/transaction_builder_test.go b/builder/transaction_builder_test.go index 7e8ab6f94..0734f949d 100644 --- a/builder/transaction_builder_test.go +++ b/builder/transaction_builder_test.go @@ -31,7 +31,7 @@ func TestTransactionBuilder(t *testing.T) { inputUTXO1 := &iotago.UTXOInput{TransactionID: tpkg.Rand32ByteArray(), TransactionOutputIndex: 0} input := tpkg.RandBasicOutput(iotago.AddressEd25519) bdl := builder.NewTransactionBuilder(tpkg.TestAPI). - AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.ID(), Input: input}). + AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.OutputID(), Input: input}). AddOutput(&iotago.BasicOutput{ Amount: 50, Conditions: iotago.BasicOutputUnlockConditions{ @@ -84,10 +84,10 @@ func TestTransactionBuilder(t *testing.T) { ) bdl := builder.NewTransactionBuilder(tpkg.TestAPI). - AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputID1.ID(), Input: basicOutput}). - AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputID2.ID(), Input: nftOutput}). - AddInput(&builder.TxInput{UnlockTarget: nftOutput.Chain().ToAddress(), InputID: inputID3.ID(), Input: accountOwnedByNFT}). - AddInput(&builder.TxInput{UnlockTarget: accountOwnedByNFT.Chain().ToAddress(), InputID: inputID4.ID(), Input: basicOwnedByAccount}). + AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputID1.OutputID(), Input: basicOutput}). + AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputID2.OutputID(), Input: nftOutput}). + AddInput(&builder.TxInput{UnlockTarget: nftOutput.Chain().ToAddress(), InputID: inputID3.OutputID(), Input: accountOwnedByNFT}). + AddInput(&builder.TxInput{UnlockTarget: accountOwnedByNFT.Chain().ToAddress(), InputID: inputID4.OutputID(), Input: basicOwnedByAccount}). AddOutput(&iotago.BasicOutput{ Amount: 4000, Conditions: iotago.BasicOutputUnlockConditions{ @@ -105,7 +105,7 @@ func TestTransactionBuilder(t *testing.T) { inputUTXO1 := &iotago.UTXOInput{TransactionID: tpkg.Rand32ByteArray(), TransactionOutputIndex: 0} bdl := builder.NewTransactionBuilder(tpkg.TestAPI). - AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.ID(), Input: tpkg.RandBasicOutput(iotago.AddressEd25519)}). + AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.OutputID(), Input: tpkg.RandBasicOutput(iotago.AddressEd25519)}). AddOutput(&iotago.BasicOutput{ Amount: 50, Conditions: iotago.BasicOutputUnlockConditions{ @@ -124,7 +124,7 @@ func TestTransactionBuilder(t *testing.T) { inputUTXO1 := &iotago.UTXOInput{TransactionID: tpkg.Rand32ByteArray(), TransactionOutputIndex: 0} bdl := builder.NewTransactionBuilder(tpkg.TestAPI). - AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.ID(), Input: tpkg.RandBasicOutput(iotago.AddressEd25519)}). + AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.OutputID(), Input: tpkg.RandBasicOutput(iotago.AddressEd25519)}). AddOutput(&iotago.BasicOutput{ Amount: 50, Conditions: iotago.BasicOutputUnlockConditions{ @@ -149,7 +149,7 @@ func TestTransactionBuilder(t *testing.T) { inputUTXO1 := &iotago.UTXOInput{TransactionID: tpkg.Rand32ByteArray(), TransactionOutputIndex: 0} bdl := builder.NewTransactionBuilder(tpkg.TestAPI). - AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.ID(), Input: tpkg.RandBasicOutput(iotago.AddressEd25519)}). + AddInput(&builder.TxInput{UnlockTarget: inputAddr, InputID: inputUTXO1.OutputID(), Input: tpkg.RandBasicOutput(iotago.AddressEd25519)}). AddOutput(&iotago.BasicOutput{ Amount: 50, Conditions: iotago.BasicOutputUnlockConditions{ diff --git a/commitment.go b/commitment.go index b5b96a695..3dd85c5e0 100644 --- a/commitment.go +++ b/commitment.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/iotaledger/hive.go/ierrors" + "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/serializer/v2" ) @@ -49,6 +50,14 @@ func (c *Commitment) ID() (CommitmentID, error) { return SlotIdentifierRepresentingData(c.Index, data), nil } +func (c *Commitment) StateID() Identifier { + return IdentifierFromData(lo.PanicOnErr(c.MustID().Bytes())) +} + +func (c *Commitment) Type() StateType { + return InputCommitment +} + func (c *Commitment) MustID() CommitmentID { id, err := c.ID() if err != nil { diff --git a/input.go b/input.go index 057228750..28986e199 100644 --- a/input.go +++ b/input.go @@ -7,12 +7,12 @@ import ( "github.com/iotaledger/hive.go/serializer/v2" ) -// InputType defines the type of inputs. -type InputType byte +// StateType defines the type of inputs. +type StateType byte const ( // InputUTXO is a type of input which references an unspent transaction output. - InputUTXO InputType = iota + InputUTXO StateType = iota // InputCommitment is a type of input which references a commitment. InputCommitment // InputBlockIssuanceCredit is a type of input which references the block issuance credit from a specific account and commitment, the latter being provided by a commitment input. @@ -21,7 +21,7 @@ const ( InputReward ) -func (inputType InputType) String() string { +func (inputType StateType) String() string { if int(inputType) >= len(inputNames) { return fmt.Sprintf("unknown input type: %d", inputType) } @@ -72,23 +72,15 @@ func (in Inputs[T]) WorkScore(workScoreStructure *WorkScoreStructure) (WorkScore return workScoreBytes, nil } -// Input references a UTXO. +// Input references a generic input. type Input interface { Sizer ProcessableObject - // Type returns the type of Input. - Type() InputType -} + StateID() Identifier -// IndexedUTXOReferencer is a type of Input which references a UTXO by the transaction ID and output index. -type IndexedUTXOReferencer interface { - Input - - // Ref returns the UTXO this Input references. - Ref() OutputID - // Index returns the output index of the UTXO this Input references. - Index() uint16 + // Type returns the type of Input. + Type() StateType } // InputsSyntacticalValidationFunc which given the index of an input and the input itself, runs syntactical validations and returns an error if any should fail. @@ -100,15 +92,15 @@ func InputsSyntacticalUnique() InputsSyntacticalValidationFunc { return func(index int, input Input) error { switch castInput := input.(type) { - case IndexedUTXOReferencer: - utxoRef := castInput.Ref() + case *UTXOInput: + utxoRef := castInput.OutputID() k := string(utxoRef[:]) if j, has := utxoSet[k]; has { return ierrors.Wrapf(ErrInputUTXORefsNotUnique, "input %d and %d share the same UTXO ref", j, index) } utxoSet[k] = index default: - return ierrors.Wrapf(ErrUnknownInputType, "input %d, tx can only contain IndexedUTXOReferencer", index) + return ierrors.Wrapf(ErrUnknownInputType, "input %d, tx can only contain UTXO inputs", index) } return nil @@ -119,12 +111,12 @@ func InputsSyntacticalUnique() InputsSyntacticalValidationFunc { func InputsSyntacticalIndicesWithinBounds() InputsSyntacticalValidationFunc { return func(index int, input Input) error { switch castInput := input.(type) { - case IndexedUTXOReferencer: + case *UTXOInput: if castInput.Index() < RefUTXOIndexMin || castInput.Index() > RefUTXOIndexMax { return ierrors.Wrapf(ErrRefUTXOIndexInvalid, "input %d", index) } default: - return ierrors.Wrapf(ErrUnknownInputType, "input %d, tx can only contain IndexedUTXOReferencer inputs", index) + return ierrors.Wrapf(ErrUnknownInputType, "input %d, tx can only contain UTXInput inputs", index) } return nil diff --git a/input_block_issuance_credit.go b/input_block_issuance_credit.go index 9cc8b3fe2..9e21e4f32 100644 --- a/input_block_issuance_credit.go +++ b/input_block_issuance_credit.go @@ -8,7 +8,11 @@ type BlockIssuanceCreditInput struct { AccountID AccountID `serix:"0,mapKey=accountId"` } -func (b *BlockIssuanceCreditInput) Type() InputType { +func (b *BlockIssuanceCreditInput) StateID() Identifier { + return IdentifierFromData(b.AccountID[:]) +} + +func (b *BlockIssuanceCreditInput) Type() StateType { return InputBlockIssuanceCredit } diff --git a/input_commitment.go b/input_commitment.go index 72530f1c5..fdf38f024 100644 --- a/input_commitment.go +++ b/input_commitment.go @@ -8,7 +8,11 @@ type CommitmentInput struct { CommitmentID CommitmentID `serix:"0,mapKey=commitmentId"` } -func (c *CommitmentInput) Type() InputType { +func (c *CommitmentInput) StateID() Identifier { + return IdentifierFromData(c.CommitmentID[:]) +} + +func (c *CommitmentInput) Type() StateType { return InputCommitment } diff --git a/input_reward.go b/input_reward.go index be1d873a2..8a8079a44 100644 --- a/input_reward.go +++ b/input_reward.go @@ -1,6 +1,8 @@ package iotago import ( + "encoding/binary" + "github.com/iotaledger/hive.go/serializer/v2" ) @@ -9,7 +11,13 @@ type RewardInput struct { Index uint16 `serix:"0,mapKey=index"` } -func (r *RewardInput) Type() InputType { +func (r *RewardInput) StateID() Identifier { + buf := make([]byte, 2) + binary.LittleEndian.PutUint16(buf, r.Index) + return IdentifierFromData(buf) +} + +func (r *RewardInput) Type() StateType { return InputReward } diff --git a/input_utxo.go b/input_utxo.go index 30966cc6b..253e18c44 100644 --- a/input_utxo.go +++ b/input_utxo.go @@ -3,6 +3,7 @@ package iotago import ( "encoding/binary" + "github.com/iotaledger/hive.go/lo" "github.com/iotaledger/hive.go/serializer/v2" ) @@ -21,20 +22,15 @@ type UTXOInput struct { TransactionOutputIndex uint16 `serix:"1,mapKey=transactionOutputIndex"` } -func (u *UTXOInput) Type() InputType { - return InputUTXO -} - -func (u *UTXOInput) Ref() OutputID { - return u.ID() +func (u *UTXOInput) StateID() Identifier { + return IdentifierFromData(lo.PanicOnErr(u.OutputID().Bytes())) } -func (u *UTXOInput) Index() uint16 { - return u.TransactionOutputIndex +func (u *UTXOInput) Type() StateType { + return InputUTXO } -// ID returns the OutputID. -func (u *UTXOInput) ID() OutputID { +func (u *UTXOInput) OutputID() OutputID { var id OutputID copy(id[:TransactionIDLength], u.TransactionID[:]) binary.LittleEndian.PutUint16(id[TransactionIDLength:], u.TransactionOutputIndex) @@ -42,6 +38,10 @@ func (u *UTXOInput) ID() OutputID { return id } +func (u *UTXOInput) Index() uint16 { + return u.TransactionOutputIndex +} + func (u *UTXOInput) Equals(other *UTXOInput) bool { if u == nil { return other == nil diff --git a/nodeclient/http_api_client_test.go b/nodeclient/http_api_client_test.go index c838db70b..dcb27d7b3 100644 --- a/nodeclient/http_api_client_test.go +++ b/nodeclient/http_api_client_test.go @@ -311,7 +311,7 @@ func TestClient_OutputByID(t *testing.T) { txID := tpkg.Rand32ByteArray() utxoInput := &iotago.UTXOInput{TransactionID: txID, TransactionOutputIndex: 3} - utxoInputID := utxoInput.ID() + utxoInputID := utxoInput.OutputID() mockGetBinary(fmt.Sprintf(nodeclient.RouteOutput, utxoInputID.ToHex()), 200, originOutput) @@ -338,7 +338,7 @@ func TestClient_OutputMetadataByID(t *testing.T) { } utxoInput := &iotago.UTXOInput{TransactionID: txID, TransactionOutputIndex: 3} - utxoInputID := utxoInput.ID() + utxoInputID := utxoInput.OutputID() mockGetJSON(fmt.Sprintf(nodeclient.RouteOutputMetadata, utxoInputID.ToHex()), 200, originRes) @@ -384,10 +384,10 @@ func TestClient_CommitmentUTXOChangesByID(t *testing.T) { originRes := &apimodels.UTXOChangesResponse{ Index: 1337, CreatedOutputs: iotago.OutputIDs{ - randCreatedOutput.ID(), + randCreatedOutput.OutputID(), }, ConsumedOutputs: iotago.OutputIDs{ - randConsumedOutput.ID(), + randConsumedOutput.OutputID(), }, } @@ -432,10 +432,10 @@ func TestClient_CommitmentUTXOChangesByIndex(t *testing.T) { originRes := &apimodels.UTXOChangesResponse{ Index: slotIndex, CreatedOutputs: iotago.OutputIDs{ - randCreatedOutput.ID(), + randCreatedOutput.OutputID(), }, ConsumedOutputs: iotago.OutputIDs{ - randConsumedOutput.ID(), + randConsumedOutput.OutputID(), }, } diff --git a/output.go b/output.go index 0c7eb48ac..145056d93 100644 --- a/output.go +++ b/output.go @@ -190,7 +190,7 @@ func OutputIDFromTransactionIDAndIndex(txID TransactionID, index uint16) OutputI utxo := UTXOInput{TransactionOutputIndex: index} copy(utxo.TransactionID[:], (txID)[:]) - return utxo.ID() + return utxo.OutputID() } // OutputIDFromBytes creates a OutputID from the given bytes. diff --git a/transaction.go b/transaction.go index ee2c8a984..2cc181e92 100644 --- a/transaction.go +++ b/transaction.go @@ -43,6 +43,8 @@ type TransactionID = Identifier // TransactionIDs are IDs of transactions. type TransactionIDs []TransactionID +type TransactionContextInputs ContextInputs[Input] + // Transaction is a transaction with its inputs, outputs and unlocks. type Transaction struct { // The transaction essence, respectively the transfer part of a Transaction. @@ -79,11 +81,11 @@ func (t *Transaction) ID(api API) (TransactionID, error) { return IdentifierFromData(data), nil } -func (t *Transaction) Inputs() ([]IndexedUTXOReferencer, error) { - references := make([]IndexedUTXOReferencer, 0, len(t.Essence.Inputs)) +func (t *Transaction) Inputs() ([]*UTXOInput, error) { + references := make([]*UTXOInput, 0, len(t.Essence.Inputs)) for _, input := range t.Essence.Inputs { switch castInput := input.(type) { - case IndexedUTXOReferencer: + case *UTXOInput: references = append(references, castInput) default: return nil, ErrUnknownInputType @@ -93,6 +95,20 @@ func (t *Transaction) Inputs() ([]IndexedUTXOReferencer, error) { return references, nil } +func (t *Transaction) ContextInputs() (TransactionContextInputs, error) { + references := make(TransactionContextInputs, 0, len(t.Essence.ContextInputs)) + for _, input := range t.Essence.ContextInputs { + switch castInput := input.(type) { + case *CommitmentInput, *BlockIssuanceCreditInput, *RewardInput: + references = append(references, castInput) + default: + return nil, ErrUnknownContextInputType + } + } + + return references, nil +} + func (t *Transaction) BICInputs() ([]*BlockIssuanceCreditInput, error) { references := make([]*BlockIssuanceCreditInput, 0, len(t.Essence.ContextInputs)) for _, input := range t.Essence.ContextInputs { @@ -149,7 +165,7 @@ func (t *Transaction) Size() int { } func (t *Transaction) String() string { - //TODO: stringify for debugging purposes + // TODO: stringify for debugging purposes return fmt.Sprintf("Transaction[%v, %v]", t.Essence, t.Unlocks) } diff --git a/vm/vm.go b/vm/vm.go index 57a596806..0eac1c8fc 100644 --- a/vm/vm.go +++ b/vm/vm.go @@ -82,8 +82,8 @@ func NewVMParamsWorkingSet(api iotago.API, t *iotago.Transaction, inputs Resolve workingSet.UTXOInputsWithCreationTime = utxoInputsSet workingSet.InputIDToIndex = make(map[iotago.OutputID]uint16) for inputIndex, inputRef := range workingSet.Tx.Essence.Inputs { - //nolint:forcetypeassert // we can safely assume that this is an IndexedUTXOReferencer - ref := inputRef.(iotago.IndexedUTXOReferencer).Ref() + //nolint:forcetypeassert // we can safely assume that this is an UTXOInput + ref := inputRef.(*iotago.UTXOInput).OutputID() workingSet.InputIDToIndex[ref] = uint16(inputIndex) input, ok := workingSet.UTXOInputsWithCreationTime[ref] if !ok { @@ -355,7 +355,7 @@ func ExecFuncInputUnlocks() ExecFunc { chainID := chainConstrOutput.Chain() if chainID.Empty() { //nolint:forcetypeassert // we can safely assume that this is an UTXOIDChainID - chainID = chainID.(iotago.UTXOIDChainID).FromOutputID(vmParams.WorkingSet.UTXOInputAtIndex(uint16(inputIndex)).Ref()) + chainID = chainID.(iotago.UTXOIDChainID).FromOutputID(vmParams.WorkingSet.UTXOInputAtIndex(uint16(inputIndex)).OutputID()) } // for account outputs which are not state transitioning, we do not add it to the set of unlocked chains @@ -394,8 +394,8 @@ func identToUnlock(vmParams *Params, input iotago.Output, inputIndex uint16) (io if !is { return nil, iotago.ErrTransDepIdentOutputNonUTXOChainID } - //nolint:forcetypeassert // we can safely assume that this is an IndexedUTXOReferencer - chainID = utxoChainID.FromOutputID(vmParams.WorkingSet.Tx.Essence.Inputs[inputIndex].(iotago.IndexedUTXOReferencer).Ref()) + //nolint:forcetypeassert // we can safely assume that this is an UTXOInput + chainID = utxoChainID.FromOutputID(vmParams.WorkingSet.Tx.Essence.Inputs[inputIndex].(*iotago.UTXOInput).OutputID()) } next := vmParams.WorkingSet.OutChains[chainID]