Skip to content

Instantly share code, notes, and snippets.

@cpacia
Created May 16, 2018 00:06
Show Gist options
  • Save cpacia/69d3ad71508c63631a5b81afe530ba3a to your computer and use it in GitHub Desktop.
Save cpacia/69d3ad71508c63631a5b81afe530ba3a to your computer and use it in GitHub Desktop.
Bitcoin Cash tree signature
package main
import (
"fmt"
"github.com/btcsuite/btcd/btcec"
"encoding/hex"
"crypto/sha256"
"github.com/btcsuite/btcd/txscript"
"github.com/cpacia/bchutil"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"bytes"
)
func main() {
// Create the keys
b1, _ := hex.DecodeString("7aa6f244ab964b29195fcda35119f3c2ac2987544552140762fae158309f9370")
key1, _ := btcec.PrivKeyFromBytes(btcec.S256(), b1)
b2, _ := hex.DecodeString("02d9d13cbb800123c03401247b64bdc4599f8745f0ae65e0040bd2510f7adfb5")
key2, _ := btcec.PrivKeyFromBytes(btcec.S256(), b2)
b3, _ := hex.DecodeString("887637c7f3dbf5fe545f8b7289f7560ee489ff2461c0e88af198a8eae5c6b694")
key3, _ := btcec.PrivKeyFromBytes(btcec.S256(), b3)
b4, _ := hex.DecodeString("a3be9fb58097fd582efd096858c848934d73f984b3cc4fb73ab74d5e5406825d")
key4, _ := btcec.PrivKeyFromBytes(btcec.S256(), b4)
b5, _ := hex.DecodeString("f5bdf62dae621bfea15439dd2e647e6ac1ce6cb3b2f9f593b7cb45a10a03e22c")
key5, _ := btcec.PrivKeyFromBytes(btcec.S256(), b5)
b6, _ := hex.DecodeString("83f182eb806b7a718ca2ff2d909c09a59bd073afe3404242de3d4f241e5bc818")
key6, _ := btcec.PrivKeyFromBytes(btcec.S256(), b6)
b7, _ := hex.DecodeString("1160a52d2e6e345013d6389abcc249377c915ad4a103530e9f9acab9eeac6d12")
key7, _ := btcec.PrivKeyFromBytes(btcec.S256(), b7)
b8, _ := hex.DecodeString("c589ec735c91b3acafa13de995b227d57333645d8fdd94e545cc2927351c7a9f")
key8, _ := btcec.PrivKeyFromBytes(btcec.S256(), b8)
// Hash into tree
k1 := sha256.Sum256(key1.PubKey().SerializeCompressed())
k2 := sha256.Sum256(key2.PubKey().SerializeCompressed())
k3 := sha256.Sum256(key3.PubKey().SerializeCompressed())
k4 := sha256.Sum256(key4.PubKey().SerializeCompressed())
k5 := sha256.Sum256(key5.PubKey().SerializeCompressed())
k6 := sha256.Sum256(key6.PubKey().SerializeCompressed())
k7 := sha256.Sum256(key7.PubKey().SerializeCompressed())
k8 := sha256.Sum256(key8.PubKey().SerializeCompressed())
x1 := sha256.Sum256(append(k1[:], k2[:]...))
x2 := sha256.Sum256(append(k3[:], k4[:]...))
x3 := sha256.Sum256(append(k5[:], k6[:]...))
x4 := sha256.Sum256(append(k7[:], k8[:]...))
y1 := sha256.Sum256(append(x1[:], x2[:]...))
y2 := sha256.Sum256(append(x3[:], x4[:]...))
r := sha256.Sum256(append(y1[:], y2[:]...))
// Build redeem script
builder := txscript.NewScriptBuilder().
AddOp(txscript.OP_6).
AddOp(txscript.OP_PICK).
AddOp(txscript.OP_SHA256).
AddOp(txscript.OP_SWAP).
AddOp(txscript.OP_IF).
AddOp(txscript.OP_SWAP).
AddOp(txscript.OP_ENDIF).
AddOp(txscript.OP_CAT).
AddOp(txscript.OP_SHA256).
AddOp(txscript.OP_SWAP).
AddOp(txscript.OP_IF).
AddOp(txscript.OP_SWAP).
AddOp(txscript.OP_ENDIF).
AddOp(txscript.OP_CAT).
AddOp(txscript.OP_SHA256).
AddOp(txscript.OP_SWAP).
AddOp(txscript.OP_IF).
AddOp(txscript.OP_SWAP).
AddOp(txscript.OP_ENDIF).
AddOp(txscript.OP_CAT).
AddOp(txscript.OP_SHA256).
AddData(r[:]).
AddOp(txscript.OP_EQUALVERIFY).
AddOp(txscript.OP_CHECKSIG)
redeemScript, _ := builder.Script()
// Create payment address
addr, _ := bchutil.NewCashAddressScriptHash(redeemScript, &chaincfg.MainNetParams)
fmt.Printf("address: %s\n", addr.String())
// Build input
val := int64(71905)
prevHash, _ := chainhash.NewHashFromStr("93628593212ebe9d57086117eb6c643146d3a10e063151d5ba8e7c5f6d619ee9")
prevIndex := uint32(0)
op := wire.NewOutPoint(prevHash, prevIndex)
in := wire.NewTxIn(op, []byte{}, [][]byte{})
// Calculate the fee
feePerByte := 5
fee := int64(336 * feePerByte)
// Build output
outAddr, _ := bchutil.DecodeAddress("qqm82pnlfh5dkepv0dyky4zuwd04hw6chcucjwnhpz", &chaincfg.MainNetParams)
outScript, _ := bchutil.PayToAddrScript(outAddr)
out := wire.NewTxOut(val-fee, outScript)
// Build transaction
tx := &wire.MsgTx{
Version: wire.TxVersion,
TxIn: []*wire.TxIn{in},
TxOut: []*wire.TxOut{out},
LockTime: 0,
}
// Sign input
sig, _ := bchutil.RawTxInSignature(tx, 0, redeemScript, txscript.SigHashAll, key5, val)
sigBuilder := txscript.NewScriptBuilder().
AddData(sig).
AddData(key5.PubKey().SerializeCompressed()).
AddData(y1[:]).
AddOp(txscript.OP_0).
AddData(x4[:]).
AddOp(txscript.OP_1).
AddData(k6[:]).
AddOp(txscript.OP_1).
AddData(redeemScript)
scriptSig, _ := sigBuilder.Script()
tx.TxIn[0].SignatureScript = scriptSig
// Print out raw transaction
var b []byte
buf := bytes.NewBuffer(b)
tx.BtcEncode(buf, 1, wire.BaseEncoding)
fmt.Printf("raw tx: %s\n", hex.EncodeToString(buf.Bytes()))
fmt.Printf("txid: %s\n", tx.TxHash())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment