atomic

package
v0.14.2-verify-interface2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 28, 2025 License: GPL-3.0, LGPL-3.0 Imports: 36 Imported by: 0

Documentation

Index

Constants

View Source
const CodecVersion = uint16(0)
View Source
const (
	X2CRateUint64 uint64 = 1_000_000_000
)

Variables

View Source
var (
	ErrExportNonAVAXInputBanff  = errors.New("export input cannot contain non-AVAX in Banff")
	ErrExportNonAVAXOutputBanff = errors.New("export output cannot contain non-AVAX in Banff")
	ErrNoExportOutputs          = errors.New("tx has no export outputs")
)
View Source
var (
	ErrImportNonAVAXInputBanff  = errors.New("import input cannot contain non-AVAX in Banff")
	ErrImportNonAVAXOutputBanff = errors.New("import output cannot contain non-AVAX in Banff")
	ErrNoImportInputs           = errors.New("tx has no imported inputs")
	ErrConflictingAtomicInputs  = errors.New("invalid block due to conflicting atomic inputs")
	ErrWrongChainID             = errors.New("tx has wrong chain ID")
	ErrNoEVMOutputs             = errors.New("tx has no EVM outputs")
	ErrInputsNotSortedUnique    = errors.New("inputs not sorted and unique")
	ErrOutputsNotSortedUnique   = errors.New("outputs not sorted and unique")
	ErrOutputsNotSorted         = errors.New("tx outputs not sorted")
	ErrAssetIDMismatch          = errors.New("asset IDs in the input don't match the utxo")
)
View Source
var (
	ErrConflictingAtomicTx     = errors.New("conflicting atomic tx present")
	ErrInsufficientAtomicTxFee = errors.New("atomic tx fee too low for atomic mempool")
	ErrTooManyAtomicTx         = errors.New("too many atomic tx")
)
View Source
var (
	ErrWrongNetworkID = errors.New("tx was issued with a different network ID")
	ErrNilTx          = errors.New("tx is nil")

	ErrNoValueInput = errors.New("input has no value")
)
View Source
var (
	TxBytesGas   uint64 = 1
	EVMOutputGas uint64 = (common.AddressLength + wrappers.LongLen + hashing.HashLen) * TxBytesGas
	EVMInputGas  uint64 = (common.AddressLength+wrappers.LongLen+hashing.HashLen+wrappers.LongLen)*TxBytesGas + secp256k1fx.CostPerSignature
	// X2CRate is the conversion rate between the smallest denomination on the X-Chain
	// 1 nAVAX and the smallest denomination on the C-Chain 1 wei. Where 1 nAVAX = 1 gWei.
	// This is only required for AVAX because the denomination of 1 AVAX is 9 decimal
	// places on the X and P chains, but is 18 decimal places within the EVM.
	X2CRate = uint256.NewInt(X2CRateUint64)
)

Constants for calculating the gas consumed by atomic transactions

View Source
var (
	// Codec does serialization and deserialization
	Codec codec.Manager
)
View Source
var TestBlockchainID = ids.GenerateTestID()
View Source
var TestTxCodec codec.Manager

Functions

func CalculateDynamicFee

func CalculateDynamicFee(cost uint64, baseFee *big.Int) (uint64, error)

calculates the amount of AVAX that must be burned by an atomic transaction that consumes [cost] at [baseFee].

func SortEVMInputsAndSigners

func SortEVMInputsAndSigners(inputs []EVMInput, signers [][]*secp256k1.PrivateKey)

SortEVMInputsAndSigners sorts the list of EVMInputs based on the addresses and assetIDs

Types

type AtomicBlockContext

type AtomicBlockContext interface {
	AtomicTxs() []*Tx
	snowman.Block
}

type Backend

type Backend struct {
	Ctx          *snow.Context
	Fx           fx.Fx
	Rules        params.Rules
	Bootstrapped bool
	BlockFetcher BlockFetcher
	SecpCache    *secp256k1.RecoverCache
}

type BlockFetcher

type BlockFetcher interface {
	LastAcceptedBlockInternal() snowman.Block
	GetBlockInternal(context.Context, ids.ID) (snowman.Block, error)
}

type EVMInput

type EVMInput struct {
	Address common.Address `serialize:"true" json:"address"`
	Amount  uint64         `serialize:"true" json:"amount"`
	AssetID ids.ID         `serialize:"true" json:"assetID"`
	Nonce   uint64         `serialize:"true" json:"nonce"`
}

EVMInput defines an input created from the EVM state to fund export transactions

func GetSpendableAVAXWithFee

func GetSpendableAVAXWithFee(
	ctx *snow.Context,
	state StateDB,
	keys []*secp256k1.PrivateKey,
	amount uint64,
	cost uint64,
	baseFee *big.Int,
) ([]EVMInput, [][]*secp256k1.PrivateKey, error)

GetSpendableAVAXWithFee returns a list of EVMInputs and keys (in corresponding order) to total [amount] + [fee] of [AVAX] owned by [keys]. This function accounts for the added cost of the additional inputs needed to create the transaction and makes sure to skip any keys with a balance that is insufficient to cover the additional fee. Note: we return [][]*secp256k1.PrivateKey even though each input corresponds to a single key, so that the signers can be passed in to [tx.Sign] which supports multiple keys on a single input.

func GetSpendableFunds

func GetSpendableFunds(
	ctx *snow.Context,
	state StateDB,
	keys []*secp256k1.PrivateKey,
	assetID ids.ID,
	amount uint64,
) ([]EVMInput, [][]*secp256k1.PrivateKey, error)

GetSpendableFunds returns a list of EVMInputs and keys (in corresponding order) to total [amount] of [assetID] owned by [keys]. Note: we return [][]*secp256k1.PrivateKey even though each input corresponds to a single key, so that the signers can be passed in to [tx.Sign] which supports multiple keys on a single input.

func (EVMInput) Compare

func (i EVMInput) Compare(other EVMInput) int

func (*EVMInput) Verify

func (in *EVMInput) Verify() error

Verify ...

type EVMOutput

type EVMOutput struct {
	Address common.Address `serialize:"true" json:"address"`
	Amount  uint64         `serialize:"true" json:"amount"`
	AssetID ids.ID         `serialize:"true" json:"assetID"`
}

EVMOutput defines an output that is added to the EVM state created by import transactions

func (EVMOutput) Compare

func (o EVMOutput) Compare(other EVMOutput) int

func (*EVMOutput) Verify

func (out *EVMOutput) Verify() error

Verify ...

type GossipAtomicTx

type GossipAtomicTx struct {
	Tx *Tx
}

func (*GossipAtomicTx) GossipID

func (tx *GossipAtomicTx) GossipID() ids.ID

type GossipAtomicTxMarshaller

type GossipAtomicTxMarshaller struct{}

func (GossipAtomicTxMarshaller) MarshalGossip

func (g GossipAtomicTxMarshaller) MarshalGossip(tx *GossipAtomicTx) ([]byte, error)

func (GossipAtomicTxMarshaller) UnmarshalGossip

func (g GossipAtomicTxMarshaller) UnmarshalGossip(bytes []byte) (*GossipAtomicTx, error)

type Mempool

type Mempool struct {

	// Pending is a channel of length one, which the mempool ensures has an item on
	// it as long as there is an unissued transaction remaining in [txs]
	Pending chan struct{}
	// contains filtered or unexported fields
}

Mempool is a simple mempool for atomic transactions

func NewMempool

func NewMempool(ctx *snow.Context, registerer prometheus.Registerer, maxSize int, verify func(tx *Tx) error) (*Mempool, error)

NewMempool returns a Mempool with [maxSize]

func (*Mempool) Add

func (m *Mempool) Add(tx *GossipAtomicTx) error

func (*Mempool) AddLocalTx

func (m *Mempool) AddLocalTx(tx *Tx) error

func (*Mempool) AddRemoteTx

