xrpl

package
v0.5.1 Latest Latest
Warning

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

Go to latest
Published: Jul 17, 2026 License: MIT Imports: 26 Imported by: 0

Documentation

Overview

Package xrpl implements the XRP Ledger custody vault via Peersyst/xrpl-go: a depositor that sends tagged Payments, and a multi-sign withdrawal finalizer over a SignerList-configured vault account. Both take a sign.Signer; neither holds persistence or a mesh.

Index

Constants

View Source
const (
	// LedgerBudget is the number of ledgers of headroom the builder targets when
	// setting LastLedgerSequence (~2min at ~4s/ledger).
	LedgerBudget = uint32(30)
	// MaxLedgerBudget is the upper bound a follower accepts on (LLS - current):
	// slack over LedgerBudget for the ledgers that close between build and
	// validation, still far under the deadline.
	MaxLedgerBudget = uint32(120)
)

LastLedgerSequence budget. XRPL has no per-tx timestamp expiry, so a signed-but-unbroadcast Payment would live as a standing bearer claim. Every canonical withdrawal instead carries a LastLedgerSequence: rippled drops the tx once the network passes that ledger, so each blob dies at the ledger level.

The critical correctness property: the budget is per-attempt and small — derived from ExecutionMargin, NOT the full validity window — so every blob a retry can produce dies before SealedAt + MaxBlockAge + margin = deadline. A full-window budget would let a blob signed near the freshness cutoff outlive clearnet's re-credit and double-spend.

Variables

This section is empty.

Functions

func BuildAmount

BuildAmount converts a WithdrawalOp into an XRPL CurrencyAmount.

func CanonicalJSON

func CanonicalJSON(flatTx transaction.FlatTransaction) ([]byte, error)

CanonicalJSON encodes a FlatTransaction with sorted keys.

func ValidateCanonical

func ValidateCanonical(ctx context.Context, assets blockchain.AssetResolver, flat transaction.FlatTransaction, op *core.WithdrawalOp, withdrawalID [32]byte, vault string, policy llsPolicy) error

ValidateCanonical asserts the canonical flatTx matches the op and that its LastLedgerSequence falls inside the follower's expiry band.

Types

type AssetResolver added in v0.5.0

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

func NewAssetResolver added in v0.5.0

func NewAssetResolver(cfg AssetResolverConfig) *AssetResolver

func (*AssetResolver) AssetDecimals added in v0.5.0

func (r *AssetResolver) AssetDecimals(ctx context.Context, assetAddress string) (uint8, error)

func (*AssetResolver) ValidateAssetAddress added in v0.5.0

func (r *AssetResolver) ValidateAssetAddress(_ context.Context, assetAddress string) error

type AssetResolverConfig added in v0.5.0

type AssetResolverConfig struct {
	IssuedDecimals map[string]uint8
}

type Depositor

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

Depositor sends a Payment from the depositor's account (the key the sign.Signer holds) to the vault, crediting a clearnet account via a `ynet-account` memo (a 20-byte account followed by a 32-byte ADR-015 reference). It implements core.VaultDepositor. Native XRP and issued currencies ("CUR.rIssuer") are both supported.

func NewDepositor

func NewDepositor(rpcURL, vaultAddress string, signer sign.Signer, assets blockchain.AssetResolver) (*Depositor, error)

NewDepositor builds the XRPL depositor against the rippled JSON-RPC at rpcURL.

func (*Depositor) DepositorAddress

func (d *Depositor) DepositorAddress() string

DepositorAddress returns the depositor's classic r-address.

func (*Depositor) SubmitDeposit

func (d *Depositor) SubmitDeposit(ctx context.Context, assetAddress string, amount decimal.Decimal, dest core.DepositDestination) (string, error)

SubmitDeposit sends amount of assetAddress to the vault, crediting dest.Account via a `ynet-account` memo carrying the 20-byte account and the 32-byte ADR-015 dest.Ref. assetAddress is "" for native or "CUR.rIssuer" for an issued currency.

func (*Depositor) VerifyDeposit

func (d *Depositor) VerifyDeposit(_ context.Context, txID string, _ uint64) (core.DepositStatus, error)

VerifyDeposit reports the on-chain status of the deposit txID. XRPL finality is binary — a validated transaction cannot be reorged — so minConf is not a depth here: a validated tx is DepositConfirmed, one found but not yet validated is DepositPending, and an unknown hash (never submitted, or dropped before validation) is DepositAbsent.

type Identity

type Identity struct {
	ClassicAddress   string
	SigningPubKeyHex string
}

Identity is a signer's XRPL classic address + signing pubkey hex.

func DeriveIdentity

func DeriveIdentity(s sign.Signer) (Identity, error)

DeriveIdentity maps a sign.Signer's public key to its XRPL identity.

type LedgerState added in v0.4.0

type LedgerState struct {
	ValidatedIndex uint32
	CloseUnix      int64
}

LedgerState is a snapshot of the network's current validated ledger: its index and close time (as a unix timestamp). Used to set and to bound a withdrawal's LastLedgerSequence against its deadline.

type LedgerStateResolver added in v0.4.0

type LedgerStateResolver func(ctx context.Context) (LedgerState, error)

LedgerStateResolver reads the current validated LedgerState. Injectable so followers/tests can supply a deterministic snapshot instead of a live RPC.

type LedgerTicketProvider

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

LedgerTicketProvider is a TicketProvider that hands out Tickets already provisioned on the vault account, read live from the ledger via account_objects. It does not create Tickets (that needs signing authority over the vault, which the caller orchestrates); it surfaces the ones that exist.

TicketFor returns the lowest available TicketSequence and is stateless: it does not reserve the Ticket it returns, so two concurrent withdrawals can be handed the same one (the second submit then fails tefNO_TICKET). Callers that run withdrawals concurrently must layer their own reservation/pool on top — this is the simple single-flight building block.

func NewLedgerTicketProvider

func NewLedgerTicketProvider(rpcURL, vaultAddress string) (*LedgerTicketProvider, error)

NewLedgerTicketProvider builds a provider reading Tickets owned by vaultAddress over the JSON-RPC at rpcURL.

func (*LedgerTicketProvider) TicketFor

func (p *LedgerTicketProvider) TicketFor(_ context.Context, _ [32]byte) (uint32, error)

TicketFor returns the lowest TicketSequence currently owned by the vault. The withdrawalID is ignored — any of the account's Tickets authorizes any withdrawal. Errors if the account owns no Tickets.

type RotationFinalizer

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

RotationFinalizer rotates the vault account's SignerList via a multi-signed SignerListSet — the rotation analogue of WithdrawalFinalizer. It owns the node's signer; the quorum's blobs are merged off-mesh by the caller. It implements core.SignerRotationFinalizer.

Replay defense is the vault account's own Sequence (autofilled into the SignerListSet), so there is no separate nonce: a given Sequence applies once.

func NewRotationFinalizer

func NewRotationFinalizer(rpcURL, vaultAddress string, threshold int, signer sign.Signer) (*RotationFinalizer, error)

NewRotationFinalizer builds the XRPL rotation finalizer. threshold is the current SignerQuorum (used to size the multi-sign fee and trim the quorum); signer is one of the current SignerList members.

func (*RotationFinalizer) LiveQuorum added in v0.2.0

func (f *RotationFinalizer) LiveQuorum(_ context.Context) (int, error)

LiveQuorum returns the vault's current on-chain SignerQuorum. Callers wire it as the ThresholdResolver (and reuse it for the ceremony collect count) so a quorum-raising rotation sizes the fee and quorum against live state rather than the boot-time threshold.

func (*RotationFinalizer) Pack

func (f *RotationFinalizer) Pack(ctx context.Context, _ [32]byte, newSigners []string, newThreshold int) ([]byte, error)

Pack builds the autofilled multi-sign SignerListSet installing newSigners / newThreshold (each member weight 1), returning its sorted-key JSON. opID is ignored: XRPL binds rotation replay to the account Sequence (autofilled here), so the operation identity is not embedded in the payload.

func (*RotationFinalizer) SetLedgerStateResolver added in v0.4.0

func (f *RotationFinalizer) SetLedgerStateResolver(fn LedgerStateResolver)

SetLedgerStateResolver overrides the current-ledger resolver used to set and bound LastLedgerSequence. Optional; unset uses a live-RPC resolver.

func (*RotationFinalizer) SetStandaloneLedgerMode added in v0.4.0

func (f *RotationFinalizer) SetStandaloneLedgerMode(v bool)

SetStandaloneLedgerMode toggles standalone-rippled behavior: LastLedgerSequence is omitted on build and required-absent on validate. TEST-ONLY.

func (*RotationFinalizer) SetThresholdResolver added in v0.2.0

func (f *RotationFinalizer) SetThresholdResolver(fn func(context.Context) (int, error))

SetThresholdResolver installs a hook that resolves the live SignerQuorum used to size the fee autofill. Optional; unset uses the static construction-time threshold.

func (*RotationFinalizer) Sign

func (f *RotationFinalizer) Sign(ctx context.Context, packed []byte) ([]byte, error)

Sign multi-signs the packed SignerListSet and returns this node's blob.

func (*RotationFinalizer) Submit

func (f *RotationFinalizer) Submit(_ context.Context, _ []byte, signatures [][]byte) (string, error)

Submit combines the collected multi-sign blobs (trimmed to the current quorum) and broadcasts the SignerListSet, returning the txID.

func (*RotationFinalizer) Validate

func (f *RotationFinalizer) Validate(ctx context.Context, _ [32]byte, packed []byte, newSigners []string, newThreshold int) error

Validate asserts the packed SignerListSet rotates to exactly the requested set and that its LastLedgerSequence is inside the follower's ledger band.

func (*RotationFinalizer) VerifyRotation

func (f *RotationFinalizer) VerifyRotation(_ context.Context, newSigners []string, newThreshold int) (string, bool, error)

VerifyRotation reads the vault's on-chain SignerList and reports whether it now holds exactly newSigners with SignerQuorum == newThreshold. Binary: no txID is recoverable from the SignerList object, so an empty txID is returned with done=true.

type TicketProvider

type TicketProvider interface {
	TicketFor(ctx context.Context, withdrawalID [32]byte) (uint32, error)
}

TicketProvider supplies the Ticket sequence that authorizes a withdrawal. Custody backs this with its ticket pool/store; tests and simpler clients back it with a fixed or create-then-return ticket.

type WithdrawalFinalizer

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

WithdrawalFinalizer is the XRPL multi-sign vault withdrawal path. It owns the node's signer and a TicketProvider; the quorum's blobs are merged off-mesh by the caller. It implements core.VaultWithdrawalFinalizer.

func NewWithdrawalFinalizer

func NewWithdrawalFinalizer(rpcURL, vaultAddress string, threshold int, signer sign.Signer, tickets TicketProvider, assets blockchain.AssetResolver) (*WithdrawalFinalizer, error)

NewWithdrawalFinalizer builds the XRPL vault finalizer. threshold is the SignerQuorum; tickets authorizes each withdrawal's TicketSequence.

func (*WithdrawalFinalizer) LiveQuorum added in v0.2.0

func (f *WithdrawalFinalizer) LiveQuorum(_ context.Context) (int, error)

LiveQuorum returns the vault's current on-chain SignerQuorum. Callers wire it as the ThresholdResolver (and reuse it for the ceremony collect count) so a quorum-raising rotation sizes the fee and quorum against live state rather than the boot-time threshold.

func (*WithdrawalFinalizer) Pack

func (f *WithdrawalFinalizer) Pack(ctx context.Context, op *core.WithdrawalOp, withdrawalID [32]byte, deadline int64) ([]byte, error)

Pack binds a Ticket and builds the autofilled multi-sign Payment, returning its sorted-key JSON. It sets LastLedgerSequence to current + a per-attempt budget clamped so the tx's estimated close is at or before the deadline ; if too little budget remains it fails and the withdrawal parks.

func (*WithdrawalFinalizer) SetLedgerStateResolver added in v0.4.0

func (f *WithdrawalFinalizer) SetLedgerStateResolver(fn LedgerStateResolver)

SetLedgerStateResolver overrides the current-ledger resolver used to set and bound LastLedgerSequence. Optional; unset uses a live-RPC resolver.

func (*WithdrawalFinalizer) SetStandaloneLedgerMode added in v0.4.0

func (f *WithdrawalFinalizer) SetStandaloneLedgerMode(v bool)

SetStandaloneLedgerMode toggles standalone-rippled behavior: LastLedgerSequence is omitted on build and required-absent on validate. TEST-ONLY — enabling it in production removes XRPL withdrawal expiry.

func (*WithdrawalFinalizer) SetThresholdResolver added in v0.2.0

func (f *WithdrawalFinalizer) SetThresholdResolver(fn func(context.Context) (int, error))

SetThresholdResolver installs a hook that resolves the live SignerQuorum used to size the fee autofill (see resolveThreshold). Optional; callers that leave it unset get the static threshold passed at construction.

func (*WithdrawalFinalizer) Sign

func (f *WithdrawalFinalizer) Sign(ctx context.Context, packed []byte) ([]byte, error)

Sign multi-signs the packed Payment and returns this node's blob.

func (*WithdrawalFinalizer) Submit

func (f *WithdrawalFinalizer) Submit(_ context.Context, _ []byte, signatures [][]byte) (string, error)

Submit combines the collected multi-sign blobs (trimmed to the quorum) and broadcasts the result, returning the txID.

func (*WithdrawalFinalizer) Validate

func (f *WithdrawalFinalizer) Validate(ctx context.Context, packed []byte, op *core.WithdrawalOp, withdrawalID [32]byte, deadline int64) error

Validate re-derives the trust-bound shape from the op and asserts the packed flatTx matches, including that LastLedgerSequence is inside this follower's deadline-bound expiry band.

func (*WithdrawalFinalizer) VerifyExecution

func (f *WithdrawalFinalizer) VerifyExecution(ctx context.Context, withdrawalID [32]byte) (string, bool, error)

VerifyExecution scans the vault's recent account_tx for a Payment whose InvoiceID equals the withdrawalID, returning its txID + true.

Jump to

Keyboard shortcuts

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