tx

package
v0.1.114 Latest Latest
Warning

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

Go to latest
Published: Jul 3, 2026 License: AGPL-3.0 Imports: 15 Imported by: 0

Documentation

Overview

Package tx implements the shared Heimdall transaction builder used by `polycli heimdall mktx`, `send`, and `estimate`. The builder assembles a cosmos.tx.v1beta1.TxRaw from one or more messages, fetches the signer's account number + sequence (unless overridden), signs with a secp256k1-eth key, and — via the broadcast helper — submits it through the REST gateway.

The signing scheme is the Heimdall v2 `PubKeySecp256k1eth` variant: curve secp256k1, but the digest is keccak256 (not sha256) and the 65-byte (r||s||v) output from eth signing is truncated to 64 bytes (r||s) before landing in TxRaw.signatures. This matches heimdall-v2 /crypto/keys/secp256k1.PrivKey.Sign.

Index

Constants

This section is empty.

Variables

View Source
var L1MirroringMsgTypes = map[string]struct{}{
	"MsgTopupTx":            {},
	"MsgCheckpointAck":      {},
	"MsgCpAck":              {},
	"MsgCheckpointNoAck":    {},
	"MsgCpNoAck":            {},
	"MsgEventRecordRequest": {},
	"MsgEventRecord":        {},
	"MsgClerkRecord":        {},
	"MsgValidatorJoin":      {},
	"MsgStakeJoin":          {},
	"MsgValidatorUpdate":    {},
	"MsgStakeUpdate":        {},
	"MsgSignerUpdate":       {},
	"MsgValidatorExit":      {},
	"MsgStakeExit":          {},
}

L1MirroringMsgTypes is the set of Msg types that are produced by the Heimdall bridge after observing an L1 event. Operators almost never hand-build these, and submitting one manually is either a no-op or a replay that competes with the real bridge path.

Subcommands flagged for these types call RequireForce before building; it returns a user-facing refusal error unless the caller has set --force.

Wording is taken verbatim from HEIMDALLCAST_REQUIREMENTS.md §3.3.

Functions

func EthAddress

func EthAddress(priv *ecdsa.PrivateKey) common.Address

EthAddress derives the 20-byte Ethereum-style address that Heimdall uses for the `proposer` / `from` fields on messages. Matches PubKey.Address() in heimdall-v2's secp256k1 package (keccak256 of the uncompressed pubkey minus the 0x04 prefix, right-most 20 bytes).

func RequireForce

func RequireForce(msgType string, force bool) error

RequireForce returns an error if msgType is an L1-mirroring type and force is false. Returns nil for safe types or when force is true.

The error text matches HEIMDALLCAST_REQUIREMENTS.md §3.3:

"this message is produced by the bridge after observing an L1
 event; you almost certainly do not want to build one by hand.
 Re-run with --force to bypass."

msgType is matched against the short name only (the last segment of the type URL, e.g. "MsgTopupTx" rather than the full URL) to keep call-sites short. Both short and fully-qualified names are accepted.

func WaitForConfirmations

func WaitForConfirmations(ctx context.Context, rpc *client.RPCClient, txHeight uint64, confirmations uint64, pollInterval time.Duration) error

WaitForConfirmations waits until the chain's latest_block_height is at least txHeight + confirmations. When confirmations is zero the function returns immediately.

func WaitForInclusion

func WaitForInclusion(ctx context.Context, rpc *client.RPCClient, txHash string, pollInterval time.Duration) (uint64, []byte, error)

WaitForInclusion polls CometBFT /tx for txHash until the tx is found or ctx is cancelled. pollInterval defaults to 500ms when zero. Returns the height and raw /tx JSON body.

Callers who need `--confirmations N` should call this to get inclusion height, then poll /status until latest_block_height >= height + N.

Types

type Account

type Account struct {
	Address       string
	AccountNumber uint64
	Sequence      uint64
}

Account is the subset of /cosmos/auth/v1beta1/accounts/{addr} that the builder reads. Exposed for tests / advanced callers who want to fetch once and feed into multiple builders.

type AccountFetcher

type AccountFetcher interface {
	FetchAccount(ctx context.Context, addr string) (*Account, error)
}

AccountFetcher is the narrow interface the builder uses to look up signer accounts. The production implementation wraps client.RESTClient; tests inject a fake.

type BackfillSpansMsg

type BackfillSpansMsg struct {
	Proposer        string
	ChainID         string
	LatestSpanID    uint64
	LatestBorSpanID uint64
}

BackfillSpansMsg wraps MsgBackfillSpans.

func (*BackfillSpansMsg) AminoJSON

func (m *BackfillSpansMsg) AminoJSON() (any, error)

func (*BackfillSpansMsg) AminoName

func (m *BackfillSpansMsg) AminoName() string

func (*BackfillSpansMsg) Marshal

func (m *BackfillSpansMsg) Marshal() ([]byte, error)

func (*BackfillSpansMsg) TypeURL

func (m *BackfillSpansMsg) TypeURL() string

type BroadcastMode

type BroadcastMode string

BroadcastMode mirrors cosmos.tx.v1beta1.BroadcastMode. We expose only SYNC (wait for CheckTx) and ASYNC (return immediately) — BLOCK is deprecated in cosmos-sdk and Heimdall has instant finality so SYNC + polling covers the real inclusion flow.

const (
	BroadcastModeSync  BroadcastMode = "BROADCAST_MODE_SYNC"
	BroadcastModeAsync BroadcastMode = "BROADCAST_MODE_ASYNC"
)

type BroadcastResult

type BroadcastResult struct {
	TxHash    string
	Code      int
	Codespace string
	RawLog    string
	Height    uint64
	// Raw is the undecoded JSON body of the /cosmos/tx/v1beta1/txs
	// response. May be nil if the transport short-circuited (--curl).
	Raw []byte
}

BroadcastResult carries the fields polycli's send command surfaces after a broadcast round-trip. Raw holds the undecoded JSON response so --json callers can pass it through verbatim.

func Broadcast

func Broadcast(ctx context.Context, rest *client.RESTClient, txBytes []byte, mode BroadcastMode) (*BroadcastResult, error)

Broadcast submits txBytes via /cosmos/tx/v1beta1/txs and returns the decoded tx response. Callers typically pass the bytes returned by Builder.Sign; this function base64-encodes them before POSTing.

On non-zero CheckTx code the function returns BroadcastResult with code/raw_log populated AND a non-nil error so callers can surface both without double-handling.

type Builder

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

Builder constructs a TxRaw. Call the With* setters, then Sign (which produces the raw bytes) or SignAndEncode (which also base64/hex encodes them). Builders are single-use; reuse after Sign is undefined.

func NewBuilder

func NewBuilder() *Builder

NewBuilder returns a fresh Builder with direct sign mode and a zero-value fee. The caller must populate at least WithChainID and one Msg before Sign.

func (*Builder) AddMsg

func (b *Builder) AddMsg(m Msg) *Builder

AddMsg appends a Msg to the builder's TxBody. Repeatable; order is preserved and determines the order of signer_infos.

func (*Builder) ResolveAccount

func (b *Builder) ResolveAccount(ctx context.Context, fetcher AccountFetcher, addr string) error

ResolveAccount populates the builder's accountNumber and sequence by asking fetcher for the given signer address. Callers that set both values via WithAccountNumber and WithSequence can skip this step.

func (*Builder) Sign

func (b *Builder) Sign(priv *ecdsa.PrivateKey) ([]byte, error)

Sign builds the TxRaw bytes using priv as the single signing key. chainID and accountNumber must be set (via WithChainID and either WithAccountNumber or ResolveAccount). Returns the canonical TxRaw proto-encoded bytes, ready for /cosmos/tx/v1beta1/txs.

func (*Builder) SignAndEncode

func (b *Builder) SignAndEncode(priv *ecdsa.PrivateKey) (raw []byte, b64, hex string, err error)

SignAndEncode signs and returns the TxRaw bytes in both base64 and hex encodings. Callers typically print one or both.

func (*Builder) WithAccountNumber

func (b *Builder) WithAccountNumber(n uint64) *Builder

WithAccountNumber overrides the auto-fetched account number.

func (*Builder) WithChainID

func (b *Builder) WithChainID(id string) *Builder

WithChainID sets the chain id used for SIGN_MODE_DIRECT replay protection.

func (*Builder) WithFee

func (b *Builder) WithFee(coins ...hproto.Coin) *Builder

WithFee sets the fee amount coins. Gas limit is set separately via WithGasLimit.

func (*Builder) WithFeeGranter

func (b *Builder) WithFeeGranter(addr string) *Builder

WithFeeGranter sets the optional fee granter address on Fee.

func (*Builder) WithFeePayer

func (b *Builder) WithFeePayer(addr string) *Builder

WithFeePayer sets the optional fee payer address on Fee.

func (*Builder) WithGasLimit

func (b *Builder) WithGasLimit(g uint64) *Builder

WithGasLimit sets the TxBody gas limit.

func (*Builder) WithMemo

func (b *Builder) WithMemo(memo string) *Builder

WithMemo sets the tx memo. Default empty.

func (*Builder) WithSequence

func (b *Builder) WithSequence(s uint64) *Builder

WithSequence overrides the auto-fetched sequence.

func (*Builder) WithSignMode

func (b *Builder) WithSignMode(m SignMode) *Builder

WithSignMode sets the signing mode (direct or amino-json).

func (*Builder) WithTimeoutHeight

func (b *Builder) WithTimeoutHeight(h uint64) *Builder

WithTimeoutHeight sets the absolute block height after which the tx is invalid. Default 0 (no timeout).

type CheckpointMsg

type CheckpointMsg struct {
	Proposer        string
	StartBlock      uint64
	EndBlock        uint64
	RootHash        []byte
	AccountRootHash []byte
	BorChainID      string
}

CheckpointMsg wraps heimdallv2.checkpoint.MsgCheckpoint for the builder. All fields must be supplied by the caller; the builder performs no semantic validation beyond "proposer non-empty".

func (*CheckpointMsg) AminoJSON

func (m *CheckpointMsg) AminoJSON() (any, error)

AminoJSON implements Msg.

func (*CheckpointMsg) AminoName

func (m *CheckpointMsg) AminoName() string

AminoName implements Msg.

func (*CheckpointMsg) Marshal

func (m *CheckpointMsg) Marshal() ([]byte, error)

Marshal implements Msg.

func (*CheckpointMsg) TypeURL

func (m *CheckpointMsg) TypeURL() string

TypeURL implements Msg.

type ClerkEventRecordMsg

type ClerkEventRecordMsg struct {
	From            string
	TxHash          string
	LogIndex        uint64
	BlockNumber     uint64
	ContractAddress string
	Data            []byte
	ID              uint64
	ChainID         string
}

ClerkEventRecordMsg wraps MsgEventRecord.

func (*ClerkEventRecordMsg) AminoJSON

func (m *ClerkEventRecordMsg) AminoJSON() (any, error)

func (*ClerkEventRecordMsg) AminoName

func (m *ClerkEventRecordMsg) AminoName() string

func (*ClerkEventRecordMsg) Marshal

func (m *ClerkEventRecordMsg) Marshal() ([]byte, error)

func (*ClerkEventRecordMsg) TypeURL

func (m *ClerkEventRecordMsg) TypeURL() string

type CpAckMsg

type CpAckMsg struct {
	From       string
	Number     uint64
	Proposer   string
	StartBlock uint64
	EndBlock   uint64
	RootHash   []byte
}

CpAckMsg wraps MsgCpAck.

func (*CpAckMsg) AminoJSON

func (m *CpAckMsg) AminoJSON() (any, error)

func (*CpAckMsg) AminoName

func (m *CpAckMsg) AminoName() string

func (*CpAckMsg) Marshal

func (m *CpAckMsg) Marshal() ([]byte, error)

func (*CpAckMsg) TypeURL

func (m *CpAckMsg) TypeURL() string

type CpNoAckMsg

type CpNoAckMsg struct {
	From string
}

CpNoAckMsg wraps MsgCpNoAck.

func (*CpNoAckMsg) AminoJSON

func (m *CpNoAckMsg) AminoJSON() (any, error)

func (*CpNoAckMsg) AminoName

func (m *CpNoAckMsg) AminoName() string

func (*CpNoAckMsg) Marshal

func (m *CpNoAckMsg) Marshal() ([]byte, error)

func (*CpNoAckMsg) TypeURL

func (m *CpNoAckMsg) TypeURL() string

type Msg

type Msg interface {
	// TypeURL is the Any.type_url for the message, e.g.
	// "/heimdallv2.topup.MsgWithdrawFeeTx".
	TypeURL() string
	// Marshal returns the proto-serialized message (the payload that
	// goes inside Any.value).
	Marshal() ([]byte, error)
	// AminoName is the amino.name option on the message, used for
	// SIGN_MODE_LEGACY_AMINO_JSON. Return "" if amino-JSON is not
	// supported for this message; the builder will refuse to sign.
	AminoName() string
	// AminoJSON returns the message as a JSON-serializable Go value
	// (typically map[string]any) for the legacy amino-JSON sign doc.
	// Implementations should emit uint64 / int64 fields as decimal
	// strings to match cosmos-sdk behavior.
	AminoJSON() (any, error)
}