func (m *Mempool) AddRemoteTx(tx *Tx) error

AddRemoteTx attempts to add [tx] to the mempool and returns an error if it could not be added to the mempool.

func (*Mempool) CancelCurrentTx

func (m *Mempool) CancelCurrentTx(txID ids.ID)

CancelCurrentTx marks the attempt to issue [txID] as being aborted. This should be called after NextTx returns [txID] and the transaction [txID] cannot be included in the block, but should not be discarded. For example, CancelCurrentTx should be called if including the transaction will put the block above the atomic tx gas limit.

func (*Mempool) CancelCurrentTxs

func (m *Mempool) CancelCurrentTxs()

[CancelCurrentTxs] marks the attempt to issue [currentTxs] as being aborted. If this is called after a buildBlock error caused by the atomic transaction, then DiscardCurrentTx should have been called such that this call will have no effect and should not re-issue the invalid tx.

func (*Mempool) DiscardCurrentTx

func (m *Mempool) DiscardCurrentTx(txID ids.ID)

DiscardCurrentTx marks a [tx] in the [currentTxs] map as invalid and aborts the attempt to issue it since it failed verification.

func (*Mempool) DiscardCurrentTxs

func (m *Mempool) DiscardCurrentTxs()

DiscardCurrentTxs marks all txs in [currentTxs] as discarded.

func (*Mempool) ForceAddTx

func (m *Mempool) ForceAddTx(tx *Tx) error

ForceAddTx forcibly adds a *Tx to the mempool and bypasses all verification.

func (*Mempool) GetFilter

func (m *Mempool) GetFilter() ([]byte, []byte)

func (*Mempool) GetPendingTx

func (m *Mempool) GetPendingTx(txID ids.ID) (*Tx, bool)

GetPendingTx returns the transaction [txID] and true if it is currently in the [txHeap] waiting to be issued into a block. Returns nil, false otherwise.

func (*Mempool) GetTx

func (m *Mempool) GetTx(txID ids.ID) (*Tx, bool, bool)

GetTx returns the transaction [txID] if it was issued by this node and returns whether it was dropped and whether it exists.

func (*Mempool) Has

func (m *Mempool) Has(txID ids.ID) bool

Has returns true if the mempool contains [txID] or it was issued.

func (*Mempool) IssueCurrentTxs

func (m *Mempool) IssueCurrentTxs()

IssueCurrentTx marks [currentTx] as issued if there is one

func (*Mempool) Iterate

func (m *Mempool) Iterate(f func(tx *GossipAtomicTx) bool)

func (*Mempool) Len

func (m *Mempool) Len() int

Len returns the number of transactions in the mempool

func (*Mempool) NextTx

func (m *Mempool) NextTx() (*Tx, bool)

NextTx returns a transaction to be issued from the mempool.

func (*Mempool) RemoveTx

func (m *Mempool) RemoveTx(tx *Tx)

RemoveTx removes [txID] from the mempool completely. Evicts [tx] from the discarded cache if present.

type Metadata

type Metadata struct {
	// contains filtered or unexported fields
}

func (*Metadata) Bytes

func (md *Metadata) Bytes() []byte

UnsignedBytes returns the unsigned binary representation of this data

func (*Metadata) ID

func (md *Metadata) ID() ids.ID

ID returns the unique ID of this data

func (*Metadata) Initialize

func (md *Metadata) Initialize(unsignedBytes, bytes []byte)

Initialize set the bytes and ID

func (*Metadata) SignedBytes

func (md *Metadata) SignedBytes() []byte

Bytes returns the binary representation of this data

type StateDB

type StateDB interface {
	AddBalance(common.Address, *uint256.Int)
	AddBalanceMultiCoin(common.Address, common.Hash, *big.Int)

	SubBalance(common.Address, *uint256.Int)
	SubBalanceMultiCoin(common.Address, common.Hash, *big.Int)

	GetBalance(common.Address) *uint256.Int
	GetBalanceMultiCoin(common.Address, common.Hash) *big.Int

	GetNonce(common.Address) uint64
	SetNonce(common.Address, uint64)
}

