psbt

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Aug 28, 2025 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package psbt PSBT处理

v2_builder.go (fixed)

Index

Constants

View Source
const (
	VersionV0 = 0
	VersionV2 = 2
)

Version 常量:支持 v0(BIP174) / v2(BIP370)

View Source
const (
	PSBT_GLOBAL_TX_VERSION    = 0x02
	PSBT_GLOBAL_FALLBACK_LOCK = 0x03
	PSBT_GLOBAL_INPUT_COUNT   = 0x04
	PSBT_GLOBAL_OUTPUT_COUNT  = 0x05
	PSBT_GLOBAL_VERSION       = 0xfb

	PSBT_IN_NON_WITNESS_UTXO = 0x00
	PSBT_IN_WITNESS_UTXO     = 0x01
	PSBT_IN_REDEEM_SCRIPT    = 0x04
	PSBT_IN_WITNESS_SCRIPT   = 0x05
	PSBT_IN_PREVIOUS_TXID    = 0x0e
	PSBT_IN_OUTPUT_INDEX     = 0x0f
	PSBT_IN_SEQUENCE         = 0x10

	PSBT_OUT_REDEEM_SCRIPT  = 0x00
	PSBT_OUT_WITNESS_SCRIPT = 0x01
	PSBT_OUT_AMOUNT         = 0x03
	PSBT_OUT_SCRIPT         = 0x04
)

====== PSBT v2 序列化 ======

Variables

This section is empty.

Functions

func SerializeV2Packet

func SerializeV2Packet(p *Packet) ([]byte, error)

Types

type AnalyzeInputReport

type AnalyzeInputReport struct {
	Index      int
	ScriptType types.AddressType
	HasUtxo    bool
	IsFinal    bool
	Ready      bool
	Missing    []string
}

AnalyzeInputReport 描述单个输入的自检结果

type AnalyzeReport

type AnalyzeReport struct {
	Version     int
	InputCount  int
	OutputCount int
	Inputs      []AnalyzeInputReport
	CanFinalize bool
}

AnalyzeReport 汇总整笔 PSBT 的自检结果

type BIP32Derivation

type BIP32Derivation struct {
	PubKey      []byte   // 压缩公钥(33)
	Fingerprint [4]byte  // 父键指纹
	Path        []uint32 // 绝对或相对路径(m/.. 样式外部表示由调用方维护)
}

BIP32Derivation 记录单钥的派生路径

type BuildResult

type BuildResult struct {
	PSBTBase64      string  `json:"psbt_base64"`        // 给 OKX
	UnsignedTxHex   string  `json:"unsigned_tx_hex"`    // 调试/核对
	Packet          *Packet `json:"-"`                  // 你自定义 psbt 结构,便于回写签名/Finalize
	EstimatedVSize  int     `json:"estimated_vsize_vb"` // 估算
	FeeSat          int64   `json:"fee_sat"`
	ChangeOutputIdx int     `json:"change_output_index"` // -1 表示没有找零
}

输出给调用方/前端(包含 OKX 可用的 PSBT base64)

func CreatePSBTForOKX

func CreatePSBTForOKX(
	inputParams *types.TxInputParams,
	selectedUTXOs []PsbtUTXO,
	network *chaincfg.Params,
) (*BuildResult, error)

CreatePSBTForOKX 生成可供 OKX 钱包签名的 PSBT(v0)

func CreatePSBTv2ForOKX

func CreatePSBTv2ForOKX(
	inputParams *types.TxInputParams,
	selectedUTXOs []PsbtUTXO,
	network *chaincfg.Params,
) (*BuildResult, error)

CreatePSBTv2ForOKX 构建 PSBT v2(BIP-370),并返回 v2 base64 字符串。

type CleanupOptions

type CleanupOptions struct {
	KeepWitnessScript bool // 是否保留 WitnessScript/TapLeafScript/ControlBlock/Annex
	KeepRedeemScript  bool // 是否保留 RedeemScript
	KeepUTXO          bool // 是否保留 WitnessUtxo/NonWitnessUtxo
}

CleanupOptions 控制 Finalize 后的字段保留策略

type Input

type Input struct {
	// 引用的前序输出(v0 可从 UnsignedTx 读取;v2 需要显式设置)
	PrevTxID  chainhash.Hash
	PrevIndex uint32
	Sequence  uint32

	// UTXO 信息(二选一或同时提供,遵循 BIP174)
	NonWitnessUtxo *wire.MsgTx
	WitnessUtxo    *wire.TxOut

	// 脚本与派生信息
	RedeemScript  []byte
	WitnessScript []byte
	BIP32         []BIP32Derivation
	// 通用见证栈(适用于 P2WSH 任意脚本;不含最终脚本本身)
	WitnessStack [][]byte

	// 签名相关
	SighashType uint32            // txscript.SigHashType
	PartialSigs map[string][]byte // pubkey(hex) -> sig (DER+hashtype 或 Schnorr+hashtype)

	// 最终化产物
	FinalScriptSig     []byte
	FinalScriptWitness wire.TxWitness

	// Taproot 脚本路径(tapscript)相关
	// 若使用脚本路径花费,应提供:TapLeafScript、TapControlBlock;
	// 可选提供:TapAnnex(首字节应为 0x50)、TapScriptStack(额外入栈元素,不含脚本与控制块)。
	TapLeafScript   []byte
	TapControlBlock []byte
	TapAnnex        []byte
	TapScriptStack  [][]byte

	// Taproot 签名(PSBT-371 友好建模)
	// Keypath 签名:单一 schnorr+hashtype
	TapKeySig []byte
	// Scriptpath 签名:key = hex(xonlyPubKey)+":"+hex(leafHash)
	TapScriptSigs map[string][]byte
}

Input 表示单个输入的 PSBT 附加数据

type Output

type Output struct {
	Value        int64
	ScriptPubKey []byte

	RedeemScript  []byte
	WitnessScript []byte
	BIP32         []BIP32Derivation
}

Output 表示单个输出的 PSBT 附加数据

type Packet

type Packet struct {
	// 版本:0 或 2
	Version int

	// v0:未签名交易的完整结构
	UnsignedTx *wire.MsgTx

	// v2:交易元数据(不直接包含完整 MsgTx)
	TxVersion int32
	LockTime  uint32

	Inputs  []*Input
	Outputs []*Output

	// Finalize 后清理策略
	Cleanup CleanupOptions
}

Packet 表示一个(简化版)PSBT 数据结构,覆盖 v0/v2 关键字段以满足本库的角色操作。 注:此结构关注“功能”与“互操作”,序列化/反序列化可后续扩展。

func NewV0FromUnsignedTx

func NewV0FromUnsignedTx(unsigned *wire.MsgTx) *Packet

NewV0FromUnsignedTx 创建 v0 PSBT:填入未签名交易;Inputs/Outputs 根据 UnsignedTx 初始化空 maps。

func NewV2

func NewV2(txVersion int32, lockTime uint32, inCount, outCount int) *Packet

NewV2 创建 v2 PSBT:设置元数据与 I/O 计数,并初始化空 maps。

func (*Packet) Analyze

func (p *Packet) Analyze() AnalyzeReport

Analyze 对当前 PSBT 做自检,给出每个输入缺失项与可最终化评估

func (*Packet) Combine

func (p *Packet) Combine(others ...*Packet) error

Combine 合并多份 PSBT(只合并相同交易的输入签名/元数据;冲突时保留已有并忽略冲突项)

func (*Packet) Extract

func (p *Packet) Extract() (*wire.MsgTx, error)

Extract 当所有输入都最终化后,导出可广播的原始交易(wire.MsgTx)

func (*Packet) FinalizeAll

func (p *Packet) FinalizeAll() error

FinalizeAll 尝试最终化所有输入

func (*Packet) FinalizeInput