Msg is a Heimdall / Cosmos SDK message that can be packed into a google.protobuf.Any and serialized as part of a TxBody.

Implementations are tiny — one per concrete Msg type — and live with the command that builds them (W3/W4 wave). The first implementation, for MsgWithdrawFeeTx, ships with this package to exercise the builder end-to-end.

type ProposeSpanMsg

type ProposeSpanMsg struct {
	SpanID     uint64
	Proposer   string
	StartBlock uint64
	EndBlock   uint64
	ChainID    string
	Seed       []byte
	SeedAuthor string
}

ProposeSpanMsg wraps MsgProposeSpan.

func (*ProposeSpanMsg) AminoJSON

func (m *ProposeSpanMsg) AminoJSON() (any, error)

func (*ProposeSpanMsg) AminoName

func (m *ProposeSpanMsg) AminoName() string

func (*ProposeSpanMsg) Marshal

func (m *ProposeSpanMsg) Marshal() ([]byte, error)

func (*ProposeSpanMsg) TypeURL

func (m *ProposeSpanMsg) TypeURL() string

type RESTAccountFetcher

type RESTAccountFetcher struct {
	Client *client.RESTClient
}

RESTAccountFetcher is the default AccountFetcher. It calls /cosmos/auth/v1beta1/accounts/{addr} and parses the BaseAccount response.

func (*RESTAccountFetcher) FetchAccount

func (f *RESTAccountFetcher) FetchAccount(ctx context.Context, addr string) (*Account, error)

FetchAccount implements AccountFetcher.

type SetProducerDowntimeMsg

type SetProducerDowntimeMsg struct {
	Producer   string
	StartBlock uint64
	EndBlock   uint64
}

SetProducerDowntimeMsg wraps MsgSetProducerDowntime.

func (*SetProducerDowntimeMsg) AminoJSON

func (m *SetProducerDowntimeMsg) AminoJSON() (any, error)

func (*SetProducerDowntimeMsg) AminoName

func (m *SetProducerDowntimeMsg) AminoName() string

func (*SetProducerDowntimeMsg) Marshal

func (m *SetProducerDowntimeMsg) Marshal() ([]byte, error)

func (*SetProducerDowntimeMsg) TypeURL

func (m *SetProducerDowntimeMsg) TypeURL() string

type SignMode

type SignMode int32

SignMode is the signing mode used to compute the signature pre-image.

const (
	// SignModeDirect signs the SIGN_MODE_DIRECT doc (proto-serialized
	// SignDoc). This is the default and matches cosmos-sdk's default.
	SignModeDirect SignMode = SignMode(proto.SignModeDirect)
	// SignModeAminoJSON signs the legacy amino-JSON document. Kept for
	// compatibility with older tooling; not otherwise recommended.
	SignModeAminoJSON SignMode = SignMode(proto.SignModeAminoJSON)
)

func ParseSignMode

func ParseSignMode(name string) (SignMode, error)

ParseSignMode maps the flag-style name ("direct" / "amino-json") to a SignMode. Unknown names return an error so usage mistakes surface at the boundary rather than silently falling back.

func (SignMode) String

func (m SignMode) String() string

String returns the cobra-flag-friendly name of the sign mode.

type SignerUpdateMsg

type SignerUpdateMsg struct {
	From            string
	ValID           uint64
	NewSignerPubKey []byte
	TxHash          []byte
	LogIndex        uint64
	BlockNumber     uint64
	Nonce           uint64
}

SignerUpdateMsg wraps MsgSignerUpdate.

func (*SignerUpdateMsg) AminoJSON

func (m *SignerUpdateMsg) AminoJSON() (any, error)

func (*SignerUpdateMsg) AminoName

func (m *SignerUpdateMsg) AminoName() string

func (*SignerUpdateMsg) Marshal

func (m *SignerUpdateMsg) Marshal() ([]byte, error)

func (*SignerUpdateMsg) TypeURL

func (m *SignerUpdateMsg) TypeURL() string

type SimulateResult

type SimulateResult struct {
	GasUsed   uint64
	GasWanted uint64
	Raw       []byte
}

SimulateResult carries the gas estimate plus the raw response JSON.

func Simulate

func Simulate(ctx context.Context, rest *client.RESTClient, txBytes []byte) (*SimulateResult, error)

Simulate calls /cosmos/tx/v1beta1/simulate with txBytes and returns the simulation result. Used by `estimate` and by `--gas auto`. Callers sign the tx before simulating — simulate still validates signatures, so a throwaway sig produced over the final doc works.

type StakeUpdateMsg

type StakeUpdateMsg struct {
	From        string
	ValID       uint64
	NewAmount   string
	TxHash      []byte
	LogIndex    uint64
	BlockNumber uint64
	Nonce       uint64
}

StakeUpdateMsg wraps MsgStakeUpdate.

func (*StakeUpdateMsg) AminoJSON

func (m *StakeUpdateMsg) AminoJSON() (any, error)

func (*StakeUpdateMsg) AminoName

func (m *StakeUpdateMsg) AminoName() string

func (*StakeUpdateMsg) Marshal

func (m *StakeUpdateMsg) Marshal() ([]byte, error)

func (*StakeUpdateMsg) TypeURL

func (m *StakeUpdateMsg) TypeURL() string

type TopupMsg

type TopupMsg struct {
	Proposer    string
	User        string
	Fee         string
	TxHash      []byte
	LogIndex    uint64
	BlockNumber uint64
}

TopupMsg wraps MsgTopupTx (L1-mirroring; gated by RequireForce).

func (*TopupMsg) AminoJSON

func (m *TopupMsg) AminoJSON() (any, error)

func (*TopupMsg) AminoName

func (m *TopupMsg) AminoName() string

func (*TopupMsg) Marshal

func (m *TopupMsg) Marshal() ([]byte, error)

func (*TopupMsg) TypeURL

func (m *TopupMsg) TypeURL() string

type ValidatorExitMsg

type ValidatorExitMsg struct {
	From              string
	ValID             uint64
	DeactivationEpoch uint64
	TxHash            []byte
	LogIndex          uint64
	BlockNumber       uint64
	Nonce             uint64
}

ValidatorExitMsg wraps MsgValidatorExit.

func (*ValidatorExitMsg) AminoJSON

func (m *ValidatorExitMsg) AminoJSON() (any, error)

func (*ValidatorExitMsg) AminoName

func (m *ValidatorExitMsg) AminoName() string

func (*ValidatorExitMsg) Marshal

func (m *ValidatorExitMsg) Marshal() ([]byte, error)

func (*ValidatorExitMsg) TypeURL

func (m *ValidatorExitMsg) TypeURL() string

type ValidatorJoinMsg

type ValidatorJoinMsg struct {
	From            string
	ValID           uint64
	ActivationEpoch uint64
	Amount          string
	SignerPubKey    []byte
	TxHash          []byte
	LogIndex        uint64
	BlockNumber     uint64
	Nonce           uint64
}

ValidatorJoinMsg wraps MsgValidatorJoin.

func (*ValidatorJoinMsg) AminoJSON

func (m *ValidatorJoinMsg) AminoJSON() (any, error)

func (*ValidatorJoinMsg) AminoName

func (m *ValidatorJoinMsg) AminoName() string

func (*ValidatorJoinMsg) Marshal

func (m *ValidatorJoinMsg) Marshal() ([]byte, error)

func (*ValidatorJoinMsg) TypeURL

func (m *ValidatorJoinMsg) TypeURL() string

type VoteProducersMsg

type VoteProducersMsg struct {
	Voter   string
	VoterID uint64
	Votes   []uint64
}

VoteProducersMsg wraps MsgVoteProducers.

func (*VoteProducersMsg) AminoJSON

func (m *VoteProducersMsg) AminoJSON() (any, error)

func (*VoteProducersMsg) AminoName

func (m *VoteProducersMsg) AminoName() string

func (*VoteProducersMsg) Marshal

func (m *VoteProducersMsg) Marshal() ([]byte, error)

func (*VoteProducersMsg) TypeURL

func (m *VoteProducersMsg) TypeURL() string

type WithdrawFeeMsg

type WithdrawFeeMsg struct {
	Proposer string
	Amount   string
}

WithdrawFeeMsg is the starter Msg for MsgWithdrawFeeTx. Additional Msg types land alongside their subcommands in W3/W4.

func (*WithdrawFeeMsg) AminoJSON

func (m *WithdrawFeeMsg) AminoJSON() (any, error)

AminoJSON implements Msg.

func (*WithdrawFeeMsg) AminoName

func (m *WithdrawFeeMsg) AminoName() string

AminoName implements Msg.

func (*WithdrawFeeMsg) Marshal

func (m *WithdrawFeeMsg) Marshal() ([]byte, error)

Marshal implements Msg.

func (*WithdrawFeeMsg) TypeURL

func (m *WithdrawFeeMsg) TypeURL() string

TypeURL implements Msg.

Jump to

Keyboard shortcuts

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