type Status

type Status uint32

Status ...

const (
	Unknown Status = iota
	Dropped
	Processing
	Accepted
)

List of possible status values Unknown Zero value, means the status is not known Dropped means the transaction was in the mempool, but was dropped because it failed verification Processing means the transaction is in the mempool Accepted means the transaction was accepted

func (Status) MarshalJSON

func (s Status) MarshalJSON() ([]byte, error)

MarshalJSON ...

func (Status) String

func (s Status) String() string

func (*Status) UnmarshalJSON

func (s *Status) UnmarshalJSON(b []byte) error

UnmarshalJSON ...

func (Status) Valid

func (s Status) Valid() error

Valid returns nil if the status is a valid status.

type TestUnsignedTx

type TestUnsignedTx struct {
	GasUsedV                    uint64                    `serialize:"true"`
	AcceptRequestsBlockchainIDV ids.ID                    `serialize:"true"`
	AcceptRequestsV             *avalancheatomic.Requests `serialize:"true"`
	VerifyV                     error
	IDV                         ids.ID `serialize:"true" json:"id"`
	BurnedV                     uint64 `serialize:"true"`
	UnsignedBytesV              []byte
	SignedBytesV                []byte
	InputUTXOsV                 set.Set[ids.ID]
	SemanticVerifyV             error
	EVMStateTransferV           error
}

func (*TestUnsignedTx) AtomicOps

func (t *TestUnsignedTx) AtomicOps() (ids.ID, *avalancheatomic.Requests, error)

AtomicOps implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) Burned

func (t *TestUnsignedTx) Burned(assetID ids.ID) (uint64, error)

Burned implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) Bytes

func (t *TestUnsignedTx) Bytes() []byte

Bytes implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) EVMStateTransfer

func (t *TestUnsignedTx) EVMStateTransfer(ctx *snow.Context, state StateDB) error

EVMStateTransfer implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) GasUsed

func (t *TestUnsignedTx) GasUsed(fixedFee bool) (uint64, error)

GasUsed implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) ID

func (t *TestUnsignedTx) ID() ids.ID

ID implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) Initialize

func (t *TestUnsignedTx) Initialize(unsignedBytes, signedBytes []byte)

Initialize implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) InputUTXOs

func (t *TestUnsignedTx) InputUTXOs() set.Set[ids.ID]

InputUTXOs implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) SemanticVerify

func (t *TestUnsignedTx) SemanticVerify(backend *Backend, stx *Tx, parent AtomicBlockContext, baseFee *big.Int) error

SemanticVerify implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) SignedBytes

func (t *TestUnsignedTx) SignedBytes() []byte

SignedBytes implements the UnsignedAtomicTx interface

func (*TestUnsignedTx) Verify

func (t *TestUnsignedTx) Verify(ctx *snow.Context, rules params.Rules) error

Verify implements the UnsignedAtomicTx interface

type Tx

type Tx struct {
	// The body of this transaction
	UnsignedAtomicTx `serialize:"true" json:"unsignedTx"`

	// The credentials of this transaction
	Creds []verify.Verifiable `serialize:"true" json:"credentials"`
}

Tx is a signed transaction

func ExtractAtomicTx

func ExtractAtomicTx(atomicTxBytes []byte, codec codec.Manager) (*Tx, error)

ExtractAtomicTx extracts a singular atomic transaction from [atomicTxBytes] and returns a slice of atomic transactions for compatibility with the type returned post ApricotPhase5. Note: this function assumes [atomicTxBytes] is non-empty.

func ExtractAtomicTxs

func ExtractAtomicTxs(atomicTxBytes []byte, batch bool, codec codec.Manager) ([]*Tx, error)

extractAtomicTxs returns the atomic transactions in [atomicTxBytes] if they exist. if [batch] is true, it attempts to unmarshal [atomicTxBytes] as a slice of transactions (post-ApricotPhase5), and if it is false, then it unmarshals it as a single atomic transaction.