func (p *Packet) FinalizeInput(i int) error

FinalizeInput 根据已收集到的 PartialSigs/WitnessScript 等,生成最终的 ScriptSig/ScriptWitness。 支持 p2wpkh / p2wsh(v0) / p2tr-keypath / p2sh-wrapped-segwit / legacy p2pkh/p2sh

func (*Packet) IsV0

func (p *Packet) IsV0() bool

IsV0 返回是否 v0

func (*Packet) IsV2

func (p *Packet) IsV2() bool

IsV2 返回是否 v2

func (*Packet) MustInput

func (p *Packet) MustInput(i int) *Input

MustInput 返回第 i 个输入,越界报错。

func (*Packet) MustOutput

func (p *Packet) MustOutput(i int) *Output

MustOutput 返回第 i 个输出,越界报错。

func (*Packet) SetInputDerivation

func (p *Packet) SetInputDerivation(i int, d BIP32Derivation)

SetInputDerivation 设置单钥的 BIP32 派生信息

func (*Packet) SetInputScripts

func (p *Packet) SetInputScripts(i int, redeem, witness []byte)

SetInputScripts 设置 redeem/witness 脚本

func (*Packet) SetInputTapScriptPath

func (p *Packet) SetInputTapScriptPath(i int, script, control, annex []byte, stack ...[]byte)

SetInputTapScriptPath 设置 Taproot 脚本路径花费所需数据 script: tapscript 脚本 control: 控制块 annex: 可选 annex(若非空,首字节应为 0x50),可传 nil stack: 额外入栈元素(不含脚本与控制块,不含 annex/sig),可为空

func (*Packet) SetInputUtxo

func (p *Packet) SetInputUtxo(i int, witness *wire.TxOut, nonWitness *wire.MsgTx)

SetInputUtxo 为第 i 个输入设置 UTXO(优先 witnessUtxo;若为 legacy 建议提供 nonWitnessUtxo)

func (*Packet) SetInputWitnessStack

func (p *Packet) SetInputWitnessStack(i int, elems ...[]byte)

SetInputWitnessStack 设置通用 witness 栈(不包含脚本与 control block)

func (*Packet) SetV2InputMeta

func (p *Packet) SetV2InputMeta(i int, prev chainhash.Hash, vout uint32, seq uint32)

SetV2InputMeta 设置 v2 输入的前序 outpoint/sequence

func (*Packet) SetV2OutputMeta

func (p *Packet) SetV2OutputMeta(i int, value int64, spk []byte)

SetV2OutputMeta 设置 v2 输出金额与脚本

func (*Packet) SignInput

func (p *Packet) SignInput(i int, pubkey []byte, sighash txscript.SigHashType, privSign func(digest []byte) ([]byte, error)) error

SignInput 依据 PSBT 中的 UTXO 信息尝试为索引 i 的输入签名。 仅当数据充分时才签名;legacy 需校验 non-witness utxo 的 txid;缺失则返回错误。 privSign 为回调:接收 digest(双 SHA256)并返回 DER(sig)+hashtype(或 schnorr+hashtype)。

type PsbtUTXO

type PsbtUTXO struct {
	TxID            string // 大端 txid
	Vout            uint32
	ValueSat        int64  // 金额,sats
	ScriptPubKeyHex string // 前序输出的 pkScript(hex)

	// Legacy P2PKH/P2SH 如要签名,必须提供 non-witness 前序原始交易(hex)
	NonWitnessTxHex string // 可留空(P2WPKH/P2TR 不需要)

	// 可选,P2SH/P2WSH 的 witnessScript(hex)
	RedeemScriptHex string // 可选,P2SH/P2WSH 的 redeemScript(hex)

	// 可选,P2WSH 的 witnessScript(hex)
	WitnessScriptHex string // 可选,P2WSH 的 witnessScript(hex)
}

UTXO 最少需要这些信息(优先走 segwit,legacy 需要 nonWitnessTx)

Jump to

Keyboard shortcuts

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