Made hashType typed as SigHashType.

This commit is contained in:
Jonathan Gillham 2014-10-11 20:55:28 +01:00
parent 9f47e9369c
commit 37ad7042b6
3 changed files with 43 additions and 38 deletions

View file

@ -1771,7 +1771,7 @@ func opcodeCheckSig(op *parsedOpcode, s *Script) error {
} }
// Trim off hashtype from the signature string. // Trim off hashtype from the signature string.
hashType := sigStr[len(sigStr)-1] hashType := SigHashType(sigStr[len(sigStr)-1])
sigStr = sigStr[:len(sigStr)-1] sigStr = sigStr[:len(sigStr)-1]
// Get script from the last OP_CODESEPARATOR and without any subsequent // Get script from the last OP_CODESEPARATOR and without any subsequent
@ -1932,7 +1932,8 @@ func opcodeCheckMultiSig(op *parsedOpcode, s *Script) error {
// check signatures. // check signatures.
success := false success := false
hash := calcScriptHash(script, signatures[i].ht, &s.tx, s.txidx) hash := calcScriptHash(script, SigHashType(signatures[i].ht),
&s.tx, s.txidx)
inner: inner:
// Find first pubkey that successfully validates signature. // Find first pubkey that successfully validates signature.
// we start off the search from the key that was successful // we start off the search from the key that was successful

View file

@ -145,13 +145,16 @@ var ErrUnsupportedAddress = errors.New("unsupported address type")
// This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012. // This timestamp corresponds to Sun Apr 1 00:00:00 UTC 2012.
var Bip16Activation = time.Unix(1333238400, 0) var Bip16Activation = time.Unix(1333238400, 0)
// SigHashType represents hash type bits at the end of a signature.
type SigHashType byte
// Hash type bits from the end of a signature. // Hash type bits from the end of a signature.
const ( const (
SigHashOld = 0x0 SigHashOld SigHashType = 0x0
SigHashAll = 0x1 SigHashAll SigHashType = 0x1
SigHashNone = 0x2 SigHashNone SigHashType = 0x2
SigHashSingle = 0x3 SigHashSingle SigHashType = 0x3
SigHashAnyOneCanPay = 0x80 SigHashAnyOneCanPay SigHashType = 0x80
) )
// These are the constants specified for maximums in individual scripts. // These are the constants specified for maximums in individual scripts.
@ -805,7 +808,7 @@ func DisasmString(buf []byte) (string, error) {
// calcScriptHash will, given the a script and hashtype for the current // calcScriptHash will, given the a script and hashtype for the current
// scriptmachine, calculate the doubleSha256 hash of the transaction and // scriptmachine, calculate the doubleSha256 hash of the transaction and
// script to be used for signature signing and verification. // script to be used for signature signing and verification.
func calcScriptHash(script []parsedOpcode, hashType byte, tx *btcwire.MsgTx, idx int) []byte { func calcScriptHash(script []parsedOpcode, hashType SigHashType, tx *btcwire.MsgTx, idx int) []byte {
// remove all instances of OP_CODESEPARATOR still left in the script // remove all instances of OP_CODESEPARATOR still left in the script
script = removeOpcode(script, OP_CODESEPARATOR) script = removeOpcode(script, OP_CODESEPARATOR)
@ -1097,7 +1100,7 @@ func MultiSigScript(pubkeys []*btcutil.AddressPubKey, nrequired int) ([]byte, er
// serialized in either a compressed or uncompressed format based on // serialized in either a compressed or uncompressed format based on
// compress. This format must match the same format used to generate // compress. This format must match the same format used to generate
// the payment address, or the script validation will fail. // the payment address, or the script validation will fail.
func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte, privKey *ecdsa.PrivateKey, compress bool) ([]byte, error) { func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType SigHashType, privKey *ecdsa.PrivateKey, compress bool) ([]byte, error) {
sig, err := signTxOutput(tx, idx, subscript, hashType, privKey) sig, err := signTxOutput(tx, idx, subscript, hashType, privKey)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1114,7 +1117,7 @@ func SignatureScript(tx *btcwire.MsgTx, idx int, subscript []byte, hashType byte
return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil return NewScriptBuilder().AddData(sig).AddData(pkData).Script(), nil
} }
func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType,
key *ecdsa.PrivateKey) ([]byte, error) { key *ecdsa.PrivateKey) ([]byte, error) {
return signTxOutputCustomReader(rand.Reader, tx, idx, subScript, return signTxOutputCustomReader(rand.Reader, tx, idx, subScript,
@ -1122,7 +1125,7 @@ func signTxOutput(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte,
} }
func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int, func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int,
subScript []byte, hashType byte, key *ecdsa.PrivateKey) ([]byte, error) { subScript []byte, hashType SigHashType, key *ecdsa.PrivateKey) ([]byte, error) {
parsedScript, err := parseScript(subScript) parsedScript, err := parseScript(subScript)
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot parse output script: %v", err) return nil, fmt.Errorf("cannot parse output script: %v", err)
@ -1133,10 +1136,11 @@ func signTxOutputCustomReader(reader io.Reader, tx *btcwire.MsgTx, idx int,
return nil, fmt.Errorf("cannot sign tx input: %s", err) return nil, fmt.Errorf("cannot sign tx input: %s", err)
} }
return append((&btcec.Signature{R: r, S: s}).Serialize(), hashType), nil return append((&btcec.Signature{R: r, S: s}).Serialize(),
byte(hashType)), nil
} }
func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, privKey *ecdsa.PrivateKey) ([]byte, error) { func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType, privKey *ecdsa.PrivateKey) ([]byte, error) {
sig, err := signTxOutput(tx, idx, subScript, hashType, privKey) sig, err := signTxOutput(tx, idx, subScript, hashType, privKey)
if err != nil { if err != nil {
return nil, err return nil, err
@ -1149,7 +1153,7 @@ func p2pkSignatureScript(tx *btcwire.MsgTx, idx int, subScript []byte, hashType
// possible. It returns the generated script and a boolean if the script fulfils // possible. It returns the generated script and a boolean if the script fulfils
// the contract (i.e. nrequired signatures are provided). Since it is arguably // the contract (i.e. nrequired signatures are provided). Since it is arguably
// legal to not be able to sign any of the outputs, no error is returned. // legal to not be able to sign any of the outputs, no error is returned.
func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte, func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType SigHashType,
addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) { addresses []btcutil.Address, nRequired int, kdb KeyDB) ([]byte, bool) {
// We start with a single OP_FALSE to work around the (now standard) // We start with a single OP_FALSE to work around the (now standard)
// but in the reference implementation that causes a spurious pop at // but in the reference implementation that causes a spurious pop at
@ -1178,7 +1182,7 @@ func signMultiSig(tx *btcwire.MsgTx, idx int, subScript []byte, hashType byte,
} }
func sign(net *btcnet.Params, tx *btcwire.MsgTx, idx int, subScript []byte, func sign(net *btcnet.Params, tx *btcwire.MsgTx, idx int, subScript []byte,
hashType byte, kdb KeyDB, sdb ScriptDB) ([]byte, ScriptClass, hashType SigHashType, kdb KeyDB, sdb ScriptDB) ([]byte, ScriptClass,
[]btcutil.Address, int, error) { []btcutil.Address, int, error) {
class, addresses, nrequired, err := ExtractPkScriptAddrs(subScript, net) class, addresses, nrequired, err := ExtractPkScriptAddrs(subScript, net)
@ -1355,7 +1359,7 @@ sigLoop:
continue continue
} }
tSig := sig[:len(sig)-1] tSig := sig[:len(sig)-1]
hashType := sig[len(sig)-1] hashType := SigHashType(sig[len(sig)-1])
pSig, err := btcec.ParseDERSignature(tSig, btcec.S256()) pSig, err := btcec.ParseDERSignature(tSig, btcec.S256())
if err != nil { if err != nil {
@ -1454,7 +1458,7 @@ func (sc ScriptClosure) GetScript(address btcutil.Address) ([]byte, error) {
// will be merged in a type-dependant manner with the newly generated. // will be merged in a type-dependant manner with the newly generated.
// signature script. // signature script.
func SignTxOutput(net *btcnet.Params, tx *btcwire.MsgTx, idx int, func SignTxOutput(net *btcnet.Params, tx *btcwire.MsgTx, idx int,
pkScript []byte, hashType byte, kdb KeyDB, sdb ScriptDB, pkScript []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB,
previousScript []byte) ([]byte, error) { previousScript []byte) ([]byte, error) {
sigScript, class, addresses, nrequired, err := sign(net, tx, idx, sigScript, class, addresses, nrequired, err := sign(net, tx, idx,

View file

@ -2518,7 +2518,7 @@ func TestCheckErrorCondition(t *testing.T) {
type TstSigScript struct { type TstSigScript struct {
name string name string
inputs []TstInput inputs []TstInput
hashtype byte hashType btcscript.SigHashType
compress bool compress bool
scriptAtWrongIndex bool scriptAtWrongIndex bool
} }
@ -2577,7 +2577,7 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -2597,7 +2597,7 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -2611,7 +2611,7 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: true, compress: true,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -2631,12 +2631,12 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: true, compress: true,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
{ {
name: "hashtype SigHashNone", name: "hashType SigHashNone",
inputs: []TstInput{ inputs: []TstInput{
{ {
txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript),
@ -2645,12 +2645,12 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashNone, hashType: btcscript.SigHashNone,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
{ {
name: "hashtype SigHashSingle", name: "hashType SigHashSingle",
inputs: []TstInput{ inputs: []TstInput{
{ {
txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript),
@ -2659,12 +2659,12 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashSingle, hashType: btcscript.SigHashSingle,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
{ {
name: "hashtype SigHashAnyoneCanPay", name: "hashType SigHashAnyoneCanPay",
inputs: []TstInput{ inputs: []TstInput{
{ {
txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript),
@ -2673,12 +2673,12 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAnyOneCanPay, hashType: btcscript.SigHashAnyOneCanPay,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
{ {
name: "hashtype non-standard", name: "hashType non-standard",
inputs: []TstInput{ inputs: []TstInput{
{ {
txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript), txout: btcwire.NewTxOut(coinbaseVal, uncompressedPkScript),
@ -2687,7 +2687,7 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: 0x04, hashType: 0x04,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -2701,7 +2701,7 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: true, compress: true,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -2714,7 +2714,7 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: false, scriptAtWrongIndex: false,
}, },
@ -2734,7 +2734,7 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: true, scriptAtWrongIndex: true,
}, },
@ -2754,14 +2754,14 @@ var SigScriptTests = []TstSigScript{
indexOutOfRange: false, indexOutOfRange: false,
}, },
}, },
hashtype: btcscript.SigHashAll, hashType: btcscript.SigHashAll,
compress: false, compress: false,
scriptAtWrongIndex: true, scriptAtWrongIndex: true,
}, },
} }
// Test the sigscript generation for valid and invalid inputs, all // Test the sigscript generation for valid and invalid inputs, all
// hashtypes, and with and without compression. This test creates // hashTypes, and with and without compression. This test creates
// sigscripts to spend fake coinbase inputs, as sigscripts cannot be // sigscripts to spend fake coinbase inputs, as sigscripts cannot be
// created for the MsgTxs in txTests, since they come from the blockchain // created for the MsgTxs in txTests, since they come from the blockchain
// and we don't have the private keys. // and we don't have the private keys.
@ -2802,7 +2802,7 @@ nexttest:
} }
script, err = btcscript.SignatureScript(tx, idx, script, err = btcscript.SignatureScript(tx, idx,
SigScriptTests[i].inputs[j].txout.PkScript, SigScriptTests[i].inputs[j].txout.PkScript,
SigScriptTests[i].hashtype, privKey, SigScriptTests[i].hashType, privKey,
SigScriptTests[i].compress) SigScriptTests[i].compress)
if (err == nil) != SigScriptTests[i].inputs[j].sigscriptGenerates { if (err == nil) != SigScriptTests[i].inputs[j].sigscriptGenerates {
@ -3239,7 +3239,7 @@ func TestMultiSigScript(t *testing.T) {
} }
func signAndCheck(msg string, tx *btcwire.MsgTx, idx int, pkScript []byte, func signAndCheck(msg string, tx *btcwire.MsgTx, idx int, pkScript []byte,
hashType byte, kdb btcscript.KeyDB, sdb btcscript.ScriptDB, hashType btcscript.SigHashType, kdb btcscript.KeyDB, sdb btcscript.ScriptDB,
previousScript []byte) error { previousScript []byte) error {
sigScript, err := btcscript.SignTxOutput( sigScript, err := btcscript.SignTxOutput(
@ -3314,7 +3314,7 @@ func TestSignTxOutput(t *testing.T) {
// make key // make key
// make script based on key. // make script based on key.
// sign with magic pixie dust. // sign with magic pixie dust.
hashTypes := []byte{ hashTypes := []btcscript.SigHashType{
btcscript.SigHashOld, // no longer used but should act like all btcscript.SigHashOld, // no longer used but should act like all
btcscript.SigHashAll, btcscript.SigHashAll,
btcscript.SigHashNone, btcscript.SigHashNone,