|
|
||
|---|---|---|
| .. | ||
| common_test.go | ||
| config_test.go | ||
| config.go | ||
| encoder_test.go | ||
| encoder.go | ||
| factory_test.go | ||
| factory.go | ||
| flags.go | ||
| README.md | ||
| signature_test.go | ||
| signature.go | ||
| tx.go | ||
| types.go | ||
| wrapper.go | ||
The tx package provides a robust set of tools for building, signing, and managing transactions in a Cosmos SDK-based blockchain application.
Overview
This package includes several key components:
- Transaction Factory
- Transaction Config
- Transaction Encoder/Decoder
- Signature Handling
Architecture
graph TD
A[Client] --> B[Factory]
B --> D[TxConfig]
D --> E[TxEncodingConfig]
D --> F[TxSigningConfig]
B --> G[Tx]
G --> H[Encoder]
G --> I[Decoder]
F --> J[SignModeHandler]
F --> K[SigningContext]
B --> L[AuxTxBuilder]
Key Components
TxConfig
TxConfig provides configuration for transaction handling, including:
- Encoding and decoding
- Sign mode handling
- Signature JSON marshaling/unmarshaling
classDiagram
class TxConfig {
<<interface>>
TxEncodingConfig
TxSigningConfig
}
class TxEncodingConfig {
<<interface>>
TxEncoder() txEncoder
TxDecoder() txDecoder
TxJSONEncoder() txEncoder
TxJSONDecoder() txDecoder
Decoder() Decoder
}
class TxSigningConfig {
<<interface>>
SignModeHandler() *signing.HandlerMap
SigningContext() *signing.Context
MarshalSignatureJSON([]Signature) ([]byte, error)
UnmarshalSignatureJSON([]byte) ([]Signature, error)
}
class txConfig {
TxEncodingConfig
TxSigningConfig
}
class defaultEncodingConfig {
cdc codec.BinaryCodec
decoder Decoder
TxEncoder() txEncoder
TxDecoder() txDecoder
TxJSONEncoder() txEncoder
TxJSONDecoder() txDecoder
}
class defaultTxSigningConfig {
signingCtx *signing.Context
handlerMap *signing.HandlerMap
cdc codec.BinaryCodec
SignModeHandler() *signing.HandlerMap
SigningContext() *signing.Context
MarshalSignatureJSON([]Signature) ([]byte, error)
UnmarshalSignatureJSON([]byte) ([]Signature, error)
}
TxConfig <|-- txConfig
TxEncodingConfig <|.. defaultEncodingConfig
TxSigningConfig <|.. defaultTxSigningConfig
txConfig *-- defaultEncodingConfig
txConfig *-- defaultTxSigningConfig
Factory
The Factory is the main entry point for creating and managing transactions. It handles:
- Account preparation
- Gas calculation
- Unsigned transaction building
- Transaction signing
- Transaction simulation
- Transaction broadcasting
classDiagram
class Factory {
keybase keyring.Keyring
cdc codec.BinaryCodec
accountRetriever account.AccountRetriever
ac address.Codec
conn gogogrpc.ClientConn
txConfig TxConfig
txParams TxParameters
tx txState
NewFactory(keybase, cdc, accRetriever, txConfig, ac, conn, parameters) Factory
Prepare() error
BuildUnsignedTx(msgs ...transaction.Msg) error
BuildsSignedTx(ctx context.Context, msgs ...transaction.Msg) (Tx, error)
calculateGas(msgs ...transaction.Msg) error
Simulate(msgs ...transaction.Msg) (*apitx.SimulateResponse, uint64, error)
UnsignedTxString(msgs ...transaction.Msg) (string, error)
BuildSimTx(msgs ...transaction.Msg) ([]byte, error)
sign(ctx context.Context, overwriteSig bool) (Tx, error)
WithGas(gas uint64)
WithSequence(sequence uint64)
WithAccountNumber(accnum uint64)
getTx() (Tx, error)
getFee() (*apitx.Fee, error)
getSigningTxData() (signing.TxData, error)
setSignatures(...Signature) error
}
class TxParameters {
<<struct>>
chainID string
AccountConfig
GasConfig
FeeConfig
SignModeConfig
TimeoutConfig
MemoConfig
}
class TxConfig {
<<interface>>
}
class Tx {
<<interface>>
}
class txState {
<<struct>>
msgs []transaction.Msg
memo string
fees []*base.Coin
gasLimit uint64
feeGranter []byte
feePayer []byte
timeoutHeight uint64
unordered bool
timeoutTimestamp uint64
signatures []Signature
signerInfos []*apitx.SignerInfo
}
Factory *-- TxParameters
Factory *-- TxConfig
Factory *-- txState
Factory ..> Tx : creates
Encoder/Decoder
The package includes functions for encoding and decoding transactions in both binary and JSON formats.
classDiagram
class Decoder {
<<interface>>
Decode(txBytes []byte) (*txdecode.DecodedTx, error)
}
class txDecoder {
<<function>>
decode(txBytes []byte) (Tx, error)
}
class txEncoder {
<<function>>
encode(tx Tx) ([]byte, error)
}
class EncoderUtils {
<<utility>>
decodeTx(cdc codec.BinaryCodec, decoder Decoder) txDecoder
encodeTx(tx Tx) ([]byte, error)
decodeJsonTx(cdc codec.BinaryCodec, decoder Decoder) txDecoder
encodeJsonTx(tx Tx) ([]byte, error)
protoTxBytes(tx *txv1beta1.Tx) ([]byte, error)
}
class MarshalOptions {
<<utility>>
Deterministic bool
}
class JSONMarshalOptions {
<<utility>>
Indent string
UseProtoNames bool
UseEnumNumbers bool
}
Decoder <.. EncoderUtils : uses
txDecoder <.. EncoderUtils : creates
txEncoder <.. EncoderUtils : implements
EncoderUtils ..> MarshalOptions : uses
EncoderUtils ..> JSONMarshalOptions : uses
Sequence Diagrams
Generate Aux Signer Data
sequenceDiagram
participant User
participant GenerateOrBroadcastTxCLI
participant generateAuxSignerData
participant makeAuxSignerData
participant AuxTxBuilder
participant ctx.PrintProto
User->>GenerateOrBroadcastTxCLI: Call with isAux flag
GenerateOrBroadcastTxCLI->>generateAuxSignerData: Call
generateAuxSignerData->>makeAuxSignerData: Call
makeAuxSignerData->>AuxTxBuilder: NewAuxTxBuilder()
makeAuxSignerData->>AuxTxBuilder: SetAddress(f.txParams.fromAddress)
alt f.txParams.offline
makeAuxSignerData->>AuxTxBuilder: SetAccountNumber(f.AccountNumber())
makeAuxSignerData->>AuxTxBuilder: SetSequence(f.Sequence())
else
makeAuxSignerData->>f.accountRetriever: GetAccountNumberSequence()
makeAuxSignerData->>AuxTxBuilder: SetAccountNumber(accNum)
makeAuxSignerData->>AuxTxBuilder: SetSequence(seq)
end
makeAuxSignerData->>AuxTxBuilder: SetMsgs(msgs...)
makeAuxSignerData->>AuxTxBuilder: SetSignMode(f.SignMode())
makeAuxSignerData->>f.keybase: GetPubKey(f.txParams.fromName)
makeAuxSignerData->>AuxTxBuilder: SetPubKey(pubKey)
makeAuxSignerData->>AuxTxBuilder: SetChainID(f.txParams.chainID)
makeAuxSignerData->>AuxTxBuilder: GetSignBytes()
makeAuxSignerData->>f.keybase: Sign(f.txParams.fromName, signBz, f.SignMode())
makeAuxSignerData->>AuxTxBuilder: SetSignature(sig)
makeAuxSignerData->>AuxTxBuilder: GetAuxSignerData()
AuxTxBuilder-->>makeAuxSignerData: Return AuxSignerData
makeAuxSignerData-->>generateAuxSignerData: Return AuxSignerData
generateAuxSignerData->>ctx.PrintProto: Print AuxSignerData
ctx.PrintProto-->>GenerateOrBroadcastTxCLI: Return result
GenerateOrBroadcastTxCLI-->>User: Return result
Generate Only
sequenceDiagram
participant User
participant GenerateOrBroadcastTxCLI
participant generateOnly
participant Factory
participant ctx.PrintString
User->>GenerateOrBroadcastTxCLI: Call with generateOnly flag
GenerateOrBroadcastTxCLI->>generateOnly: Call
generateOnly->>Factory: Prepare()
alt Error in Prepare
Factory-->>generateOnly: Return error
generateOnly-->>GenerateOrBroadcastTxCLI: Return error
GenerateOrBroadcastTxCLI-->>User: Return error
end
generateOnly->>Factory: UnsignedTxString(msgs...)
Factory->>Factory: BuildUnsignedTx(msgs...)
Factory->>Factory: setMsgs(msgs...)
Factory->>Factory: setMemo(f.txParams.memo)
Factory->>Factory: setFees(f.txParams.gasPrices)
Factory->>Factory: setGasLimit(f.txParams.gas)
Factory->>Factory: setFeeGranter(f.txParams.feeGranter)
Factory->>Factory: setFeePayer(f.txParams.feePayer)
Factory->>Factory: setTimeoutHeight(f.txParams.timeoutHeight)
Factory->>Factory: getTx()
Factory->>Factory: txConfig.TxJSONEncoder()
Factory->>Factory: encoder(tx)
Factory-->>generateOnly: Return unsigned tx string
generateOnly->>ctx.PrintString: Print unsigned tx string
ctx.PrintString-->>generateOnly: Return result
generateOnly-->>GenerateOrBroadcastTxCLI: Return result
GenerateOrBroadcastTxCLI-->>User: Return result
DryRun
sequenceDiagram
participant User
participant GenerateOrBroadcastTxCLI
participant dryRun
participant Factory
participant os.Stderr
User->>GenerateOrBroadcastTxCLI: Call with dryRun flag
GenerateOrBroadcastTxCLI->>dryRun: Call
dryRun->>Factory: Prepare()
alt Error in Prepare
Factory-->>dryRun: Return error
dryRun-->>GenerateOrBroadcastTxCLI: Return error
GenerateOrBroadcastTxCLI-->>User: Return error
end
dryRun->>Factory: Simulate(msgs...)
Factory->>Factory: BuildSimTx(msgs...)
Factory->>Factory: BuildUnsignedTx(msgs...)
Factory->>Factory: getSimPK()
Factory->>Factory: getSimSignatureData(pk)
Factory->>Factory: setSignatures(sig)
Factory->>Factory: getTx()
Factory->>Factory: txConfig.TxEncoder()(tx)
Factory->>ServiceClient: Simulate(context.Background(), &apitx.SimulateRequest{})
ServiceClient->>Factory: Return result
Factory-->>dryRun: Return (simulation, gas, error)
alt Error in Simulate
dryRun-->>GenerateOrBroadcastTxCLI: Return error
GenerateOrBroadcastTxCLI-->>User: Return error
end
dryRun->>os.Stderr: Fprintf(GasEstimateResponse{GasEstimate: gas})
os.Stderr-->>dryRun: Return result
dryRun-->>GenerateOrBroadcastTxCLI: Return result
GenerateOrBroadcastTxCLI-->>User: Return result
Generate and Broadcast Tx
sequenceDiagram
participant User
participant GenerateOrBroadcastTxCLI
participant BroadcastTx
participant Factory
participant clientCtx
User->>GenerateOrBroadcastTxCLI: Call
GenerateOrBroadcastTxCLI->>BroadcastTx: Call
BroadcastTx->>Factory: Prepare()
alt Error in Prepare
Factory-->>BroadcastTx: Return error
BroadcastTx-->>GenerateOrBroadcastTxCLI: Return error
GenerateOrBroadcastTxCLI-->>User: Return error
end
alt SimulateAndExecute is true
BroadcastTx->>Factory: calculateGas(msgs...)
Factory->>Factory: Simulate(msgs...)
Factory->>Factory: WithGas(adjusted)
end
BroadcastTx->>Factory: BuildUnsignedTx(msgs...)
Factory->>Factory: setMsgs(msgs...)
Factory->>Factory: setMemo(f.txParams.memo)
Factory->>Factory: setFees(f.txParams.gasPrices)
Factory->>Factory: setGasLimit(f.txParams.gas)
Factory->>Factory: setFeeGranter(f.txParams.feeGranter)
Factory->>Factory: setFeePayer(f.txParams.feePayer)
Factory->>Factory: setTimeoutHeight(f.txParams.timeoutHeight)
alt !clientCtx.SkipConfirm
BroadcastTx->>Factory: getTx()
BroadcastTx->>Factory: txConfig.TxJSONEncoder()
BroadcastTx->>clientCtx: PrintRaw(txBytes)
BroadcastTx->>clientCtx: Input.GetConfirmation()
alt Not confirmed
BroadcastTx-->>GenerateOrBroadcastTxCLI: Return error
GenerateOrBroadcastTxCLI-->>User: Return error
end
end
BroadcastTx->>Factory: BuildsSignedTx(ctx, msgs...)
Factory->>Factory: sign(ctx, true)
Factory->>Factory: keybase.GetPubKey(fromName)
Factory->>Factory: getSignBytesAdapter()
Factory->>Factory: keybase.Sign(fromName, bytesToSign, signMode)
Factory->>Factory: setSignatures(sig)
Factory->>Factory: getTx()
BroadcastTx->>Factory: txConfig.TxEncoder()
BroadcastTx->>clientCtx: BroadcastTx(txBytes)
alt Error in BroadcastTx
clientCtx-->>BroadcastTx: Return error
BroadcastTx-->>GenerateOrBroadcastTxCLI: Return error
GenerateOrBroadcastTxCLI-->>User: Return error
end
BroadcastTx->>clientCtx: OutputTx(res)
clientCtx-->>BroadcastTx: Return result
BroadcastTx-->>GenerateOrBroadcastTxCLI: Return result
GenerateOrBroadcastTxCLI-->>User: Return result
Usage
To use the tx package, typically you would:
- Create a
Factory - Simulate the transaction (optional)
- Build a signed transaction
- Encode the transaction
- Broadcast the transaction
Here's a simplified example:
// Create a Factory
factory, err := NewFactory(keybase, cdc, accountRetriever, txConfig, addressCodec, conn, txParameters)
if err != nil {
return err
}
// Simulate the transaction (optional)
simRes, gas, err := factory.Simulate(msgs...)
if err != nil {
return err
}
factory.WithGas(gas)
// Build a signed transaction
signedTx, err := factory.BuildsSignedTx(context.Background(), msgs...)
if err != nil {
return err
}
// Encode the transaction
txBytes, err := factory.txConfig.TxEncoder()(signedTx)
if err != nil {
return err
}
// Broadcast the transaction
// (This step depends on your specific client implementation)