Skip to content

Commit

Permalink
Merge pull request #628 from iotaledger/split-context-inputs-and-inputs
Browse files Browse the repository at this point in the history
Split Context Inputs and Inputs
  • Loading branch information
muXxer authored Dec 19, 2023
2 parents 89b5ba1 + 965bf33 commit 0ff4e9e
Show file tree
Hide file tree
Showing 15 changed files with 350 additions and 228 deletions.
44 changes: 22 additions & 22 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,21 @@ require (
github.com/gorilla/websocket v1.5.1
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/iotaledger/hive.go/ads v0.0.0-20231214025533-67add6c5091b
github.com/iotaledger/hive.go/app v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/constraints v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/crypto v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/ds v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/ierrors v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/app v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/constraints v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/core v1.0.0-rc.3.0.20231219095137-dd4674b3226e
github.com/iotaledger/hive.go/crypto v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/ds v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/ierrors v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/kvstore v0.0.0-20231214025533-67add6c5091b
github.com/iotaledger/hive.go/lo v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/log v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/runtime v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231214121634-8b23c68d408d
github.com/iotaledger/hive.go/stringify v0.0.0-20231214121634-8b23c68d408d
github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231214122225-f510ea9b00b5
github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231206124145-f773dfe3927e
github.com/iotaledger/iota.go/v4 v4.0.0-20231211160706-492c65d5e3f5
github.com/iotaledger/hive.go/lo v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/log v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/runtime v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/hive.go/serializer/v2 v2.0.0-rc.1.0.20231219095137-dd4674b3226e
github.com/iotaledger/hive.go/stringify v0.0.0-20231219105941-542b1b724494
github.com/iotaledger/inx-app v1.0.0-rc.3.0.20231219130724-cb37c927be6d
github.com/iotaledger/inx/go v1.0.0-rc.2.0.20231219130433-ad0971fe6306
github.com/iotaledger/iota.go/v4 v4.0.0-20231219130133-667f32aa821d
github.com/labstack/echo/v4 v4.11.3
github.com/labstack/gommon v0.4.1
github.com/libp2p/go-libp2p v0.32.0
Expand All @@ -40,13 +40,13 @@ require (
github.com/zyedidia/generic v1.2.1
go.uber.org/atomic v1.11.0
go.uber.org/dig v1.17.1
golang.org/x/crypto v0.16.0
google.golang.org/grpc v1.59.0
golang.org/x/crypto v0.17.0
google.golang.org/grpc v1.60.1
google.golang.org/protobuf v1.31.0
)

require (
filippo.io/edwards25519 v1.0.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/benbjohnson/clock v1.3.5 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect
Expand All @@ -60,7 +60,7 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/eclipse/paho.mqtt.golang v1.4.3 // indirect
github.com/elastic/gosigar v0.14.2 // indirect
github.com/ethereum/go-ethereum v1.13.5 // indirect
github.com/ethereum/go-ethereum v1.13.6 // indirect
github.com/fatih/structs v1.1.0 // indirect
github.com/felixge/fgprof v0.9.3 // indirect
github.com/fjl/memsize v0.0.2 // indirect
Expand Down Expand Up @@ -167,17 +167,17 @@ require (
go.uber.org/mock v0.3.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
golang.org/x/image v0.13.0 // indirect
golang.org/x/mod v0.13.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sync v0.5.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.14.0 // indirect
golang.org/x/tools v0.15.0 // indirect
gonum.org/v1/gonum v0.14.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231127180814-3a041ad873d4 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231212172506-995d672761c0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
lukechampine.com/blake3 v1.2.1 // indirect
Expand Down
90 changes: 46 additions & 44 deletions go.sum

Large diffs are not rendered by default.

39 changes: 19 additions & 20 deletions pkg/protocol/engine/ledger/ledger/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/iotaledger/hive.go/ds"
"github.com/iotaledger/hive.go/ierrors"
"github.com/iotaledger/hive.go/kvstore"
"github.com/iotaledger/hive.go/lo"
"github.com/iotaledger/hive.go/runtime/event"
"github.com/iotaledger/hive.go/runtime/module"
"github.com/iotaledger/iota-core/pkg/core/promise"
Expand Down Expand Up @@ -266,7 +267,8 @@ func (l *Ledger) Output(outputID iotago.OutputID) (*utxoledger.Output, error) {
}

func (l *Ledger) OutputOrSpent(outputID iotago.OutputID) (*utxoledger.Output, *utxoledger.Spent, error) {
stateWithMetadata, err := l.memPool.StateMetadata(outputID.UTXOInput())
stateRef := mempool.UTXOInputStateRefFromInput(outputID.UTXOInput())
stateWithMetadata, err := l.memPool.StateMetadata(stateRef)
if err != nil {
if ierrors.Is(iotago.ErrInputAlreadySpent, err) {
l.utxoLedger.ReadLockLedger()
Expand Down Expand Up @@ -613,7 +615,7 @@ func (l *Ledger) processStateDiffTransactions(stateDiff mempool.StateDiff) (spen
// process outputs
{
// input side
for _, inputRef := range inputRefs {
for _, inputRef := range lo.Map(inputRefs, mempool.UTXOInputStateRefFromInput) {
stateWithMetadata, stateError := l.memPool.StateMetadata(inputRef)
if stateError != nil {
err = ierrors.Errorf("failed to retrieve outputs of %s: %w", txID, errInput)
Expand Down Expand Up @@ -711,39 +713,36 @@ func (l *Ledger) resolveState(stateRef mempool.StateReference) *promise.Promise[
defer l.utxoLedger.ReadUnlockLedger()

switch stateRef.Type() {
case iotago.InputUTXO:
//nolint:forcetypeassert // we can safely assume that this is an UTXOInput
concreteStateRef := stateRef.(*iotago.UTXOInput)
isUnspent, err := l.utxoLedger.IsOutputIDUnspentWithoutLocking(concreteStateRef.OutputID())
case mempool.StateTypeUTXOInput:
//nolint:forcetypeassert // we can safely assume that this is a UTXOInputStateRef
utxoInput := stateRef.(mempool.UTXOInputStateRef).Input
isUnspent, err := l.utxoLedger.IsOutputIDUnspentWithoutLocking(utxoInput.OutputID())
if err != nil {
return p.Reject(ierrors.Wrapf(iotago.ErrUTXOInputInvalid, "error while retrieving output %s: %w", concreteStateRef.OutputID(), err))
return p.Reject(ierrors.Wrapf(iotago.ErrUTXOInputInvalid, "error while retrieving output %s: %w", utxoInput.OutputID(), err))
}

if !isUnspent {
return p.Reject(ierrors.Join(iotago.ErrInputAlreadySpent, ierrors.Wrapf(mempool.ErrStateNotFound, "unspent output %s not found", concreteStateRef.OutputID())))
return p.Reject(ierrors.Join(iotago.ErrInputAlreadySpent, ierrors.Wrapf(mempool.ErrStateNotFound, "unspent output %s not found", utxoInput.OutputID())))
}

// possible to cast `stateRef` to more specialized interfaces here, e.g. for DustOutput
output, err := l.utxoLedger.ReadOutputByOutputIDWithoutLocking(concreteStateRef.OutputID())
output, err := l.utxoLedger.ReadOutputByOutputIDWithoutLocking(utxoInput.OutputID())
if err != nil {
return p.Reject(ierrors.Wrapf(iotago.ErrUTXOInputInvalid, "output %s not found: %w", concreteStateRef.OutputID(), mempool.ErrStateNotFound))
return p.Reject(ierrors.Wrapf(iotago.ErrUTXOInputInvalid, "output %s not found: %w", utxoInput.OutputID(), mempool.ErrStateNotFound))
}

return p.Resolve(output)
case iotago.InputCommitment:
//nolint:forcetypeassert // we can safely assume that this is an CommitmentInput
concreteStateRef := stateRef.(*iotago.CommitmentInput)
loadedCommitment, err := l.loadCommitment(concreteStateRef.CommitmentID)
case mempool.StateTypeCommitment:
//nolint:forcetypeassert // we can safely assume that this is a CommitmentInputStateRef
commitment := stateRef.(mempool.CommitmentInputStateRef).Input
loadedCommitment, err := l.loadCommitment(commitment.CommitmentID)
if err != nil {
return p.Reject(ierrors.Join(iotago.ErrCommitmentInputInvalid, ierrors.Wrapf(err, "failed to load commitment %s", concreteStateRef.CommitmentID)))
return p.Reject(ierrors.Join(iotago.ErrCommitmentInputInvalid, ierrors.Wrapf(err, "failed to load commitment %s", commitment.CommitmentID)))
}

return p.Resolve(loadedCommitment)
case iotago.InputBlockIssuanceCredit, iotago.InputReward:
//nolint:forcetypeassert
return p.Resolve(stateRef.(mempool.State))
return p.Resolve(mempool.CommitmentInputStateFromCommitment(loadedCommitment))
default:
return p.Reject(ierrors.Errorf("unsupported input type %s", stateRef.Type()))
return p.Reject(ierrors.Errorf("unsupported input type %d", stateRef.Type()))
}
}

Expand Down
54 changes: 44 additions & 10 deletions pkg/protocol/engine/ledger/ledger/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,32 @@ func (v *VM) Inputs(transaction mempool.Transaction) (inputReferences []mempool.
}

for _, input := range stardustTransaction.TransactionEssence.Inputs {
inputReferences = append(inputReferences, input)
switch input.Type() {
case iotago.InputUTXO:
//nolint:forcetypeassert // we can safely assume that this is a UTXOInput
inputReferences = append(inputReferences, mempool.UTXOInputStateRefFromInput(
input.(*iotago.UTXOInput),
))
default:
return nil, ierrors.Errorf("unrecognized input type %d", input.Type())
}
}
for _, input := range stardustTransaction.TransactionEssence.ContextInputs {
inputReferences = append(inputReferences, input)

for _, contextInput := range stardustTransaction.TransactionEssence.ContextInputs {
switch contextInput.Type() {
case iotago.ContextInputCommitment:
//nolint:forcetypeassert // we can safely assume that this is a CommitmentInput
inputReferences = append(inputReferences, mempool.CommitmentInputStateRefFromInput(
contextInput.(*iotago.CommitmentInput),
))
// These context inputs do not need to be resolved.
case iotago.ContextInputBlockIssuanceCredit:
continue
case iotago.ContextInputReward:
continue
default:
return nil, ierrors.Errorf("unrecognized context input type %d", contextInput.Type())
}
}

return inputReferences, nil
Expand All @@ -43,21 +65,31 @@ func (v *VM) ValidateSignatures(signedTransaction mempool.SignedTransaction, res
return nil, iotago.ErrTxTypeInvalid
}

contextInputs, err := signedStardustTransaction.Transaction.ContextInputs()
if err != nil {
return nil, ierrors.Wrapf(err, "unable to retrieve context inputs from transaction")
}

utxoInputSet := iotagovm.InputSet{}
commitmentInput := (*iotago.Commitment)(nil)
bicInputs := make([]*iotago.BlockIssuanceCreditInput, 0)
rewardInputs := make([]*iotago.RewardInput, 0)

for _, resolvedInput := range resolvedInputStates {
resolvedInput.Type()
switch typedInput := resolvedInput.(type) {
case *iotago.Commitment:
commitmentInput = typedInput
case mempool.CommitmentInputState:
commitmentInput = typedInput.Commitment
case *utxoledger.Output:
utxoInputSet[typedInput.OutputID()] = typedInput.Output()
}
}

for _, contextInput := range contextInputs {
switch typedInput := contextInput.(type) {
case *iotago.BlockIssuanceCreditInput:
bicInputs = append(bicInputs, typedInput)
case *iotago.RewardInput:
rewardInputs = append(rewardInputs, typedInput)
case *utxoledger.Output:
utxoInputSet[typedInput.OutputID()] = typedInput.Output()
}
}

Expand Down Expand Up @@ -186,14 +218,16 @@ func (v *VM) Execute(executionContext context.Context, transaction mempool.Trans
return nil, err
}

outputs = append(outputs, utxoledger.CreateOutput(
output := utxoledger.CreateOutput(
v.ledger.apiProvider,
iotago.OutputIDFromTransactionIDAndIndex(transactionID, uint16(index)),
iotago.EmptyBlockID,
0,
output,
proof,
))
)

outputs = append(outputs, output)
}

return outputs, nil
Expand Down
5 changes: 3 additions & 2 deletions pkg/protocol/engine/ledger/tests/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package ledgertests

import (
"github.com/iotaledger/hive.go/lo"
"github.com/iotaledger/iota-core/pkg/protocol/engine/mempool"
iotago "github.com/iotaledger/iota.go/v4"
)

Expand All @@ -23,8 +24,8 @@ func (m *MockedState) StateID() iotago.Identifier {
return iotago.IdentifierFromData(lo.PanicOnErr(m.id.Bytes()))
}

func (m *MockedState) Type() iotago.StateType {
return iotago.InputUTXO
func (m *MockedState) Type() mempool.StateType {
return mempool.StateTypeUTXOInput
}

func (m *MockedState) IsReadOnly() bool {
Expand Down
8 changes: 8 additions & 0 deletions pkg/protocol/engine/mempool/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ type MemPool[VoteRank spenddag.VoteRankType[VoteRank]] interface {
// Reset resets the component to a clean state as if it was created at the last commitment.
Reset()
}

// Denotes the type of state.
type StateType byte

const (
StateTypeUTXOInput StateType = iota
StateTypeCommitment
)
34 changes: 32 additions & 2 deletions pkg/protocol/engine/mempool/state.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,41 @@
package mempool

import iotago "github.com/iotaledger/iota.go/v4"
import (
"github.com/iotaledger/hive.go/lo"
iotago "github.com/iotaledger/iota.go/v4"
)

// A generic interface over a state (like an output or a commitment).
type State interface {
// The identifier of the state.
StateID() StateID

Type() iotago.StateType
// The type of state.
Type() StateType

// Whether the state is read only.
IsReadOnly() bool
}

// A thin wrapper around a resolved commitment.
type CommitmentInputState struct {
Commitment *iotago.Commitment
}

func (s CommitmentInputState) StateID() StateID {
return iotago.IdentifierFromData(lo.PanicOnErr(s.Commitment.MustID().Bytes()))
}

func (s CommitmentInputState) Type() StateType {
return StateTypeCommitment
}

func (s CommitmentInputState) IsReadOnly() bool {
return true
}

func CommitmentInputStateFromCommitment(commitment *iotago.Commitment) CommitmentInputState {
return CommitmentInputState{
Commitment: commitment,
}
}
49 changes: 46 additions & 3 deletions pkg/protocol/engine/mempool/state_reference.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,53 @@
package mempool

import iotago "github.com/iotaledger/iota.go/v4"
import (
"github.com/iotaledger/hive.go/lo"
iotago "github.com/iotaledger/iota.go/v4"
)

// A reference to a state (like an output or a commitment).
type StateReference interface {
// The identifier of the state to which it resolves.
ReferencedStateID() iotago.Identifier

// Type returns the type of Input.
Type() iotago.StateType
// The type of state.
Type() StateType
}

// A thin wrapper around a UTXO input.
type UTXOInputStateRef struct {
Input *iotago.UTXOInput
}

func (r UTXOInputStateRef) ReferencedStateID() iotago.Identifier {
return iotago.IdentifierFromData(lo.PanicOnErr(r.Input.OutputID().Bytes()))
}

func (r UTXOInputStateRef) Type() StateType {
return StateTypeUTXOInput
}

func UTXOInputStateRefFromInput(input *iotago.UTXOInput) UTXOInputStateRef {
return UTXOInputStateRef{
Input: input,
}
}

// A thin wrapper around a Commitment input.
type CommitmentInputStateRef struct {
Input *iotago.CommitmentInput
}

func (r CommitmentInputStateRef) ReferencedStateID() iotago.Identifier {
return iotago.IdentifierFromData(lo.PanicOnErr(r.Input.CommitmentID.Bytes()))
}

func (r CommitmentInputStateRef) Type() StateType {
return StateTypeCommitment
}

func CommitmentInputStateRefFromInput(input *iotago.CommitmentInput) CommitmentInputStateRef {
return CommitmentInputStateRef{
Input: input,
}
}
Loading

0 comments on commit 0ff4e9e

Please sign in to comment.