mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
[NOD-374] Create transaction signer tool (#435)
* [NOD-374 ] Create transaction signer tool * [NOD-374] Rename variables * [NOD-374] Add network selection; Move error handling to control-flow function * [NOD-374] Rename variables * [NOD-374] Add new line after if blocks * [NOD-374] Fix formatting error (gofmt)
This commit is contained in:
parent
e2d3c4c821
commit
7c9f5a65d8
56
cmd/txsigner/config.go
Normal file
56
cmd/txsigner/config.go
Normal file
@ -0,0 +1,56 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/daglabs/btcd/dagconfig"
|
||||
"github.com/jessevdk/go-flags"
|
||||
"os"
|
||||
)
|
||||
|
||||
var activeNetParams = &dagconfig.MainNetParams
|
||||
|
||||
type config struct {
|
||||
Transaction string `long:"transaction" short:"t" description:"Unsigned transaction in HEX format" required:"true"`
|
||||
PrivateKey string `long:"private-key" short:"p" description:"Private key" required:"true"`
|
||||
TestNet bool `long:"testnet" description:"Use the test network"`
|
||||
RegressionTest bool `long:"regtest" description:"Use the regression test network"`
|
||||
SimNet bool `long:"simnet" description:"Use the simulation test network"`
|
||||
DevNet bool `long:"devnet" description:"Use the development test network"`
|
||||
}
|
||||
|
||||
func parseCommandLine() (*config, error) {
|
||||
cfg := &config{}
|
||||
parser := flags.NewParser(cfg, flags.PrintErrors|flags.HelpFlag)
|
||||
_, err := parser.Parse()
|
||||
// Multiple networks can't be selected simultaneously.
|
||||
funcName := "loadConfig"
|
||||
numNets := 0
|
||||
// Count number of network flags passed; assign active network params
|
||||
// while we're at it
|
||||
if cfg.TestNet {
|
||||
numNets++
|
||||
activeNetParams = &dagconfig.TestNetParams
|
||||
}
|
||||
if cfg.RegressionTest {
|
||||
numNets++
|
||||
activeNetParams = &dagconfig.RegressionNetParams
|
||||
}
|
||||
if cfg.SimNet {
|
||||
numNets++
|
||||
activeNetParams = &dagconfig.SimNetParams
|
||||
}
|
||||
if cfg.DevNet {
|
||||
numNets++
|
||||
activeNetParams = &dagconfig.DevNetParams
|
||||
}
|
||||
if numNets > 1 {
|
||||
str := "%s: The testnet, regtest, simnet and devent params can't be " +
|
||||
"used together -- choose one of the four"
|
||||
err := fmt.Errorf(str, funcName)
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
parser.WriteHelp(os.Stderr)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return cfg, err
|
||||
}
|
88
cmd/txsigner/txsigner.go
Normal file
88
cmd/txsigner/txsigner.go
Normal file
@ -0,0 +1,88 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/daglabs/btcd/btcec"
|
||||
"github.com/daglabs/btcd/txscript"
|
||||
"github.com/daglabs/btcd/util"
|
||||
"github.com/daglabs/btcd/wire"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
cfg, err := parseCommandLine()
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to parse arguments")
|
||||
}
|
||||
|
||||
privateKey, err := parsePrivateKey(cfg.PrivateKey)
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to decode private key")
|
||||
}
|
||||
|
||||
transaction, err := parseTransaction(cfg.Transaction)
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to decode transaction")
|
||||
}
|
||||
|
||||
scriptPubKey, err := createScriptPubKey(privateKey.PubKey())
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to create scriptPubKey")
|
||||
}
|
||||
|
||||
err = signTransaction(transaction, privateKey, scriptPubKey)
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to sign transaction")
|
||||
}
|
||||
|
||||
serializedTransaction, err := serializeTransaction(transaction)
|
||||
if err != nil {
|
||||
printErrorAndExit(err, "Failed to serialize transaction")
|
||||
}
|
||||
|
||||
fmt.Printf("Signed Transaction (hex): %s\n\n", serializedTransaction)
|
||||
}
|
||||
|
||||
func parsePrivateKey(privateKeyHex string) (*btcec.PrivateKey, error) {
|
||||
privateKeyBytes, err := hex.DecodeString(privateKeyHex)
|
||||
privateKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes)
|
||||
return privateKey, err
|
||||
}
|
||||
|
||||
func parseTransaction(transactionHex string) (*wire.MsgTx, error) {
|
||||
serializedTx, err := hex.DecodeString(transactionHex)
|
||||
var transaction wire.MsgTx
|
||||
err = transaction.Deserialize(bytes.NewReader(serializedTx))
|
||||
return &transaction, err
|
||||
}
|
||||
|
||||
func createScriptPubKey(publicKey *btcec.PublicKey) ([]byte, error) {
|
||||
p2pkhAddress, err := util.NewAddressPubKeyHashFromPublicKey(publicKey.SerializeCompressed(), activeNetParams.Prefix)
|
||||
scriptPubKey, err := txscript.PayToAddrScript(p2pkhAddress)
|
||||
return scriptPubKey, err
|
||||
}
|
||||
|
||||
func signTransaction(transaction *wire.MsgTx, privateKey *btcec.PrivateKey, scriptPubKey []byte) error {
|
||||
for i, transactionInput := range transaction.TxIn {
|
||||
signatureScript, err := txscript.SignatureScript(transaction, i, scriptPubKey, txscript.SigHashAll, privateKey, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
transactionInput.SignatureScript = signatureScript
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func serializeTransaction(transaction *wire.MsgTx) (string, error) {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, transaction.SerializeSize()))
|
||||
err := transaction.Serialize(buf)
|
||||
serializedTransaction := hex.EncodeToString(buf.Bytes())
|
||||
return serializedTransaction, err
|
||||
}
|
||||
|
||||
func printErrorAndExit(err error, message string) {
|
||||
fmt.Fprintf(os.Stderr, "%s: %s", message, err)
|
||||
os.Exit(1)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user