func ExtractAtomicTxsBatch

func ExtractAtomicTxsBatch(atomicTxBytes []byte, codec codec.Manager) ([]*Tx, error)

ExtractAtomicTxsBatch extracts a slice of atomic transactions from [atomicTxBytes]. Note: this function assumes [atomicTxBytes] is non-empty.

func GenerateTestExportTx

func GenerateTestExportTx() *Tx

func GenerateTestImportTx

func GenerateTestImportTx() *Tx

func GenerateTestImportTxWithGas

func GenerateTestImportTxWithGas(gasUsed uint64, burned uint64) *Tx

func NewExportTx

func NewExportTx(
	ctx *snow.Context,
	rules params.Rules,
	state StateDB,
	assetID ids.ID,
	amount uint64,
	chainID ids.ID,
	to ids.ShortID,
	baseFee *big.Int,
	keys []*secp256k1.PrivateKey,
) (*Tx, error)

NewExportTx returns a new ExportTx

func NewImportTx

func NewImportTx(
	ctx *snow.Context,
	rules params.Rules,
	time uint64,
	chainID ids.ID,
	to common.Address,
	baseFee *big.Int,
	kc *secp256k1fx.Keychain,
	atomicUTXOs []*avax.UTXO,
) (*Tx, error)

NewImportTx returns a new ImportTx

func NewTestTx

func NewTestTx() *Tx

func NewTestTxs

func NewTestTxs(numTxs int) []*Tx

func (*Tx) BlockFeeContribution

func (tx *Tx) BlockFeeContribution(fixedFee bool, avaxAssetID ids.ID, baseFee *big.Int) (*big.Int, *big.Int, error)

BlockFeeContribution calculates how much AVAX towards the block fee contribution was paid for via this transaction denominated in [avaxAssetID] with [baseFee] used to calculate the cost of this transaction. This function also returns the [gasUsed] by the transaction for inclusion in the [baseFee] algorithm.

func (*Tx) Compare

func (tx *Tx) Compare(other *Tx) int

func (*Tx) Sign

func (tx *Tx) Sign(c codec.Manager, signers [][]*secp256k1.PrivateKey) error

Sign this transaction with the provided signers

type UnsignedAtomicTx

type UnsignedAtomicTx interface {
	UnsignedTx

	// InputUTXOs returns the UTXOs this tx consumes
	InputUTXOs() set.Set[ids.ID]
	// Verify attempts to verify that the transaction is well formed
	Verify(ctx *snow.Context, rules params.Rules) error
	// Attempts to verify this transaction with the provided state.
	// SemanticVerify this transaction is valid.
	SemanticVerify(backend *Backend, stx *Tx, parent AtomicBlockContext, baseFee *big.Int) error
	// AtomicOps returns the blockchainID and set of atomic requests that
	// must be applied to shared memory for this transaction to be accepted.
	// The set of atomic requests must be returned in a consistent order.
	AtomicOps() (ids.ID, *atomic.Requests, error)

	EVMStateTransfer(ctx *snow.Context, state StateDB) error
}

UnsignedAtomicTx is an unsigned operation that can be atomically accepted

type UnsignedExportTx

type UnsignedExportTx struct {
	Metadata
	// ID of the network on which this tx was issued
	NetworkID uint32 `serialize:"true" json:"networkID"`
	// ID of this blockchain.
	BlockchainID ids.ID `serialize:"true" json:"blockchainID"`
	// Which chain to send the funds to
	DestinationChain ids.ID `serialize:"true" json:"destinationChain"`
	// Inputs
	Ins []EVMInput `serialize:"true" json:"inputs"`
	// Outputs that are exported to the chain
	ExportedOutputs []*avax.TransferableOutput `serialize:"true" json:"exportedOutputs"`
}

UnsignedExportTx is an unsigned ExportTx

func (*UnsignedExportTx) AtomicOps

func (utx *UnsignedExportTx) AtomicOps() (ids.ID, *atomic.Requests, error)

AtomicOps returns the atomic operations for this transaction.

func (*UnsignedExportTx) Burned

func (utx *UnsignedExportTx) Burned(assetID ids.ID) (uint64, error)

Amount of [assetID] burned by this transaction

func (*UnsignedExportTx) EVMStateTransfer

func (utx *UnsignedExportTx) EVMStateTransfer(ctx *snow.Context, state StateDB) error

EVMStateTransfer executes the state update from the atomic export transaction

func (*UnsignedExportTx) GasUsed

func (utx *UnsignedExportTx) GasUsed(fixedFee bool) (uint64, error)

func (*UnsignedExportTx) InputUTXOs

func (utx *UnsignedExportTx) InputUTXOs() set.Set[ids.ID]

InputUTXOs returns a set of all the hash(address:nonce) exporting funds.

func (*UnsignedExportTx) SemanticVerify

func (utx *UnsignedExportTx) SemanticVerify(
	backend *Backend,
	stx *Tx,
	parent AtomicBlockContext,
	baseFee *big.Int,
) error

SemanticVerify this transaction is valid.

func (*UnsignedExportTx) Verify

func (utx *UnsignedExportTx) Verify(
	ctx *snow.Context,
	rules params.Rules,
) error

Verify this transaction is well-formed

type UnsignedImportTx

type UnsignedImportTx struct {
	Metadata
	// ID of the network on which this tx was issued
	NetworkID uint32 `serialize:"true" json:"networkID"`
	// ID of this blockchain.
	BlockchainID ids.ID `serialize:"true" json:"blockchainID"`
	// Which chain to consume the funds from
	SourceChain ids.ID `serialize:"true" json:"sourceChain"`
	// Inputs that consume UTXOs produced on the chain
	ImportedInputs []*avax.TransferableInput `serialize:"true" json:"importedInputs"`
	// Outputs
	Outs []EVMOutput `serialize:"true" json:"outputs"`
}

UnsignedImportTx is an unsigned ImportTx

func (*UnsignedImportTx) AtomicOps

func (utx *UnsignedImportTx) AtomicOps() (ids.ID, *atomic.Requests, error)

AtomicOps returns imported inputs spent on this transaction We spend imported UTXOs here rather than in semanticVerify because we don't want to remove an imported UTXO in semanticVerify only to have the transaction not be Accepted. This would be inconsistent. Recall that imported UTXOs are not kept in a versionDB.

func (*UnsignedImportTx) Burned

func (utx *UnsignedImportTx) Burned(assetID ids.ID) (uint64, error)

Amount of [assetID] burned by this transaction

func (*UnsignedImportTx) EVMStateTransfer

func (utx *UnsignedImportTx) EVMStateTransfer(ctx *snow.Context, state StateDB) error

EVMStateTransfer performs the state transfer to increase the balances of accounts accordingly with the imported EVMOutputs

func (*UnsignedImportTx) GasUsed

func (utx *UnsignedImportTx) GasUsed(fixedFee bool) (uint64, error)

func (*UnsignedImportTx) InputUTXOs

func (utx *UnsignedImportTx) InputUTXOs() set.Set[ids.ID]

InputUTXOs returns the UTXOIDs of the imported funds

func (*UnsignedImportTx) SemanticVerify

func (utx *UnsignedImportTx) SemanticVerify(
	backend *Backend,
	stx *Tx,
	parent AtomicBlockContext,
	baseFee *big.Int,
) error

SemanticVerify this transaction is valid.

func (*UnsignedImportTx) Verify

func (utx *UnsignedImportTx) Verify(
	ctx *snow.Context,
	rules params.Rules,
) error

Verify this transaction is well-formed

type UnsignedTx

type UnsignedTx interface {
	Initialize(unsignedBytes, signedBytes []byte)
	ID() ids.ID
	GasUsed(fixedFee bool) (uint64, error)
	Burned(assetID ids.ID) (uint64, error)
	Bytes() []byte
	SignedBytes() []byte
}

UnsignedTx is an unsigned transaction

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL