pretty ugly. But got the hash from the bip143 example.
This commit is contained in:
parent
233ec9538c
commit
f6cf4b87f0
@ -5,8 +5,10 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
@ -16,36 +18,130 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
inspk0 = "2103c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432ac"
|
inspk0 = "2103c9f4836b9a4f77fc0d81f7bcb01b7f1b35916864b9476c241ce9fc198bd25432ac"
|
||||||
inamt0 = uint64(625000000)
|
inamt0 = int64(625000000)
|
||||||
|
|
||||||
inspk1 = "00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1"
|
inspk1 = "00141d0f172a0ecb48aee1be1f2687d2963ae33f71a1"
|
||||||
inamt1 = uint64(600000000)
|
inamt1 = int64(600000000)
|
||||||
)
|
)
|
||||||
|
|
||||||
func outpointBytesLil(op wire.OutPoint) []byte {
|
// calcWitnessSignatureHash is the witnessified version of calcSignatureHash
|
||||||
var buf bytes.Buffer
|
func calcWitnessSignatureHash(
|
||||||
// ignore errors because.. whatever
|
hashType txscript.SigHashType, tx *wire.MsgTx, idx int, amt int64) []byte {
|
||||||
_ = binary.Write(&buf, binary.LittleEndian, op.Index)
|
// in the script.go calcSignatureHash(), idx is assumed safe, so I guess
|
||||||
|
// that's OK here too...
|
||||||
|
|
||||||
b := op.Hash[:]
|
// first get hashPrevOuts, hashSequence, and hashOutputs
|
||||||
return append(b, buf.Bytes()...)
|
hashPrevOuts := calcHashPrevOuts(tx, hashType)
|
||||||
|
hashSequence := calcHashSequence(tx, hashType)
|
||||||
|
hashOutputs := calcHashOutputs(tx, idx, hashType)
|
||||||
|
|
||||||
|
var buf4 [4]byte // buffer for 4-byte stuff
|
||||||
|
var buf8 [8]byte // buffer for 8-byte stuff
|
||||||
|
var pre []byte // the pre-image we're generating
|
||||||
|
|
||||||
|
binary.LittleEndian.PutUint32(buf4[:], uint32(tx.Version))
|
||||||
|
pre = append(pre, buf4[:]...)
|
||||||
|
|
||||||
|
pre = append(pre, hashPrevOuts.Bytes()...)
|
||||||
|
pre = append(pre, hashSequence.Bytes()...)
|
||||||
|
|
||||||
|
// outpoint being spent
|
||||||
|
pre = append(pre, tx.TxIn[idx].PreviousOutPoint.Hash.Bytes()...)
|
||||||
|
binary.LittleEndian.PutUint32(buf4[:], tx.TxIn[idx].PreviousOutPoint.Index)
|
||||||
|
pre = append(pre, buf4[:]...)
|
||||||
|
|
||||||
|
// scriptCode which is some new thing
|
||||||
|
sCode := []byte{0x19, 0x76, 0xa9, 0x14}
|
||||||
|
sCode = append(sCode, tx.TxIn[idx].SignatureScript[2:22]...)
|
||||||
|
sCode = append(sCode, []byte{0x88, 0xac}...)
|
||||||
|
pre = append(pre, sCode...)
|
||||||
|
|
||||||
|
// amount being signed off
|
||||||
|
binary.LittleEndian.PutUint64(buf8[:], uint64(amt))
|
||||||
|
pre = append(pre, buf8[:]...)
|
||||||
|
|
||||||
|
// nsequence of input
|
||||||
|
binary.LittleEndian.PutUint32(buf4[:], tx.TxIn[idx].Sequence)
|
||||||
|
pre = append(pre, buf4[:]...)
|
||||||
|
|
||||||
|
pre = append(pre, hashOutputs.Bytes()...)
|
||||||
|
|
||||||
|
// locktime
|
||||||
|
binary.LittleEndian.PutUint32(buf4[:], tx.LockTime)
|
||||||
|
pre = append(pre, buf4[:]...)
|
||||||
|
|
||||||
|
// hashType... in 4 bytes, instead of 1, because reasons.
|
||||||
|
binary.LittleEndian.PutUint32(buf4[:], uint32(hashType))
|
||||||
|
pre = append(pre, buf4[:]...)
|
||||||
|
|
||||||
|
fmt.Printf("pre: %x\n", pre)
|
||||||
|
hsh := wire.DoubleSha256SH(pre)
|
||||||
|
return hsh.Bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
func calcSignatureHash(
|
// calcHashPrevOuts makes a single hash of all previous outputs in the tx
|
||||||
hashType txscript.SigHashType, tx *wire.MsgTx, idx int) []byte {
|
func calcHashPrevOuts(tx *wire.MsgTx, hType txscript.SigHashType) wire.ShaHash {
|
||||||
|
// skip this (0x00) for anyonecanpay
|
||||||
return nil
|
if hType == txscript.SigHashAnyOneCanPay {
|
||||||
|
var empty [32]byte
|
||||||
|
return empty
|
||||||
}
|
}
|
||||||
|
|
||||||
// if sighash_ALL, hash of all txin outpoints, sequentially.
|
var pre []byte
|
||||||
// if other sighash type, 0x00 * 32
|
|
||||||
func calcHashPrevOuts(tx *wire.MsgTx) [32]byte {
|
|
||||||
|
|
||||||
for _, in := range tx.TxIn {
|
for _, in := range tx.TxIn {
|
||||||
// in.PreviousOutPoint.Hash
|
// first append 32 byte hash
|
||||||
|
pre = append(pre, in.PreviousOutPoint.Hash.Bytes()...)
|
||||||
|
// then make a buffer, put 4 byte index in lil' endian and append that
|
||||||
|
var buf [4]byte
|
||||||
|
binary.LittleEndian.PutUint32(buf[:], in.PreviousOutPoint.Index)
|
||||||
|
pre = append(pre, buf[:]...)
|
||||||
|
}
|
||||||
|
fmt.Printf("pre: %x\n", pre)
|
||||||
|
return wire.DoubleSha256SH(pre)
|
||||||
}
|
}
|
||||||
|
|
||||||
return wire.DoubleSha256SH(tx.TxIn[0].SignatureScript)
|
// calcHashSequence is hash of txins' seq numbers, lil' endian, stuck together
|
||||||
|
func calcHashSequence(tx *wire.MsgTx, hType txscript.SigHashType) wire.ShaHash {
|
||||||
|
// skip (0x00) for single, none, anyonecanpay
|
||||||
|
if hType == txscript.SigHashSingle || hType == txscript.SigHashNone ||
|
||||||
|
hType == txscript.SigHashAnyOneCanPay {
|
||||||
|
var empty [32]byte
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
|
||||||
|
var pre []byte
|
||||||
|
for _, in := range tx.TxIn {
|
||||||
|
var buf [4]byte
|
||||||
|
binary.LittleEndian.PutUint32(buf[:], in.Sequence)
|
||||||
|
pre = append(pre, buf[:]...)
|
||||||
|
}
|
||||||
|
fmt.Printf("pre: %x\n", pre)
|
||||||
|
return wire.DoubleSha256SH(pre)
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcHashOutputs also wants a input index, which it only uses for
|
||||||
|
// sighash single. If it's not sighash single, just put a 0 or whatever.
|
||||||
|
func calcHashOutputs(
|
||||||
|
tx *wire.MsgTx, inIndex int, hType txscript.SigHashType) wire.ShaHash {
|
||||||
|
if hType == txscript.SigHashNone ||
|
||||||
|
(hType == txscript.SigHashSingle && inIndex <= len(tx.TxOut)) {
|
||||||
|
var empty [32]byte
|
||||||
|
return empty
|
||||||
|
}
|
||||||
|
if hType == txscript.SigHashSingle {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
writeTxOut(&buf, 0, 0, tx.TxOut[inIndex])
|
||||||
|
return wire.DoubleSha256SH(buf.Bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
var pre []byte
|
||||||
|
for _, out := range tx.TxOut {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
writeTxOut(&buf, 0, 0, out)
|
||||||
|
pre = append(pre, buf.Bytes()...)
|
||||||
|
}
|
||||||
|
fmt.Printf("pre: %x\n", pre)
|
||||||
|
return wire.DoubleSha256SH(pre)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -88,4 +184,72 @@ func main() {
|
|||||||
|
|
||||||
fmt.Printf(uspv.TxToString(ttx))
|
fmt.Printf(uspv.TxToString(ttx))
|
||||||
|
|
||||||
|
hxh := calcWitnessSignatureHash(txscript.SigHashAll, ttx, 1, inamt1)
|
||||||
|
|
||||||
|
fmt.Printf("got sigHash %x\n", hxh)
|
||||||
|
}
|
||||||
|
|
||||||
|
// pver can be 0, doesn't do anything in these. Same for msg.Version
|
||||||
|
// writeVarInt serializes val to w using a variable number of bytes depending
|
||||||
|
// on its value.
|
||||||
|
func writeVarInt(w io.Writer, pver uint32, val uint64) error {
|
||||||
|
if val < 0xfd {
|
||||||
|
_, err := w.Write([]byte{uint8(val)})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if val <= math.MaxUint16 {
|
||||||
|
var buf [3]byte
|
||||||
|
buf[0] = 0xfd
|
||||||
|
binary.LittleEndian.PutUint16(buf[1:], uint16(val))
|
||||||
|
_, err := w.Write(buf[:])
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if val <= math.MaxUint32 {
|
||||||
|
var buf [5]byte
|
||||||
|
buf[0] = 0xfe
|
||||||
|
binary.LittleEndian.PutUint32(buf[1:], uint32(val))
|
||||||
|
_, err := w.Write(buf[:])
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf [9]byte
|
||||||
|
buf[0] = 0xff
|
||||||
|
binary.LittleEndian.PutUint64(buf[1:], val)
|
||||||
|
_, err := w.Write(buf[:])
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeVarBytes serializes a variable length byte array to w as a varInt
|
||||||
|
// containing the number of bytes, followed by the bytes themselves.
|
||||||
|
func writeVarBytes(w io.Writer, pver uint32, bytes []byte) error {
|
||||||
|
slen := uint64(len(bytes))
|
||||||
|
err := writeVarInt(w, pver, slen)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(bytes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// writeTxOut encodes to into the bitcoin protocol encoding for a transaction
|
||||||
|
// output (TxOut) to w.
|
||||||
|
func writeTxOut(w io.Writer, pver uint32, version int32, to *wire.TxOut) error {
|
||||||
|
var buf [8]byte
|
||||||
|
binary.LittleEndian.PutUint64(buf[:], uint64(to.Value))
|
||||||
|
_, err := w.Write(buf[:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writeVarBytes(w, pver, to.PkScript)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user