mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-07 14:46:44 +00:00
[NOD-224] Make P2PK and raw Multisig non-standard (#332)
This commit is contained in:
parent
f7f44995d6
commit
c14c64d534
@ -528,12 +528,6 @@ func addrToKey(addr util.Address) ([addrKeySize]byte, error) {
|
||||
result[0] = addrKeyTypeScriptHash
|
||||
copy(result[1:], addr.Hash160()[:])
|
||||
return result, nil
|
||||
|
||||
case *util.AddressPubKey:
|
||||
var result [addrKeySize]byte
|
||||
result[0] = addrKeyTypePubKeyHash
|
||||
copy(result[1:], addr.AddressPubKeyHash().Hash160()[:])
|
||||
return result, nil
|
||||
}
|
||||
|
||||
return [addrKeySize]byte{}, errUnsupportedAddressType
|
||||
|
@ -11,9 +11,9 @@ func decodeKeys(cfg *config) (*btcec.PrivateKey, *util.AddressPubKeyHash, error)
|
||||
privateKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), privateKeyBytes)
|
||||
serializedPrivateKey := privateKey.PubKey().SerializeCompressed()
|
||||
|
||||
pubKeyAddr, err := util.NewAddressPubKey(serializedPrivateKey, activeNetParams.Prefix)
|
||||
addr, err := util.NewAddressPubKeyHashFromPublicKey(serializedPrivateKey, activeNetParams.Prefix)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return privateKey, pubKeyAddr.AddressPubKeyHash(), nil
|
||||
return privateKey, addr, nil
|
||||
}
|
||||
|
@ -18,12 +18,10 @@ func main() {
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Printf("\nPrivate key (base-58): %s\n", base58.Encode(privateKey.Serialize()))
|
||||
serializedKey := privateKey.PubKey().SerializeCompressed()
|
||||
pubKeyAddr, err := util.NewAddressPubKey(serializedKey, activeNetParams.Prefix)
|
||||
addr, err := util.NewAddressPubKeyHash(privateKey.PubKey().SerializeCompressed(), activeNetParams.Prefix)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to generate public key address: %s", err)
|
||||
fmt.Fprintf(os.Stderr, "Failed to generate p2pkh address: %s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
addr := pubKeyAddr.AddressPubKeyHash()
|
||||
fmt.Printf("Public key: %s\n\n", addr)
|
||||
}
|
||||
|
@ -19,12 +19,7 @@ var (
|
||||
|
||||
// privateKeyToP2pkhAddress generates p2pkh address from private key.
|
||||
func privateKeyToP2pkhAddress(key *btcec.PrivateKey, net *dagconfig.Params) (util.Address, error) {
|
||||
serializedKey := key.PubKey().SerializeCompressed()
|
||||
pubKeyAddr, err := util.NewAddressPubKey(serializedKey, net.Prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pubKeyAddr.AddressPubKeyHash(), nil
|
||||
return util.NewAddressPubKeyHashFromPublicKey(key.PubKey().SerializeCompressed(), net.Prefix)
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
@ -522,9 +522,5 @@ func (m *memWallet) ConfirmedBalance() util.Amount {
|
||||
// keyToAddr maps the passed private to corresponding p2pkh address.
|
||||
func keyToAddr(key *btcec.PrivateKey, net *dagconfig.Params) (util.Address, error) {
|
||||
serializedKey := key.PubKey().SerializeCompressed()
|
||||
pubKeyAddr, err := util.NewAddressPubKey(serializedKey, net.Prefix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pubKeyAddr.AddressPubKeyHash(), nil
|
||||
return util.NewAddressPubKeyHashFromPublicKey(serializedKey, net.Prefix)
|
||||
}
|
||||
|
@ -49,11 +49,6 @@ const (
|
||||
// considered dust and as a base for calculating minimum required fees
|
||||
// for larger transactions. This value is in Satoshi/1000 bytes.
|
||||
DefaultMinRelayTxFee = util.Amount(1000)
|
||||
|
||||
// maxStandardMultiSigKeys is the maximum number of public keys allowed
|
||||
// in a multi-signature transaction output script for it to be
|
||||
// considered standard.
|
||||
maxStandardMultiSigKeys = 3
|
||||
)
|
||||
|
||||
// calcMinRequiredTxRelayFee returns the minimum transaction fee required for a
|
||||
@ -118,56 +113,6 @@ func checkInputsStandard(tx *util.Tx, utxoSet blockdag.UTXOSet) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkPkScriptStandard performs a series of checks on a transaction output
|
||||
// script (public key script) to ensure it is a "standard" public key script.
|
||||
// A standard public key script is one that is a recognized form, and for
|
||||
// multi-signature scripts, only contains from 1 to maxStandardMultiSigKeys
|
||||
// public keys.
|
||||
func checkPkScriptStandard(pkScript []byte, scriptClass txscript.ScriptClass) error {
|
||||
switch scriptClass {
|
||||
case txscript.MultiSigTy:
|
||||
numPubKeys, numSigs, err := txscript.CalcMultiSigStats(pkScript)
|
||||
if err != nil {
|
||||
str := fmt.Sprintf("multi-signature script parse "+
|
||||
"failure: %s", err)
|
||||
return txRuleError(wire.RejectNonstandard, str)
|
||||
}
|
||||
|
||||
// A standard multi-signature public key script must contain
|
||||
// from 1 to maxStandardMultiSigKeys public keys.
|
||||
if numPubKeys < 1 {
|
||||
str := "multi-signature script with no pubkeys"
|
||||
return txRuleError(wire.RejectNonstandard, str)
|
||||
}
|
||||
if numPubKeys > maxStandardMultiSigKeys {
|
||||
str := fmt.Sprintf("multi-signature script with %d "+
|
||||
"public keys which is more than the allowed "+
|
||||
"max of %d", numPubKeys, maxStandardMultiSigKeys)
|
||||
return txRuleError(wire.RejectNonstandard, str)
|
||||
}
|
||||
|
||||
// A standard multi-signature public key script must have at
|
||||
// least 1 signature and no more signatures than available
|
||||
// public keys.
|
||||
if numSigs < 1 {
|
||||
return txRuleError(wire.RejectNonstandard,
|
||||
"multi-signature script with no signatures")
|
||||
}
|
||||
if numSigs > numPubKeys {
|
||||
str := fmt.Sprintf("multi-signature script with %d "+
|
||||
"signatures which is more than the available "+
|
||||
"%d public keys", numSigs, numPubKeys)
|
||||
return txRuleError(wire.RejectNonstandard, str)
|
||||
}
|
||||
|
||||
case txscript.NonStandardTy:
|
||||
return txRuleError(wire.RejectNonstandard,
|
||||
"non-standard script form")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// isDust returns whether or not the passed transaction output amount is
|
||||
// considered dust or not based on the passed minimum transaction relay fee.
|
||||
// Dust is defined in terms of the minimum transaction relay fee. In
|
||||
@ -306,17 +251,9 @@ func checkTransactionStandard(tx *util.Tx, blueScore uint64,
|
||||
// be "dust".
|
||||
for i, txOut := range msgTx.TxOut {
|
||||
scriptClass := txscript.GetScriptClass(txOut.PkScript)
|
||||
err := checkPkScriptStandard(txOut.PkScript, scriptClass)
|
||||
if err != nil {
|
||||
// Attempt to extract a reject code from the error so
|
||||
// it can be retained. When not possible, fall back to
|
||||
// a non standard error.
|
||||
rejectCode := wire.RejectNonstandard
|
||||
if rejCode, found := extractRejectCode(err); found {
|
||||
rejectCode = rejCode
|
||||
}
|
||||
str := fmt.Sprintf("transaction output %d: %s", i, err)
|
||||
return txRuleError(rejectCode, str)
|
||||
if scriptClass == txscript.NonStandardTy {
|
||||
str := fmt.Sprintf("transaction output %d: non-standard script form", i)
|
||||
return txRuleError(wire.RejectNonstandard, str)
|
||||
}
|
||||
|
||||
if isDust(txOut, policy.MinRelayTxFee) {
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/daglabs/btcd/btcec"
|
||||
"github.com/daglabs/btcd/txscript"
|
||||
"github.com/daglabs/btcd/util"
|
||||
"github.com/daglabs/btcd/util/daghash"
|
||||
@ -93,116 +92,6 @@ func TestCalcMinRequiredTxRelayFee(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestCheckPkScriptStandard tests the checkPkScriptStandard API.
|
||||
func TestCheckPkScriptStandard(t *testing.T) {
|
||||
var pubKeys [][]byte
|
||||
for i := 0; i < 4; i++ {
|
||||
pk, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Fatalf("TestCheckPkScriptStandard NewPrivateKey failed: %v",
|
||||
err)
|
||||
return
|
||||
}
|
||||
pubKeys = append(pubKeys, pk.PubKey().SerializeCompressed())
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string // test description.
|
||||
script *txscript.ScriptBuilder
|
||||
isStandard bool
|
||||
}{
|
||||
{
|
||||
"key1 and key2",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op2).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddOp(txscript.Op2).AddOp(txscript.OpCheckMultiSig),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"key1 or key2",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op1).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddOp(txscript.Op2).AddOp(txscript.OpCheckMultiSig),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"escrow",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op2).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddData(pubKeys[2]).
|
||||
AddOp(txscript.Op3).AddOp(txscript.OpCheckMultiSig),
|
||||
true,
|
||||
},
|
||||
{
|
||||
"one of four",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op1).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddData(pubKeys[2]).AddData(pubKeys[3]).
|
||||
AddOp(txscript.Op4).AddOp(txscript.OpCheckMultiSig),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"malformed1",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op3).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddOp(txscript.Op2).AddOp(txscript.OpCheckMultiSig),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"malformed2",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op2).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddOp(txscript.Op3).AddOp(txscript.OpCheckMultiSig),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"malformed3",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op0).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddOp(txscript.Op2).AddOp(txscript.OpCheckMultiSig),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"malformed4",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op1).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddOp(txscript.Op0).AddOp(txscript.OpCheckMultiSig),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"malformed5",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op1).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]).
|
||||
AddOp(txscript.OpCheckMultiSig),
|
||||
false,
|
||||
},
|
||||
{
|
||||
"malformed6",
|
||||
txscript.NewScriptBuilder().AddOp(txscript.Op1).
|
||||
AddData(pubKeys[0]).AddData(pubKeys[1]),
|
||||
false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
script, err := test.script.Script()
|
||||
if err != nil {
|
||||
t.Fatalf("TestCheckPkScriptStandard test '%s' "+
|
||||
"failed: %v", test.name, err)
|
||||
continue
|
||||
}
|
||||
scriptClass := txscript.GetScriptClass(script)
|
||||
got := checkPkScriptStandard(script, scriptClass)
|
||||
if (test.isStandard && got != nil) ||
|
||||
(!test.isStandard && got == nil) {
|
||||
|
||||
t.Fatalf("TestCheckPkScriptStandard test '%s' failed",
|
||||
test.name)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestDust tests the isDust API.
|
||||
func TestDust(t *testing.T) {
|
||||
pkScript := []byte{0x76, 0xa9, 0x21, 0x03, 0x2f, 0x7e, 0x43,
|
||||
|
@ -3557,7 +3557,7 @@ func handleVerifyMessage(s *Server, cmd interface{}, closeChan <-chan struct{})
|
||||
} else {
|
||||
serializedPK = pk.SerializeUncompressed()
|
||||
}
|
||||
address, err := util.NewAddressPubKey(serializedPK, params.Prefix)
|
||||
address, err := util.NewAddressPubKeyHashFromPublicKey(serializedPK, params.Prefix)
|
||||
if err != nil {
|
||||
// Again mirror Bitcoin Core behavior, which treats error in public key
|
||||
// reconstruction as invalid signature.
|
||||
|
@ -288,20 +288,6 @@ func (f *wsClientFilter) addAddress(a util.Address) {
|
||||
case *util.AddressScriptHash:
|
||||
f.scriptHashes[*a.Hash160()] = struct{}{}
|
||||
return
|
||||
case *util.AddressPubKey:
|
||||
serializedPubKey := a.ScriptAddress()
|
||||
switch len(serializedPubKey) {
|
||||
case 33: // compressed
|
||||
var compressedPubKey [33]byte
|
||||
copy(compressedPubKey[:], serializedPubKey)
|
||||
f.compressedPubKeys[compressedPubKey] = struct{}{}
|
||||
return
|
||||
case 65: // uncompressed
|
||||
var uncompressedPubKey [65]byte
|
||||
copy(uncompressedPubKey[:], serializedPubKey)
|
||||
f.uncompressedPubKeys[uncompressedPubKey] = struct{}{}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
f.otherAddresses[a.EncodeAddress()] = struct{}{}
|
||||
@ -334,26 +320,6 @@ func (f *wsClientFilter) existsAddress(a util.Address) bool {
|
||||
case *util.AddressScriptHash:
|
||||
_, ok := f.scriptHashes[*a.Hash160()]
|
||||
return ok
|
||||
case *util.AddressPubKey:
|
||||
serializedPubKey := a.ScriptAddress()
|
||||
switch len(serializedPubKey) {
|
||||
case 33: // compressed
|
||||
var compressedPubKey [33]byte
|
||||
copy(compressedPubKey[:], serializedPubKey)
|
||||
_, ok := f.compressedPubKeys[compressedPubKey]
|
||||
if !ok {
|
||||
_, ok = f.pubKeyHashes[*a.AddressPubKeyHash().Hash160()]
|
||||
}
|
||||
return ok
|
||||
case 65: // uncompressed
|
||||
var uncompressedPubKey [65]byte
|
||||
copy(uncompressedPubKey[:], serializedPubKey)
|
||||
_, ok := f.uncompressedPubKeys[uncompressedPubKey]
|
||||
if !ok {
|
||||
_, ok = f.pubKeyHashes[*a.AddressPubKeyHash().Hash160()]
|
||||
}
|
||||
return ok
|
||||
}
|
||||
}
|
||||
|
||||
_, ok := f.otherAddresses[a.EncodeAddress()]
|
||||
@ -372,20 +338,6 @@ func (f *wsClientFilter) removeAddress(a util.Address) {
|
||||
case *util.AddressScriptHash:
|
||||
delete(f.scriptHashes, *a.Hash160())
|
||||
return
|
||||
case *util.AddressPubKey:
|
||||
serializedPubKey := a.ScriptAddress()
|
||||
switch len(serializedPubKey) {
|
||||
case 33: // compressed
|
||||
var compressedPubKey [33]byte
|
||||
copy(compressedPubKey[:], serializedPubKey)
|
||||
delete(f.compressedPubKeys, compressedPubKey)
|
||||
return
|
||||
case 65: // uncompressed
|
||||
var uncompressedPubKey [65]byte
|
||||
copy(uncompressedPubKey[:], serializedPubKey)
|
||||
delete(f.uncompressedPubKeys, uncompressedPubKey)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
delete(f.otherAddresses, a.EncodeAddress())
|
||||
|
175
txscript/sign.go
175
txscript/sign.go
@ -56,46 +56,6 @@ func SignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashTyp
|
||||
return NewScriptBuilder().AddData(sig).AddData(pkData).Script()
|
||||
}
|
||||
|
||||
func p2pkSignatureScript(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType, privKey *btcec.PrivateKey) ([]byte, error) {
|
||||
sig, err := RawTxInSignature(tx, idx, script, hashType, privKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewScriptBuilder().AddData(sig).Script()
|
||||
}
|
||||
|
||||
// signMultiSig signs as many of the outputs in the provided multisig script as
|
||||
// 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
|
||||
// legal to not be able to sign any of the outputs, no error is returned.
|
||||
func signMultiSig(tx *wire.MsgTx, idx int, script []byte, hashType SigHashType,
|
||||
addresses []util.Address, nRequired int, kdb KeyDB) ([]byte, bool) {
|
||||
|
||||
builder := NewScriptBuilder()
|
||||
signedCount := 0
|
||||
for _, addr := range addresses {
|
||||
key, _, err := kdb.GetKey(addr)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
sig, err := RawTxInSignature(tx, idx, script, hashType, key)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
builder.AddData(sig)
|
||||
signedCount++
|
||||
if signedCount == nRequired {
|
||||
break
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
signedScript, _ := builder.Script()
|
||||
return signedScript, signedCount == nRequired
|
||||
}
|
||||
|
||||
func sign(chainParams *dagconfig.Params, tx *wire.MsgTx, idx int,
|
||||
script []byte, hashType SigHashType, kdb KeyDB, sdb ScriptDB) ([]byte,
|
||||
ScriptClass, []util.Address, int, error) {
|
||||
@ -107,20 +67,6 @@ func sign(chainParams *dagconfig.Params, tx *wire.MsgTx, idx int,
|
||||
}
|
||||
|
||||
switch class {
|
||||
case PubKeyTy:
|
||||
// look up key for address
|
||||
key, _, err := kdb.GetKey(addresses[0])
|
||||
if err != nil {
|
||||
return nil, class, nil, 0, err
|
||||
}
|
||||
|
||||
signedScript, err := p2pkSignatureScript(tx, idx, script, hashType,
|
||||
key)
|
||||
if err != nil {
|
||||
return nil, class, nil, 0, err
|
||||
}
|
||||
|
||||
return signedScript, class, addresses, nrequired, nil
|
||||
case PubKeyHashTy:
|
||||
// look up key for address
|
||||
key, compressed, err := kdb.GetKey(addresses[0])
|
||||
@ -142,10 +88,6 @@ func sign(chainParams *dagconfig.Params, tx *wire.MsgTx, idx int,
|
||||
}
|
||||
|
||||
return script, class, addresses, nrequired, nil
|
||||
case MultiSigTy:
|
||||
signedScript, _ := signMultiSig(tx, idx, script, hashType,
|
||||
addresses, nrequired, kdb)
|
||||
return signedScript, class, addresses, nrequired, nil
|
||||
default:
|
||||
return nil, class, nil, 0,
|
||||
errors.New("can't sign unknown transactions")
|
||||
@ -203,9 +145,6 @@ func mergeScripts(chainParams *dagconfig.Params, tx *wire.MsgTx, idx int,
|
||||
builder.AddOps(mergedScript)
|
||||
builder.AddData(script)
|
||||
return builder.Script()
|
||||
case MultiSigTy:
|
||||
return mergeMultiSig(tx, idx, addresses, nRequired, pkScript,
|
||||
sigScript, prevScript)
|
||||
|
||||
// It doesn't actually make sense to merge anything other than multiig
|
||||
// and scripthash (because it could contain multisig). Everything else
|
||||
@ -221,120 +160,6 @@ func mergeScripts(chainParams *dagconfig.Params, tx *wire.MsgTx, idx int,
|
||||
}
|
||||
}
|
||||
|
||||
// mergeMultiSig combines the two signature scripts sigScript and prevScript
|
||||
// that both provide signatures for pkScript in output idx of tx. addresses
|
||||
// and nRequired should be the results from extracting the addresses from
|
||||
// pkScript.
|
||||
func mergeMultiSig(tx *wire.MsgTx, idx int, addresses []util.Address,
|
||||
nRequired int, pkScript, sigScript, prevScript []byte) ([]byte, error) {
|
||||
|
||||
pkPops, err := parseScript(pkScript)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
sigPops, err := parseScript(sigScript)
|
||||
if err != nil || len(sigPops) == 0 {
|
||||
return prevScript, nil
|
||||
}
|
||||
|
||||
prevPops, err := parseScript(prevScript)
|
||||
if err != nil || len(prevPops) == 0 {
|
||||
return sigScript, nil
|
||||
}
|
||||
|
||||
// Convenience function to avoid duplication.
|
||||
extractSigs := func(pops []parsedOpcode, sigs [][]byte) [][]byte {
|
||||
for _, pop := range pops {
|
||||
if len(pop.data) != 0 {
|
||||
sigs = append(sigs, pop.data)
|
||||
}
|
||||
}
|
||||
return sigs
|
||||
}
|
||||
|
||||
possibleSigs := make([][]byte, 0, len(sigPops)+len(prevPops))
|
||||
possibleSigs = extractSigs(sigPops, possibleSigs)
|
||||
possibleSigs = extractSigs(prevPops, possibleSigs)
|
||||
|
||||
// Now we need to match the signatures to pubkeys, the only real way to
|
||||
// do that is to try to verify them all and match it to the pubkey
|
||||
// that verifies it. we then can go through the addresses in order
|
||||
// to build our script. Anything that doesn't parse or doesn't verify we
|
||||
// throw away.
|
||||
addrToSig := make(map[string][]byte)
|
||||
sigLoop:
|
||||
for _, sig := range possibleSigs {
|
||||
|
||||
// can't have a valid signature that doesn't at least have a
|
||||
// hashtype, in practise it is even longer than this. but
|
||||
// that'll be checked next.
|
||||
if len(sig) < 1 {
|
||||
continue
|
||||
}
|
||||
tSig := sig[:len(sig)-1]
|
||||
hashType := SigHashType(sig[len(sig)-1])
|
||||
|
||||
pSig, err := btcec.ParseDERSignature(tSig, btcec.S256())
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// We have to do this each round since hash types may vary
|
||||
// between signatures and so the hash will vary. We can,
|
||||
// however, assume no sigs etc are in the script since that
|
||||
// would make the transaction nonstandard and thus not
|
||||
// MultiSigTy, so we just need to hash the full thing.
|
||||
hash, err := calcSignatureHash(pkPops, hashType, tx, idx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, addr := range addresses {
|
||||
// All multisig addresses should be pubkey addresses
|
||||
// it is an error to call this internal function with
|
||||
// bad input.
|
||||
pkaddr := addr.(*util.AddressPubKey)
|
||||
|
||||
pubKey := pkaddr.PubKey()
|
||||
|
||||
// If it matches we put it in the map. We only
|
||||
// can take one signature per public key so if we
|
||||
// already have one, we can throw this away.
|
||||
if pSig.Verify(hash, pubKey) {
|
||||
aStr := addr.EncodeAddress()
|
||||
if _, ok := addrToSig[aStr]; !ok {
|
||||
addrToSig[aStr] = sig
|
||||
}
|
||||
continue sigLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
builder := NewScriptBuilder()
|
||||
doneSigs := 0
|
||||
// This assumes that addresses are in the same order as in the script.
|
||||
for _, addr := range addresses {
|
||||
sig, ok := addrToSig[addr.EncodeAddress()]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
builder.AddData(sig)
|
||||
doneSigs++
|
||||
if doneSigs == nRequired {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// padding for missing ones.
|
||||
for i := doneSigs; i < nRequired; i++ {
|
||||
builder.AddOp(Op0)
|
||||
}
|
||||
|
||||
script, _ := builder.Script()
|
||||
return script, nil
|
||||
}
|
||||
|
||||
// KeyDB is an interface type provided to SignTxOutput, it encapsulates
|
||||
// any user state required to get the private keys for an address.
|
||||
type KeyDB interface {
|
||||
|
@ -331,200 +331,6 @@ func TestSignTxOutput(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (uncompressed)
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
if err := signAndCheck(msg, tx, i, pkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, false},
|
||||
}), mkGetScript(nil), nil); err != nil {
|
||||
t.Error(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (uncompressed)
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
sigScript, err := SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, pkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, false},
|
||||
}), mkGetScript(nil), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg,
|
||||
err)
|
||||
break
|
||||
}
|
||||
|
||||
// by the above loop, this should be valid, now sign
|
||||
// again and merge.
|
||||
sigScript, err = SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, pkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, false},
|
||||
}), mkGetScript(nil), sigScript)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s a "+
|
||||
"second time: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
err = checkScripts(msg, tx, i, sigScript, pkScript)
|
||||
if err != nil {
|
||||
t.Errorf("twice signed script invalid for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (compressed)
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
if err := signAndCheck(msg, tx, i, pkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, true},
|
||||
}), mkGetScript(nil), nil); err != nil {
|
||||
t.Error(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (compressed) with duplicate merge
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
sigScript, err := SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, pkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, true},
|
||||
}), mkGetScript(nil), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg,
|
||||
err)
|
||||
break
|
||||
}
|
||||
|
||||
// by the above loop, this should be valid, now sign
|
||||
// again and merge.
|
||||
sigScript, err = SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, pkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, true},
|
||||
}), mkGetScript(nil), sigScript)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s a "+
|
||||
"second time: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
err = checkScripts(msg, tx, i, sigScript, pkScript)
|
||||
if err != nil {
|
||||
t.Errorf("twice signed script invalid for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// As before, but with p2sh now.
|
||||
// Pay to Pubkey Hash (uncompressed)
|
||||
for _, hashType := range hashTypes {
|
||||
@ -799,551 +605,6 @@ func TestSignTxOutput(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (uncompressed)
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
scriptAddr, err := util.NewAddressScriptHash(
|
||||
pkScript, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make p2sh addr for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
scriptPkScript, err := PayToAddrScript(
|
||||
scriptAddr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make script pkscript for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
if err := signAndCheck(msg, tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, false},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil); err != nil {
|
||||
t.Error(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (uncompressed) with duplicate merge
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeUncompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
scriptAddr, err := util.NewAddressScriptHash(
|
||||
pkScript, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make p2sh addr for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
scriptPkScript, err := PayToAddrScript(scriptAddr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make script pkscript for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
sigScript, err := SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, false},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg,
|
||||
err)
|
||||
break
|
||||
}
|
||||
|
||||
// by the above loop, this should be valid, now sign
|
||||
// again and merge.
|
||||
sigScript, err = SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, false},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s a "+
|
||||
"second time: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
|
||||
if err != nil {
|
||||
t.Errorf("twice signed script invalid for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (compressed)
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
scriptAddr, err := util.NewAddressScriptHash(
|
||||
pkScript, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make p2sh addr for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
scriptPkScript, err := PayToAddrScript(scriptAddr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make script pkscript for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
if err := signAndCheck(msg, tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil); err != nil {
|
||||
t.Error(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pay to PubKey (compressed)
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk := (*btcec.PublicKey)(&key.PublicKey).
|
||||
SerializeCompressed()
|
||||
address, err := util.NewAddressPubKey(pk, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := PayToAddrScript(address)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
scriptAddr, err := util.NewAddressScriptHash(
|
||||
pkScript, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make p2sh addr for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
scriptPkScript, err := PayToAddrScript(scriptAddr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make script pkscript for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
sigScript, err := SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg,
|
||||
err)
|
||||
break
|
||||
}
|
||||
|
||||
// by the above loop, this should be valid, now sign
|
||||
// again and merge.
|
||||
sigScript, err = SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address.EncodeAddress(): {key, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s a "+
|
||||
"second time: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
|
||||
if err != nil {
|
||||
t.Errorf("twice signed script invalid for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Basic Multisig
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key1, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk1 := (*btcec.PublicKey)(&key1.PublicKey).
|
||||
SerializeCompressed()
|
||||
address1, err := util.NewAddressPubKey(pk1, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
key2, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey 2 for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk2 := (*btcec.PublicKey)(&key2.PublicKey).
|
||||
SerializeCompressed()
|
||||
address2, err := util.NewAddressPubKey(pk2, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address 2 for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := MultiSigScript(
|
||||
[]*util.AddressPubKey{address1, address2},
|
||||
2)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
scriptAddr, err := util.NewAddressScriptHash(
|
||||
pkScript, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make p2sh addr for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
scriptPkScript, err := PayToAddrScript(scriptAddr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make script pkscript for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
if err := signAndCheck(msg, tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address1.EncodeAddress(): {key1, true},
|
||||
address2.EncodeAddress(): {key2, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil); err != nil {
|
||||
t.Error(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Two part multisig, sign with one key then the other.
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key1, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk1 := (*btcec.PublicKey)(&key1.PublicKey).
|
||||
SerializeCompressed()
|
||||
address1, err := util.NewAddressPubKey(pk1, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
key2, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey 2 for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk2 := (*btcec.PublicKey)(&key2.PublicKey).
|
||||
SerializeCompressed()
|
||||
address2, err := util.NewAddressPubKey(pk2, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address 2 for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := MultiSigScript(
|
||||
[]*util.AddressPubKey{address1, address2},
|
||||
2)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
scriptAddr, err := util.NewAddressScriptHash(
|
||||
pkScript, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make p2sh addr for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
scriptPkScript, err := PayToAddrScript(scriptAddr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make script pkscript for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
sigScript, err := SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address1.EncodeAddress(): {key1, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg,
|
||||
err)
|
||||
break
|
||||
}
|
||||
|
||||
// Only 1 out of 2 signed, this *should* fail.
|
||||
if checkScripts(msg, tx, i, sigScript, scriptPkScript) == nil {
|
||||
t.Errorf("part signed script valid for %s", msg)
|
||||
break
|
||||
}
|
||||
|
||||
// Sign with the other key and merge
|
||||
sigScript, err = SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address2.EncodeAddress(): {key2, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), sigScript)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
|
||||
if err != nil {
|
||||
t.Errorf("fully signed script invalid for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Two part multisig, sign with one key then both, check key dedup
|
||||
// correctly.
|
||||
for _, hashType := range hashTypes {
|
||||
for i := range tx.TxIn {
|
||||
msg := fmt.Sprintf("%d:%d", hashType, i)
|
||||
|
||||
key1, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk1 := (*btcec.PublicKey)(&key1.PublicKey).
|
||||
SerializeCompressed()
|
||||
address1, err := util.NewAddressPubKey(pk1, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
key2, err := btcec.NewPrivateKey(btcec.S256())
|
||||
if err != nil {
|
||||
t.Errorf("failed to make privKey 2 for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pk2 := (*btcec.PublicKey)(&key2.PublicKey).
|
||||
SerializeCompressed()
|
||||
address2, err := util.NewAddressPubKey(pk2, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make address 2 for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
pkScript, err := MultiSigScript(
|
||||
[]*util.AddressPubKey{address1, address2},
|
||||
2)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make pkscript "+
|
||||
"for %s: %v", msg, err)
|
||||
}
|
||||
|
||||
scriptAddr, err := util.NewAddressScriptHash(
|
||||
pkScript, util.Bech32PrefixDAGTest)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make p2sh addr for %s: %v",
|
||||
msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
scriptPkScript, err := PayToAddrScript(scriptAddr)
|
||||
if err != nil {
|
||||
t.Errorf("failed to make script pkscript for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
sigScript, err := SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address1.EncodeAddress(): {key1, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg,
|
||||
err)
|
||||
break
|
||||
}
|
||||
|
||||
// Only 1 out of 2 signed, this *should* fail.
|
||||
if checkScripts(msg, tx, i, sigScript, scriptPkScript) == nil {
|
||||
t.Errorf("part signed script valid for %s", msg)
|
||||
break
|
||||
}
|
||||
|
||||
// Sign with the other key and merge
|
||||
sigScript, err = SignTxOutput(&dagconfig.TestNet3Params,
|
||||
tx, i, scriptPkScript, hashType,
|
||||
mkGetKey(map[string]addressToKey{
|
||||
address1.EncodeAddress(): {key1, true},
|
||||
address2.EncodeAddress(): {key2, true},
|
||||
}), mkGetScript(map[string][]byte{
|
||||
scriptAddr.EncodeAddress(): pkScript,
|
||||
}), sigScript)
|
||||
if err != nil {
|
||||
t.Errorf("failed to sign output %s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
|
||||
// Now we should pass.
|
||||
err = checkScripts(msg, tx, i, sigScript, scriptPkScript)
|
||||
if err != nil {
|
||||
t.Errorf("fully signed script invalid for "+
|
||||
"%s: %v", msg, err)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type tstInput struct {
|
||||
|
@ -31,20 +31,16 @@ type ScriptClass byte
|
||||
// Classes of script payment known about in the blockDAG.
|
||||
const (
|
||||
NonStandardTy ScriptClass = iota // None of the recognized forms.
|
||||
PubKeyTy // Pay pubkey.
|
||||
PubKeyHashTy // Pay pubkey hash.
|
||||
ScriptHashTy // Pay to script hash.
|
||||
MultiSigTy // Multi signature.
|
||||
)
|
||||
|
||||
// scriptClassToName houses the human-readable strings which describe each
|
||||
// script class.
|
||||
var scriptClassToName = []string{
|
||||
NonStandardTy: "nonstandard",
|
||||
PubKeyTy: "pubkey",
|
||||
PubKeyHashTy: "pubkeyhash",
|
||||
ScriptHashTy: "scripthash",
|
||||
MultiSigTy: "multisig",
|
||||
}
|
||||
|
||||
// String implements the Stringer interface by returning the name of
|
||||
@ -57,15 +53,6 @@ func (t ScriptClass) String() string {
|
||||
return scriptClassToName[t]
|
||||
}
|
||||
|
||||
// isPubkey returns true if the script passed is a pay-to-pubkey transaction,
|
||||
// false otherwise.
|
||||
func isPubkey(pops []parsedOpcode) bool {
|
||||
// Valid pubkeys are either 33 or 65 bytes.
|
||||
return len(pops) == 2 &&
|
||||
(len(pops[0].data) == 33 || len(pops[0].data) == 65) &&
|
||||
pops[1].opcode.value == OpCheckSig
|
||||
}
|
||||
|
||||
// isPubkeyHash returns true if the script passed is a pay-to-pubkey-hash
|
||||
// transaction, false otherwise.
|
||||
func isPubkeyHash(pops []parsedOpcode) bool {
|
||||
@ -78,51 +65,13 @@ func isPubkeyHash(pops []parsedOpcode) bool {
|
||||
|
||||
}
|
||||
|
||||
// isMultiSig returns true if the passed script is a multisig transaction, false
|
||||
// otherwise.
|
||||
func isMultiSig(pops []parsedOpcode) bool {
|
||||
// The absolute minimum is 1 pubkey:
|
||||
// OP_0/OP_1-16 <pubkey> OP_1 OP_CHECKMULTISIG
|
||||
l := len(pops)
|
||||
if l < 4 {
|
||||
return false
|
||||
}
|
||||
if !isSmallInt(pops[0].opcode) {
|
||||
return false
|
||||
}
|
||||
if !isSmallInt(pops[l-2].opcode) {
|
||||
return false
|
||||
}
|
||||
if pops[l-1].opcode.value != OpCheckMultiSig {
|
||||
return false
|
||||
}
|
||||
|
||||
// Verify the number of pubkeys specified matches the actual number
|
||||
// of pubkeys provided.
|
||||
if l-2-1 != asSmallInt(pops[l-2].opcode) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, pop := range pops[1 : l-2] {
|
||||
// Valid pubkeys are either 33 or 65 bytes.
|
||||
if len(pop.data) != 33 && len(pop.data) != 65 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// scriptType returns the type of the script being inspected from the known
|
||||
// standard types.
|
||||
func typeOfScript(pops []parsedOpcode) ScriptClass {
|
||||
if isPubkey(pops) {
|
||||
return PubKeyTy
|
||||
} else if isPubkeyHash(pops) {
|
||||
if isPubkeyHash(pops) {
|
||||
return PubKeyHashTy
|
||||
} else if isScriptHash(pops) {
|
||||
return ScriptHashTy
|
||||
} else if isMultiSig(pops) {
|
||||
return MultiSigTy
|
||||
}
|
||||
return NonStandardTy
|
||||
}
|
||||
@ -145,8 +94,6 @@ func GetScriptClass(script []byte) ScriptClass {
|
||||
// while finding out the type).
|
||||
func expectedInputs(pops []parsedOpcode, class ScriptClass) int {
|
||||
switch class {
|
||||
case PubKeyTy:
|
||||
return 1
|
||||
|
||||
case PubKeyHashTy:
|
||||
return 2
|
||||
@ -155,16 +102,6 @@ func expectedInputs(pops []parsedOpcode, class ScriptClass) int {
|
||||
// Not including script. That is handled by the caller.
|
||||
return 1
|
||||
|
||||
case MultiSigTy:
|
||||
// Standard multisig has a push a small number for the number
|
||||
// of sigs and number of keys. Check the first push instruction
|
||||
// to see how many arguments are expected. typeOfScript already
|
||||
// checked this so we know it'll be a small int. Also, due to
|
||||
// the original bitcoind bug where OP_CHECKMULTISIG pops an
|
||||
// additional item from the stack, add an extra expected input
|
||||
// for the extra push that is required to compensate.
|
||||
return asSmallInt(pops[0].opcode) + 1
|
||||
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
@ -242,32 +179,6 @@ func CalcScriptInfo(sigScript, pkScript []byte, isP2SH bool) (*ScriptInfo, error
|
||||
return si, nil
|
||||
}
|
||||
|
||||
// CalcMultiSigStats returns the number of public keys and signatures from
|
||||
// a multi-signature transaction script. The passed script MUST already be
|
||||
// known to be a multi-signature script.
|
||||
func CalcMultiSigStats(script []byte) (int, int, error) {
|
||||
pops, err := parseScript(script)
|
||||
if err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
// A multi-signature script is of the pattern:
|
||||
// NUM_SIGS PUBKEY PUBKEY PUBKEY... NUM_PUBKEYS OP_CHECKMULTISIG
|
||||
// Therefore the number of signatures is the oldest item on the stack
|
||||
// and the number of pubkeys is the 2nd to last. Also, the absolute
|
||||
// minimum for a multi-signature script is 1 pubkey, so at least 4
|
||||
// items must be on the stack per:
|
||||
// OP_1 PUBKEY OP_1 OP_CHECKMULTISIG
|
||||
if len(pops) < 4 {
|
||||
str := fmt.Sprintf("script %x is not a multisig script", script)
|
||||
return 0, 0, scriptError(ErrNotMultisigScript, str)
|
||||
}
|
||||
|
||||
numSigs := asSmallInt(pops[0].opcode)
|
||||
numPubKeys := asSmallInt(pops[len(pops)-2].opcode)
|
||||
return numPubKeys, numSigs, nil
|
||||
}
|
||||
|
||||
// payToPubKeyHashScript creates a new script to pay a transaction
|
||||
// output to a 20-byte pubkey hash. It is expected that the input is a valid
|
||||
// hash.
|
||||
@ -310,13 +221,6 @@ func PayToAddrScript(addr util.Address) ([]byte, error) {
|
||||
nilAddrErrStr)
|
||||
}
|
||||
return payToScriptHashScript(addr.ScriptAddress())
|
||||
|
||||
case *util.AddressPubKey:
|
||||
if addr == nil {
|
||||
return nil, scriptError(ErrUnsupportedAddress,
|
||||
nilAddrErrStr)
|
||||
}
|
||||
return payToPubKeyScript(addr.ScriptAddress())
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("unable to generate payment script for unsupported "+
|
||||
@ -348,28 +252,6 @@ func PayToScriptHashSignatureScript(redeemScript []byte, signature []byte) ([]by
|
||||
return signatureScript, nil
|
||||
}
|
||||
|
||||
// MultiSigScript returns a valid script for a multisignature redemption where
|
||||
// nrequired of the keys in pubkeys are required to have signed the transaction
|
||||
// for success. An Error with the error code ErrTooManyRequiredSigs will be
|
||||
// returned if nrequired is larger than the number of keys provided.
|
||||
func MultiSigScript(pubkeys []*util.AddressPubKey, nrequired int) ([]byte, error) {
|
||||
if len(pubkeys) < nrequired {
|
||||
str := fmt.Sprintf("unable to generate multisig script with "+
|
||||
"%d required signatures when there are only %d public "+
|
||||
"keys available", nrequired, len(pubkeys))
|
||||
return nil, scriptError(ErrTooManyRequiredSigs, str)
|
||||
}
|
||||
|
||||
builder := NewScriptBuilder().AddInt64(int64(nrequired))
|
||||
for _, key := range pubkeys {
|
||||
builder.AddData(key.ScriptAddress())
|
||||
}
|
||||
builder.AddInt64(int64(len(pubkeys)))
|
||||
builder.AddOp(OpCheckMultiSig)
|
||||
|
||||
return builder.Script()
|
||||
}
|
||||
|
||||
// PushedData returns an array of byte slices containing any pushed data found
|
||||
// in the passed script. This includes OP_0, but not OP_1 - OP_16.
|
||||
func PushedData(script []byte) ([][]byte, error) {
|
||||
@ -418,17 +300,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *dagconfig.Params) (Scrip
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
|
||||
case PubKeyTy:
|
||||
// A pay-to-pubkey script is of the form:
|
||||
// <pubkey> OP_CHECKSIG
|
||||
// Therefore the pubkey is the first item on the stack.
|
||||
// Skip the pubkey if it's invalid for some reason.
|
||||
requiredSigs = 1
|
||||
addr, err := util.NewAddressPubKey(pops[0].data, chainParams.Prefix)
|
||||
if err == nil {
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
|
||||
case ScriptHashTy:
|
||||
// A pay-to-script-hash script is of the form:
|
||||
// OP_HASH160 <scripthash> OP_EQUAL
|
||||
@ -441,24 +312,6 @@ func ExtractPkScriptAddrs(pkScript []byte, chainParams *dagconfig.Params) (Scrip
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
|
||||
case MultiSigTy:
|
||||
// A multi-signature script is of the form:
|
||||
// <numsigs> <pubkey> <pubkey> <pubkey>... <numpubkeys> OP_CHECKMULTISIG
|
||||
// Therefore the number of required signatures is the 1st item
|
||||
// on the stack and the number of public keys is the 2nd to last
|
||||
// item on the stack.
|
||||
requiredSigs = asSmallInt(pops[0].opcode)
|
||||
numPubKeys := asSmallInt(pops[len(pops)-2].opcode)
|
||||
|
||||
// Extract the public keys while skipping any that are invalid.
|
||||
addrs = make([]util.Address, 0, numPubKeys)
|
||||
for i := 0; i < numPubKeys; i++ {
|
||||
addr, err := util.NewAddressPubKey(pops[i+1].data, chainParams.Prefix)
|
||||
if err == nil {
|
||||
addrs = append(addrs, addr)
|
||||
}
|
||||
}
|
||||
|
||||
case NonStandardTy:
|
||||
// Don't attempt to extract addresses or required signatures for
|
||||
// nonstandard transactions.
|
||||
|
@ -27,19 +27,6 @@ func mustParseShortForm(script string) []byte {
|
||||
return s
|
||||
}
|
||||
|
||||
// newAddressPubKey returns a new util.AddressPubKey from the provided
|
||||
// serialized public key. It panics if an error occurs. This is only used in
|
||||
// the tests as a helper since the only way it can fail is if there is an error
|
||||
// in the test source code.
|
||||
func newAddressPubKey(serializedPubKey []byte) util.Address {
|
||||
addr, err := util.NewAddressPubKey(serializedPubKey, util.Bech32PrefixDAGCoin)
|
||||
if err != nil {
|
||||
panic("invalid public key in test source")
|
||||
}
|
||||
|
||||
return addr
|
||||
}
|
||||
|
||||
// newAddressPubKeyHash returns a new util.AddressPubKeyHash from the
|
||||
// provided hash. It panics if an error occurs. This is only used in the tests
|
||||
// as a helper since the only way it can fail is if there is an error in the
|
||||
@ -79,94 +66,6 @@ func TestExtractPkScriptAddrs(t *testing.T) {
|
||||
reqSigs int
|
||||
class ScriptClass
|
||||
}{
|
||||
{
|
||||
name: "standard p2pk with compressed pubkey (0x02)",
|
||||
script: hexToBytes("2102192d74d0cb94344c9569c2e779015" +
|
||||
"73d8d7903c3ebec3a957724895dca52c6b4ac"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("02192d74d0cb9434" +
|
||||
"4c9569c2e77901573d8d7903c3ebec3a9577" +
|
||||
"24895dca52c6b4")),
|
||||
},
|
||||
reqSigs: 1,
|
||||
class: PubKeyTy,
|
||||
},
|
||||
{
|
||||
name: "standard p2pk with uncompressed pubkey (0x04)",
|
||||
script: hexToBytes("410411db93e1dcdb8a016b49840f8c53b" +
|
||||
"c1eb68a382e97b1482ecad7b148a6909a5cb2e0eaddf" +
|
||||
"b84ccf9744464f82e160bfa9b8b64f9d4c03f999b864" +
|
||||
"3f656b412a3ac"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("0411db93e1dcdb8a" +
|
||||
"016b49840f8c53bc1eb68a382e97b1482eca" +
|
||||
"d7b148a6909a5cb2e0eaddfb84ccf9744464" +
|
||||
"f82e160bfa9b8b64f9d4c03f999b8643f656" +
|
||||
"b412a3")),
|
||||
},
|
||||
reqSigs: 1,
|
||||
class: PubKeyTy,
|
||||
},
|
||||
{
|
||||
name: "standard p2pk with hybrid pubkey (0x06)",
|
||||
script: hexToBytes("4106192d74d0cb94344c9569c2e779015" +
|
||||
"73d8d7903c3ebec3a957724895dca52c6b40d4526483" +
|
||||
"8c0bd96852662ce6a847b197376830160c6d2eb5e6a4" +
|
||||
"c44d33f453eac"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("06192d74d0cb9434" +
|
||||
"4c9569c2e77901573d8d7903c3ebec3a9577" +
|
||||
"24895dca52c6b40d45264838c0bd96852662" +
|
||||
"ce6a847b197376830160c6d2eb5e6a4c44d3" +
|
||||
"3f453e")),
|
||||
},
|
||||
reqSigs: 1,
|
||||
class: PubKeyTy,
|
||||
},
|
||||
{
|
||||
name: "standard p2pk with compressed pubkey (0x03)",
|
||||
script: hexToBytes("2103b0bd634234abbb1ba1e986e884185" +
|
||||
"c61cf43e001f9137f23c2c409273eb16e65ac"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("03b0bd634234abbb" +
|
||||
"1ba1e986e884185c61cf43e001f9137f23c2" +
|
||||
"c409273eb16e65")),
|
||||
},
|
||||
reqSigs: 1,
|
||||
class: PubKeyTy,
|
||||
},
|
||||
{
|
||||
name: "2nd standard p2pk with uncompressed pubkey (0x04)",
|
||||
script: hexToBytes("4104b0bd634234abbb1ba1e986e884185" +
|
||||
"c61cf43e001f9137f23c2c409273eb16e6537a576782" +
|
||||
"eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3" +
|
||||
"c1e0908ef7bac"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("04b0bd634234abbb" +
|
||||
"1ba1e986e884185c61cf43e001f9137f23c2" +
|
||||
"c409273eb16e6537a576782eba668a7ef8bd" +
|
||||
"3b3cfb1edb7117ab65129b8a2e681f3c1e09" +
|
||||
"08ef7b")),
|
||||
},
|
||||
reqSigs: 1,
|
||||
class: PubKeyTy,
|
||||
},
|
||||
{
|
||||
name: "standard p2pk with hybrid pubkey (0x07)",
|
||||
script: hexToBytes("4107b0bd634234abbb1ba1e986e884185" +
|
||||
"c61cf43e001f9137f23c2c409273eb16e6537a576782" +
|
||||
"eba668a7ef8bd3b3cfb1edb7117ab65129b8a2e681f3" +
|
||||
"c1e0908ef7bac"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("07b0bd634234abbb" +
|
||||
"1ba1e986e884185c61cf43e001f9137f23c2" +
|
||||
"c409273eb16e6537a576782eba668a7ef8bd" +
|
||||
"3b3cfb1edb7117ab65129b8a2e681f3c1e09" +
|
||||
"08ef7b")),
|
||||
},
|
||||
reqSigs: 1,
|
||||
class: PubKeyTy,
|
||||
},
|
||||
{
|
||||
name: "standard p2pkh",
|
||||
script: hexToBytes("76a914ad06dd6ddee55cbca9a9e3713bd" +
|
||||
@ -189,64 +88,6 @@ func TestExtractPkScriptAddrs(t *testing.T) {
|
||||
reqSigs: 1,
|
||||
class: ScriptHashTy,
|
||||
},
|
||||
// from real tx 60a20bd93aa49ab4b28d514ec10b06e1829ce6818ec06cd3aabd013ebcdc4bb1, vout 0
|
||||
{
|
||||
name: "standard 1 of 2 multisig",
|
||||
script: hexToBytes("514104cc71eb30d653c0c3163990c47b9" +
|
||||
"76f3fb3f37cccdcbedb169a1dfef58bbfbfaff7d8a47" +
|
||||
"3e7e2e6d317b87bafe8bde97e3cf8f065dec022b51d1" +
|
||||
"1fcdd0d348ac4410461cbdcc5409fb4b4d42b51d3338" +
|
||||
"1354d80e550078cb532a34bfa2fcfdeb7d76519aecc6" +
|
||||
"2770f5b0e4ef8551946d8a540911abe3e7854a26f39f" +
|
||||
"58b25c15342af52ae"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("04cc71eb30d653c0" +
|
||||
"c3163990c47b976f3fb3f37cccdcbedb169a" +
|
||||
"1dfef58bbfbfaff7d8a473e7e2e6d317b87b" +
|
||||
"afe8bde97e3cf8f065dec022b51d11fcdd0d" +
|
||||
"348ac4")),
|
||||
newAddressPubKey(hexToBytes("0461cbdcc5409fb4" +
|
||||
"b4d42b51d33381354d80e550078cb532a34b" +
|
||||
"fa2fcfdeb7d76519aecc62770f5b0e4ef855" +
|
||||
"1946d8a540911abe3e7854a26f39f58b25c1" +
|
||||
"5342af")),
|
||||
},
|
||||
reqSigs: 1,
|
||||
class: MultiSigTy,
|
||||
},
|
||||
// from real tx d646f82bd5fbdb94a36872ce460f97662b80c3050ad3209bef9d1e398ea277ab, vin 1
|
||||
{
|
||||
name: "standard 2 of 3 multisig",
|
||||
script: hexToBytes("524104cb9c3c222c5f7a7d3b9bd152f36" +
|
||||
"3a0b6d54c9eb312c4d4f9af1e8551b6c421a6a4ab0e2" +
|
||||
"9105f24de20ff463c1c91fcf3bf662cdde4783d4799f" +
|
||||
"787cb7c08869b4104ccc588420deeebea22a7e900cc8" +
|
||||
"b68620d2212c374604e3487ca08f1ff3ae12bdc63951" +
|
||||
"4d0ec8612a2d3c519f084d9a00cbbe3b53d071e9b09e" +
|
||||
"71e610b036aa24104ab47ad1939edcb3db65f7fedea6" +
|
||||
"2bbf781c5410d3f22a7a3a56ffefb2238af8627363bd" +
|
||||
"f2ed97c1f89784a1aecdb43384f11d2acc64443c7fc2" +
|
||||
"99cef0400421a53ae"),
|
||||
addrs: []util.Address{
|
||||
newAddressPubKey(hexToBytes("04cb9c3c222c5f7a" +
|
||||
"7d3b9bd152f363a0b6d54c9eb312c4d4f9af" +
|
||||
"1e8551b6c421a6a4ab0e29105f24de20ff46" +
|
||||
"3c1c91fcf3bf662cdde4783d4799f787cb7c" +
|
||||
"08869b")),
|
||||
newAddressPubKey(hexToBytes("04ccc588420deeeb" +
|
||||
"ea22a7e900cc8b68620d2212c374604e3487" +
|
||||
"ca08f1ff3ae12bdc639514d0ec8612a2d3c5" +
|
||||
"19f084d9a00cbbe3b53d071e9b09e71e610b" +
|
||||
"036aa2")),
|
||||
newAddressPubKey(hexToBytes("04ab47ad1939edcb" +
|
||||
"3db65f7fedea62bbf781c5410d3f22a7a3a5" +
|
||||
"6ffefb2238af8627363bdf2ed97c1f89784a" +
|
||||
"1aecdb43384f11d2acc64443c7fc299cef04" +
|
||||
"00421a")),
|
||||
},
|
||||
reqSigs: 2,
|
||||
class: MultiSigTy,
|
||||
},
|
||||
|
||||
// The below are nonstandard script due to things such as
|
||||
// invalid pubkeys, failure to parse, and not being of a
|
||||
@ -289,40 +130,6 @@ func TestExtractPkScriptAddrs(t *testing.T) {
|
||||
reqSigs: 0,
|
||||
class: NonStandardTy,
|
||||
},
|
||||
// from real tx 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 0
|
||||
// invalid public keys
|
||||
{
|
||||
name: "1 of 3 multisig with invalid pubkeys",
|
||||
script: hexToBytes("51411c2200007353455857696b696c656" +
|
||||
"16b73204361626c6567617465204261636b75700a0a6" +
|
||||
"361626c65676174652d3230313031323034313831312" +
|
||||
"e377a0a0a446f41776e6c6f61642074686520666f6c6" +
|
||||
"c6f77696e67207472616e73616374696f6e732077697" +
|
||||
"468205361746f736869204e616b616d6f746f2773206" +
|
||||
"46f776e6c6f61416420746f6f6c2077686963680a636" +
|
||||
"16e20626520666f756e6420696e207472616e7361637" +
|
||||
"4696f6e2036633533636439383731313965663739376" +
|
||||
"435616463636453ae"),
|
||||
addrs: []util.Address{},
|
||||
reqSigs: 1,
|
||||
class: MultiSigTy,
|
||||
},
|
||||
// from real tx: 691dd277dc0e90a462a3d652a1171686de49cf19067cd33c7df0392833fb986a, vout 44
|
||||
// invalid public keys
|
||||
{
|
||||
name: "1 of 3 multisig with invalid pubkeys 2",
|
||||
script: hexToBytes("514134633365633235396337346461636" +
|
||||
"536666430383862343463656638630a6336366263313" +
|
||||
"93936633862393461333831316233363536313866653" +
|
||||
"16539623162354136636163636539393361333938386" +
|
||||
"134363966636336643664616266640a3236363363666" +
|
||||
"13963663463303363363039633539336333653931666" +
|
||||
"56465373032392131323364643432643235363339643" +
|
||||
"338613663663530616234636434340a00000053ae"),
|
||||
addrs: []util.Address{},
|
||||
reqSigs: 1,
|
||||
class: MultiSigTy,
|
||||
},
|
||||
{
|
||||
name: "empty script",
|
||||
script: []byte{},
|
||||
@ -437,26 +244,6 @@ func TestCalcScriptInfo(t *testing.T) {
|
||||
SigOps: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
// Script is invented, numbers all fake.
|
||||
name: "multisig script",
|
||||
// Extra 0 arg on the end for OP_CHECKMULTISIG bug.
|
||||
sigScript: "1 1 1 0",
|
||||
pkScript: "3 " +
|
||||
"DATA_33 0x0102030405060708090a0b0c0d0e0f1011" +
|
||||
"12131415161718191a1b1c1d1e1f2021 DATA_33 " +
|
||||
"0x0102030405060708090a0b0c0d0e0f101112131415" +
|
||||
"161718191a1b1c1d1e1f2021 DATA_33 0x010203040" +
|
||||
"5060708090a0b0c0d0e0f101112131415161718191a1" +
|
||||
"b1c1d1e1f2021 3 CHECKMULTISIG",
|
||||
isP2SH: true,
|
||||
scriptInfo: ScriptInfo{
|
||||
PkScriptClass: MultiSigTy,
|
||||
NumInputs: 4,
|
||||
ExpectedInputs: 4,
|
||||
SigOps: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@ -528,29 +315,6 @@ func TestPayToAddrScript(t *testing.T) {
|
||||
t.Fatalf("Unable to create script hash address: %v", err)
|
||||
}
|
||||
|
||||
// mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg
|
||||
p2pkCompressedMain, err := util.NewAddressPubKey(hexToBytes("02192d"+
|
||||
"74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), util.Bech32PrefixDAGCoin)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create pubkey address (compressed): %v",
|
||||
err)
|
||||
}
|
||||
p2pkCompressed2Main, err := util.NewAddressPubKey(hexToBytes("03b0b"+
|
||||
"d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), util.Bech32PrefixDAGCoin)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create pubkey address (compressed 2): %v",
|
||||
err)
|
||||
}
|
||||
|
||||
p2pkUncompressedMain, err := util.NewAddressPubKey(hexToBytes("0411"+
|
||||
"db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+
|
||||
"cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+
|
||||
"12a3"), util.Bech32PrefixDAGCoin)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create pubkey address (uncompressed): %v",
|
||||
err)
|
||||
}
|
||||
|
||||
// Errors used in the tests below defined here for convenience and to
|
||||
// keep the horizontal test size shorter.
|
||||
errUnsupportedAddress := scriptError(ErrUnsupportedAddress, "")
|
||||
@ -574,34 +338,10 @@ func TestPayToAddrScript(t *testing.T) {
|
||||
"6eb5b4 EQUAL",
|
||||
nil,
|
||||
},
|
||||
// pay-to-pubkey address on mainnet. compressed key.
|
||||
{
|
||||
p2pkCompressedMain,
|
||||
"DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c3" +
|
||||
"ebec3a957724895dca52c6b4 CHECKSIG",
|
||||
nil,
|
||||
},
|
||||
// pay-to-pubkey address on mainnet. compressed key (other way).
|
||||
{
|
||||
p2pkCompressed2Main,
|
||||
"DATA_33 0x03b0bd634234abbb1ba1e986e884185c61cf43e001" +
|
||||
"f9137f23c2c409273eb16e65 CHECKSIG",
|
||||
nil,
|
||||
},
|
||||
// pay-to-pubkey address on mainnet. uncompressed key.
|
||||
{
|
||||
p2pkUncompressedMain,
|
||||
"DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" +
|
||||
"97b1482ecad7b148a6909a5cb2e0eaddfb84ccf97444" +
|
||||
"64f82e160bfa9b8b64f9d4c03f999b8643f656b412a3 " +
|
||||
"CHECKSIG",
|
||||
nil,
|
||||
},
|
||||
|
||||
// Supported address types with nil pointers.
|
||||
{(*util.AddressPubKeyHash)(nil), "", errUnsupportedAddress},
|
||||
{(*util.AddressScriptHash)(nil), "", errUnsupportedAddress},
|
||||
{(*util.AddressPubKey)(nil), "", errUnsupportedAddress},
|
||||
|
||||
// Unsupported address type.
|
||||
{&bogusAddress{}, "", errUnsupportedAddress},
|
||||
@ -625,157 +365,6 @@ func TestPayToAddrScript(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestMultiSigScript ensures the MultiSigScript function returns the expected
|
||||
// scripts and errors.
|
||||
func TestMultiSigScript(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// mainnet p2pk 13CG6SJ3yHUXo4Cr2RY4THLLJrNFuG3gUg
|
||||
p2pkCompressedMain, err := util.NewAddressPubKey(hexToBytes("02192d"+
|
||||
"74d0cb94344c9569c2e77901573d8d7903c3ebec3a957724895dca52c6b4"), util.Bech32PrefixDAGCoin)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create pubkey address (compressed): %v",
|
||||
err)
|
||||
}
|
||||
p2pkCompressed2Main, err := util.NewAddressPubKey(hexToBytes("03b0b"+
|
||||
"d634234abbb1ba1e986e884185c61cf43e001f9137f23c2c409273eb16e65"), util.Bech32PrefixDAGCoin)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create pubkey address (compressed 2): %v",
|
||||
err)
|
||||
}
|
||||
|
||||
p2pkUncompressedMain, err := util.NewAddressPubKey(hexToBytes("0411"+
|
||||
"db93e1dcdb8a016b49840f8c53bc1eb68a382e97b1482ecad7b148a6909a5"+
|
||||
"cb2e0eaddfb84ccf9744464f82e160bfa9b8b64f9d4c03f999b8643f656b4"+
|
||||
"12a3"), util.Bech32PrefixDAGCoin)
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create pubkey address (uncompressed): %v",
|
||||
err)
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
keys []*util.AddressPubKey
|
||||
nrequired int
|
||||
expected string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
[]*util.AddressPubKey{
|
||||
p2pkCompressedMain,
|
||||
p2pkCompressed2Main,
|
||||
},
|
||||
1,
|
||||
"1 DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c" +
|
||||
"3ebec3a957724895dca52c6b4 DATA_33 0x03b0bd634" +
|
||||
"234abbb1ba1e986e884185c61cf43e001f9137f23c2c4" +
|
||||
"09273eb16e65 2 CHECKMULTISIG",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
[]*util.AddressPubKey{
|
||||
p2pkCompressedMain,
|
||||
p2pkCompressed2Main,
|
||||
},
|
||||
2,
|
||||
"2 DATA_33 0x02192d74d0cb94344c9569c2e77901573d8d7903c" +
|
||||
"3ebec3a957724895dca52c6b4 DATA_33 0x03b0bd634" +
|
||||
"234abbb1ba1e986e884185c61cf43e001f9137f23c2c4" +
|
||||
"09273eb16e65 2 CHECKMULTISIG",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
[]*util.AddressPubKey{
|
||||
p2pkCompressedMain,
|
||||
p2pkCompressed2Main,
|
||||
},
|
||||
3,
|
||||
"",
|
||||
scriptError(ErrTooManyRequiredSigs, ""),
|
||||
},
|
||||
{
|
||||
[]*util.AddressPubKey{
|
||||
p2pkUncompressedMain,
|
||||
},
|
||||
1,
|
||||
"1 DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382" +
|
||||
"e97b1482ecad7b148a6909a5cb2e0eaddfb84ccf97444" +
|
||||
"64f82e160bfa9b8b64f9d4c03f999b8643f656b412a3 " +
|
||||
"1 CHECKMULTISIG",
|
||||
nil,
|
||||
},
|
||||
{
|
||||
[]*util.AddressPubKey{
|
||||
p2pkUncompressedMain,
|
||||
},
|
||||
2,
|
||||
"",
|
||||
scriptError(ErrTooManyRequiredSigs, ""),
|
||||
},
|
||||
}
|
||||
|
||||
t.Logf("Running %d tests", len(tests))
|
||||
for i, test := range tests {
|
||||
script, err := MultiSigScript(test.keys, test.nrequired)
|
||||
if e := checkScriptError(err, test.err); e != nil {
|
||||
t.Errorf("MultiSigScript #%d: %v", i, e)
|
||||
continue
|
||||
}
|
||||
|
||||
expected := mustParseShortForm(test.expected)
|
||||
if !bytes.Equal(script, expected) {
|
||||
t.Errorf("MultiSigScript #%d got: %x\nwant: %x",
|
||||
i, script, expected)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestCalcMultiSigStats ensures the CalcMutliSigStats function returns the
|
||||
// expected errors.
|
||||
func TestCalcMultiSigStats(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
script string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "short script",
|
||||
script: "0x046708afdb0fe5548271967f1a67130b7105cd6a828" +
|
||||
"e03909a67962e0ea1f61d",
|
||||
err: scriptError(ErrMalformedPush, ""),
|
||||
},
|
||||
{
|
||||
name: "stack underflow",
|
||||
script: "RETURN DATA_41 0x046708afdb0fe5548271967f1a" +
|
||||
"67130b7105cd6a828e03909a67962e0ea1f61deb649f6" +
|
||||
"bc3f4cef308",
|
||||
err: scriptError(ErrNotMultisigScript, ""),
|
||||
},
|
||||
{
|
||||
name: "multisig script",
|
||||
script: "0 DATA_72 0x30450220106a3e4ef0b51b764a2887226" +
|
||||
"2ffef55846514dacbdcbbdd652c849d395b4384022100" +
|
||||
"e03ae554c3cbb40600d31dd46fc33f25e47bf8525b1fe" +
|
||||
"07282e3b6ecb5f3bb2801 1 DATA_33 0x0232abdc893e7f06" +
|
||||
"31364d7fd01cb33d24da45329a00357b3a7886211ab414d55a" +
|
||||
" 1 CHECKMULTISIG",
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for i, test := range tests {
|
||||
script := mustParseShortForm(test.script)
|
||||
_, _, err := CalcMultiSigStats(script)
|
||||
if e := checkScriptError(err, test.err); e != nil {
|
||||
t.Errorf("CalcMultiSigStats #%d (%s): %v", i, test.name,
|
||||
e)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// scriptClassTests houses several test scripts used to ensure various class
|
||||
// determination is working as expected. It's defined as a test global versus
|
||||
// inside a function scope since this spans both the standard tests and the
|
||||
@ -785,12 +374,13 @@ var scriptClassTests = []struct {
|
||||
script string
|
||||
class ScriptClass
|
||||
}{
|
||||
// p2pk. It is standard in BTC but not in DAGCoin
|
||||
{
|
||||
name: "Pay Pubkey",
|
||||
script: "DATA_65 0x0411db93e1dcdb8a016b49840f8c53bc1eb68a382e" +
|
||||
"97b1482ecad7b148a6909a5cb2e0eaddfb84ccf9744464f82e16" +
|
||||
"0bfa9b8b64f9d4c03f999b8643f656b412a3 CHECKSIG",
|
||||
class: PubKeyTy,
|
||||
class: NonStandardTy,
|
||||
},
|
||||
// tx 599e47a8114fe098103663029548811d2651991b62397e057f0c863c2bc9f9ea
|
||||
{
|
||||
@ -799,14 +389,12 @@ var scriptClassTests = []struct {
|
||||
"c271ad504b EQUALVERIFY CHECKSIG",
|
||||
class: PubKeyHashTy,
|
||||
},
|
||||
// part of tx 6d36bc17e947ce00bb6f12f8e7a56a1585c5a36188ffa2b05e10b4743273a74b
|
||||
// codeseparator parts have been elided. (bitcoin core's checks for
|
||||
// multisig type doesn't have codesep either).
|
||||
// mutlisig. It is standard in BTC but not in DAGCoin
|
||||
{
|
||||
name: "multisig",
|
||||
script: "1 DATA_33 0x0232abdc893e7f0631364d7fd01cb33d24da4" +
|
||||
"5329a00357b3a7886211ab414d55a 1 CHECKMULTISIG",
|
||||
class: MultiSigTy,
|
||||
class: NonStandardTy,
|
||||
},
|
||||
// tx e5779b9e78f9650debc2893fd9636d827b26b4ddfa6a8172fe8708c924f5c39d
|
||||
{
|
||||
@ -910,11 +498,6 @@ func TestStringifyClass(t *testing.T) {
|
||||
class: NonStandardTy,
|
||||
stringed: "nonstandard",
|
||||
},
|
||||
{
|
||||
name: "pubkey",
|
||||
class: PubKeyTy,
|
||||
stringed: "pubkey",
|
||||
},
|
||||
{
|
||||
name: "pubkeyhash",
|
||||
class: PubKeyHashTy,
|
||||
@ -925,11 +508,6 @@ func TestStringifyClass(t *testing.T) {
|
||||
class: ScriptHashTy,
|
||||
stringed: "scripthash",
|
||||
},
|
||||
{
|
||||
name: "multisigty",
|
||||
class: MultiSigTy,
|
||||
stringed: "multisig",
|
||||
},
|
||||
{
|
||||
name: "broken",
|
||||
class: ScriptClass(255),
|
||||
|
138
util/address.go
138
util/address.go
@ -5,11 +5,9 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/daglabs/btcd/btcec"
|
||||
"github.com/daglabs/btcd/util/bech32"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
@ -166,6 +164,11 @@ type AddressPubKeyHash struct {
|
||||
hash [ripemd160.Size]byte
|
||||
}
|
||||
|
||||
func NewAddressPubKeyHashFromPublicKey(publicKey []byte, prefix Bech32Prefix) (*AddressPubKeyHash, error) {
|
||||
pkHash := Hash160(publicKey)
|
||||
return newAddressPubKeyHash(prefix, pkHash)
|
||||
}
|
||||
|
||||
// NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash mustbe 20
|
||||
// bytes.
|
||||
func NewAddressPubKeyHash(pkHash []byte, prefix Bech32Prefix) (*AddressPubKeyHash, error) {
|
||||
@ -286,134 +289,3 @@ func (a *AddressScriptHash) String() string {
|
||||
func (a *AddressScriptHash) Hash160() *[ripemd160.Size]byte {
|
||||
return &a.hash
|
||||
}
|
||||
|
||||
// PubKeyFormat describes what format to use for a pay-to-pubkey address.
|
||||
type PubKeyFormat int
|
||||
|
||||
const (
|
||||
// PKFUncompressed indicates the pay-to-pubkey address format is an
|
||||
// uncompressed public key.
|
||||
PKFUncompressed PubKeyFormat = iota
|
||||
|
||||
// PKFCompressed indicates the pay-to-pubkey address format is a
|
||||
// compressed public key.
|
||||
PKFCompressed
|
||||
|
||||
// PKFHybrid indicates the pay-to-pubkey address format is a hybrid
|
||||
// public key.
|
||||
PKFHybrid
|
||||
)
|
||||
|
||||
// AddressPubKey is an Address for a pay-to-pubkey transaction.
|
||||
type AddressPubKey struct {
|
||||
prefix Bech32Prefix
|
||||
pubKeyFormat PubKeyFormat
|
||||
pubKey *btcec.PublicKey
|
||||
pubKeyHashID byte
|
||||
}
|
||||
|
||||
// NewAddressPubKey returns a new AddressPubKey which represents a pay-to-pubkey
|
||||
// address. The serializedPubKey parameter must be a valid pubkey and can be
|
||||
// uncompressed, compressed, or hybrid.
|
||||
func NewAddressPubKey(serializedPubKey []byte, prefix Bech32Prefix) (*AddressPubKey, error) {
|
||||
pubKey, err := btcec.ParsePubKey(serializedPubKey, btcec.S256())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Set the format of the pubkey. This probably should be returned
|
||||
// from btcec, but do it here to avoid API churn. We already know the
|
||||
// pubkey is valid since it parsed above, so it's safe to simply examine
|
||||
// the leading byte to get the format.
|
||||
pkFormat := PKFUncompressed
|
||||
switch serializedPubKey[0] {
|
||||
case 0x02, 0x03:
|
||||
pkFormat = PKFCompressed
|
||||
case 0x06, 0x07:
|
||||
pkFormat = PKFHybrid
|
||||
}
|
||||
|
||||
return &AddressPubKey{
|
||||
pubKeyFormat: pkFormat,
|
||||
pubKey: pubKey,
|
||||
pubKeyHashID: pubKeyHashAddrID,
|
||||
prefix: prefix,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// serialize returns the serialization of the public key according to the
|
||||
// format associated with the address.
|
||||
func (a *AddressPubKey) serialize() []byte {
|
||||
switch a.pubKeyFormat {
|
||||
default:
|
||||
fallthrough
|
||||
case PKFUncompressed:
|
||||
return a.pubKey.SerializeUncompressed()
|
||||
|
||||
case PKFCompressed:
|
||||
return a.pubKey.SerializeCompressed()
|
||||
|
||||
case PKFHybrid:
|
||||
return a.pubKey.SerializeHybrid()
|
||||
}
|
||||
}
|
||||
|
||||
// EncodeAddress returns the string encoding of the public key as a
|
||||
// pay-to-pubkey-hash. Note that the public key format (uncompressed,
|
||||
// compressed, etc) will change the resulting address. This is expected since
|
||||
// pay-to-pubkey-hash is a hash of the serialized public key which obviously
|
||||
// differs with the format. At the time of this writing, most Bitcoin addresses
|
||||
// are pay-to-pubkey-hash constructed from the uncompressed public key.
|
||||
//
|
||||
// Part of the Address interface.
|
||||
func (a *AddressPubKey) EncodeAddress() string {
|
||||
return encodeAddress(a.prefix, Hash160(a.serialize()), a.pubKeyHashID)
|
||||
}
|
||||
|
||||
// ScriptAddress returns the bytes to be included in a txout script to pay
|
||||
// to a public key. Setting the public key format will affect the output of
|
||||
// this function accordingly. Part of the Address interface.
|
||||
func (a *AddressPubKey) ScriptAddress() []byte {
|
||||
return a.serialize()
|
||||
}
|
||||
|
||||
// IsForPrefix returns whether or not the pay-to-pubkey address is associated
|
||||
// with the passed bitcoin network.
|
||||
func (a *AddressPubKey) IsForPrefix(prefix Bech32Prefix) bool {
|
||||
return a.prefix == prefix
|
||||
}
|
||||
|
||||
// String returns the hex-encoded human-readable string for the pay-to-pubkey
|
||||
// address. This is not the same as calling EncodeAddress.
|
||||
func (a *AddressPubKey) String() string {
|
||||
return hex.EncodeToString(a.serialize())
|
||||
}
|
||||
|
||||
// Format returns the format (uncompressed, compressed, etc) of the
|
||||
// pay-to-pubkey address.
|
||||
func (a *AddressPubKey) Format() PubKeyFormat {
|
||||
return a.pubKeyFormat
|
||||
}
|
||||
|
||||
// SetFormat sets the format (uncompressed, compressed, etc) of the
|
||||
// pay-to-pubkey address.
|
||||
func (a *AddressPubKey) SetFormat(pkFormat PubKeyFormat) {
|
||||
a.pubKeyFormat = pkFormat
|
||||
}
|
||||
|
||||
// AddressPubKeyHash returns the pay-to-pubkey address converted to a
|
||||
// pay-to-pubkey-hash address. Note that the public key format (uncompressed,
|
||||
// compressed, etc) will change the resulting address. This is expected since
|
||||
// pay-to-pubkey-hash is a hash of the serialized public key which obviously
|
||||
// differs with the format. At the time of this writing, most Bitcoin addresses
|
||||
// are pay-to-pubkey-hash constructed from the uncompressed public key.
|
||||
func (a *AddressPubKey) AddressPubKeyHash() *AddressPubKeyHash {
|
||||
addr := &AddressPubKeyHash{prefix: a.prefix}
|
||||
copy(addr.hash[:], Hash160(a.serialize()))
|
||||
return addr
|
||||
}
|
||||
|
||||
// PubKey returns the underlying public key for the address.
|
||||
func (a *AddressPubKey) PubKey() *btcec.PublicKey {
|
||||
return a.pubKey
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ package util_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
@ -232,17 +231,12 @@ func TestAddresses(t *testing.T) {
|
||||
|
||||
// Perform type-specific calculations.
|
||||
var saddr []byte
|
||||
switch d := decoded.(type) {
|
||||
switch decoded.(type) {
|
||||
case *util.AddressPubKeyHash:
|
||||
saddr = util.TstAddressSAddr(encoded)
|
||||
|
||||
case *util.AddressScriptHash:
|
||||
saddr = util.TstAddressSAddr(encoded)
|
||||
|
||||
case *util.AddressPubKey:
|
||||
// Ignore the error here since the script
|
||||
// address is checked below.
|
||||
saddr, _ = hex.DecodeString(d.String())
|
||||
}
|
||||
|
||||
// Check script address, as well as the Hash160 method for P2PKH and
|
||||
|
@ -251,16 +251,9 @@ func (bf *Filter) AddOutpoint(outpoint *wire.Outpoint) {
|
||||
//
|
||||
// This function MUST be called with the filter lock held.
|
||||
func (bf *Filter) maybeAddOutpoint(pkScript []byte, outTxID *daghash.TxID, outIdx uint32) {
|
||||
switch bf.msgFilterLoad.Flags {
|
||||
case wire.BloomUpdateAll:
|
||||
if bf.msgFilterLoad.Flags == wire.BloomUpdateAll {
|
||||
outpoint := wire.NewOutpoint(outTxID, outIdx)
|
||||
bf.addOutpoint(outpoint)
|
||||
case wire.BloomUpdateP2PubkeyOnly:
|
||||
class := txscript.GetScriptClass(pkScript)
|
||||
if class == txscript.PubKeyTy || class == txscript.MultiSigTy {
|
||||
outpoint := wire.NewOutpoint(outTxID, outIdx)
|
||||
bf.addOutpoint(outpoint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -527,340 +527,6 @@ func TestFilterInsertUpdateNone(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterInsertP2PubKeyOnly(t *testing.T) {
|
||||
blockBytes := []byte{
|
||||
0x01, 0x00, 0x00, 0x00, // Version
|
||||
0x01, // NumParentBlocks
|
||||
0x82, 0xBB, 0x86, 0x9C, 0xF3, 0xA7, 0x93, 0x43, 0x2A, 0x66, 0xE8, // ParentHashes
|
||||
0x26, 0xE0, 0x5A, 0x6F, 0xC3, 0x74, 0x69, 0xF8, 0xEF, 0xB7, 0x42,
|
||||
0x1D, 0xC8, 0x80, 0x67, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x7F, 0x16, 0xC5, 0x96, 0x2E, 0x8B, 0xD9, 0x63, 0x65, 0x9C, 0x79, // HashMerkleRoot
|
||||
0x3C, 0xE3, 0x70, 0xD9, 0x5F, 0x09, 0x3B, 0xC7, 0xE3, 0x67, 0x11,
|
||||
0x7B, 0x3C, 0x30, 0xC1, 0xF8, 0xFD, 0xD0, 0xD9, 0x72, 0x87,
|
||||
0x3C, 0xE3, 0x70, 0xD9, 0x5F, 0x09, 0x3B, 0xC7, 0xE3, 0x67, 0x11, // AcceptedIDMerkleRoot
|
||||
0x7F, 0x16, 0xC5, 0x96, 0x2E, 0x8B, 0xD9, 0x63, 0x65, 0x9C, 0x79,
|
||||
0x7B, 0x3C, 0x30, 0xC1, 0xF8, 0xFD, 0xD0, 0xD9, 0x72, 0x87,
|
||||
0x10, 0x3B, 0xC7, 0xE3, 0x67, 0x11, 0x7B, 0x3C, // UTXOCommitment
|
||||
0x30, 0xC1, 0xF8, 0xFD, 0xD0, 0xD9, 0x72, 0x87,
|
||||
0x7F, 0x16, 0xC5, 0x96, 0x2E, 0x8B, 0xD9, 0x63,
|
||||
0x65, 0x9C, 0x79, 0x3C, 0xE3, 0x70, 0xD9, 0x5F,
|
||||
0x76, 0x38, 0x1B, 0x4D, 0x00, 0x00, 0x00, 0x00, // Time
|
||||
0x4C, 0x86, 0x04, 0x1B, // Bits
|
||||
0x55, 0x4B, 0x85, 0x29, 0x00, 0x00, 0x00, 0x00, // Fake Nonce. TODO: (Ori) Replace to a real nonce
|
||||
0x07, // NumTxns
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Txs[0]
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x04, 0x4C,
|
||||
0x86, 0x04, 0x1B, 0x01, 0x36, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x01, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00,
|
||||
0x43, 0x41, 0x04, 0xEA, 0xAF, 0xC2, 0x31, 0x4D, 0xEF, 0x4C, 0xA9,
|
||||
0x8A, 0xC9, 0x70, 0x24, 0x1B, 0xCA, 0xB0, 0x22, 0xB9, 0xC1, 0xE1,
|
||||
0xF4, 0xEA, 0x42, 0x3A, 0x20, 0xF1, 0x34, 0xC8, 0x76, 0xF2, 0xC0,
|
||||
0x1E, 0xC0, 0xF0, 0xDD, 0x5B, 0x2E, 0x86, 0xE7, 0x16, 0x8C, 0xEF,
|
||||
0xE0, 0xD8, 0x11, 0x13, 0xC3, 0x80, 0x74, 0x20, 0xCE, 0x13, 0xAD,
|
||||
0x13, 0x57, 0x23, 0x1A, 0x22, 0x52, 0x24, 0x7D, 0x97, 0xA4, 0x6A,
|
||||
0x91, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0xBC, 0xAD, 0x20, 0xA6, 0xA2, 0x98, // Txs[1]
|
||||
0x27, 0xD1, 0x42, 0x4F, 0x08, 0x98, 0x92, 0x55, 0x12, 0x0B, 0xF7,
|
||||
0xF3, 0xE9, 0xE3, 0xCD, 0xAA, 0xA6, 0xBB, 0x31, 0xB0, 0x73, 0x7F,
|
||||
0xE0, 0x48, 0x72, 0x43, 0x00, 0x00, 0x00, 0x00, 0x49, 0x48, 0x30,
|
||||
0x45, 0x02, 0x20, 0x35, 0x6E, 0x83, 0x4B, 0x04, 0x6C, 0xAD, 0xC0,
|
||||
0xF8, 0xEB, 0xB5, 0xA8, 0xA0, 0x17, 0xB0, 0x2D, 0xE5, 0x9C, 0x86,
|
||||
0x30, 0x54, 0x03, 0xDA, 0xD5, 0x2C, 0xD7, 0x7B, 0x55, 0xAF, 0x06,
|
||||
0x2E, 0xA1, 0x02, 0x21, 0x00, 0x92, 0x53, 0xCD, 0x6C, 0x11, 0x9D,
|
||||
0x47, 0x29, 0xB7, 0x7C, 0x97, 0x8E, 0x1E, 0x2A, 0xA1, 0x9F, 0x5E,
|
||||
0xA6, 0xE0, 0xE5, 0x2B, 0x3F, 0x16, 0xE3, 0x2F, 0xA6, 0x08, 0xCD,
|
||||
0x5B, 0xAB, 0x75, 0x39, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x02, 0x00, 0x8D, 0x38, 0x0C, 0x01, 0x00, 0x00, 0x00,
|
||||
0x19, 0x76, 0xA9, 0x14, 0x2B, 0x4B, 0x80, 0x72, 0xEC, 0xBB, 0xA1,
|
||||
0x29, 0xB6, 0x45, 0x3C, 0x63, 0xE1, 0x29, 0xE6, 0x43, 0x20, 0x72,
|
||||
0x49, 0xCA, 0x88, 0xAC, 0x00, 0x65, 0xCD, 0x1D, 0x00, 0x00, 0x00,
|
||||
0x00, 0x19, 0x76, 0xA9, 0x14, 0x1B, 0x8D, 0xD1, 0x3B, 0x99, 0x4B,
|
||||
0xCF, 0xC7, 0x87, 0xB3, 0x2A, 0xEA, 0xDF, 0x58, 0xCC, 0xB3, 0x61,
|
||||
0x5C, 0xBD, 0x54, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x03, 0xFD, 0xAC, 0xF9, 0xB3, 0xEB, 0x07, // Txs[2]
|
||||
0x74, 0x12, 0xE7, 0xA9, 0x68, 0xD2, 0xE4, 0xF1, 0x1B, 0x9A, 0x9D,
|
||||
0xEE, 0x31, 0x2D, 0x66, 0x61, 0x87, 0xED, 0x77, 0xEE, 0x7D, 0x26,
|
||||
0xAF, 0x16, 0xCB, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x49, 0x30,
|
||||
0x46, 0x02, 0x21, 0x00, 0xEA, 0x16, 0x08, 0xE7, 0x09, 0x11, 0xCA,
|
||||
0x0D, 0xE5, 0xAF, 0x51, 0xBA, 0x57, 0xAD, 0x23, 0xB9, 0xA5, 0x1D,
|
||||
0xB8, 0xD2, 0x8F, 0x82, 0xC5, 0x35, 0x63, 0xC5, 0x6A, 0x05, 0xC2,
|
||||
0x0F, 0x5A, 0x87, 0x02, 0x21, 0x00, 0xA8, 0xBD, 0xC8, 0xB4, 0xA8,
|
||||
0xAC, 0xC8, 0x63, 0x4C, 0x6B, 0x42, 0x04, 0x10, 0x15, 0x07, 0x75,
|
||||
0xEB, 0x7F, 0x24, 0x74, 0xF5, 0x61, 0x5F, 0x7F, 0xCC, 0xD6, 0x5A,
|
||||
0xF3, 0x0F, 0x31, 0x0F, 0xBF, 0x01, 0x41, 0x04, 0x65, 0xFD, 0xF4,
|
||||
0x9E, 0x29, 0xB0, 0x6B, 0x9A, 0x15, 0x82, 0x28, 0x7B, 0x62, 0x79,
|
||||
0x01, 0x4F, 0x83, 0x4E, 0xDC, 0x31, 0x76, 0x95, 0xD1, 0x25, 0xEF,
|
||||
0x62, 0x3C, 0x1C, 0xC3, 0xAA, 0xEC, 0xE2, 0x45, 0xBD, 0x69, 0xFC,
|
||||
0xAD, 0x75, 0x08, 0x66, 0x6E, 0x9C, 0x74, 0xA4, 0x9D, 0xC9, 0x05,
|
||||
0x6D, 0x5F, 0xC1, 0x43, 0x38, 0xEF, 0x38, 0x11, 0x8D, 0xC4, 0xAF,
|
||||
0xAE, 0x5F, 0xE2, 0xC5, 0x85, 0xCA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x30, 0x9E, 0x19, 0x13, 0x63, 0x4E, 0xCB, 0x50,
|
||||
0xF3, 0xC4, 0xF8, 0x3E, 0x96, 0xE7, 0x0B, 0x2D, 0xF0, 0x71, 0xB4,
|
||||
0x97, 0xB8, 0x97, 0x3A, 0x3E, 0x75, 0x42, 0x9D, 0xF3, 0x97, 0xB5,
|
||||
0xAF, 0x83, 0x00, 0x00, 0x00, 0x00, 0x49, 0x48, 0x30, 0x45, 0x02,
|
||||
0x20, 0x2B, 0xDB, 0x79, 0xC5, 0x96, 0xA9, 0xFF, 0xC2, 0x4E, 0x96,
|
||||
0xF4, 0x38, 0x61, 0x99, 0xAB, 0xA3, 0x86, 0xE9, 0xBC, 0x7B, 0x60,
|
||||
0x71, 0x51, 0x6E, 0x2B, 0x51, 0xDD, 0xA9, 0x42, 0xB3, 0xA1, 0xED,
|
||||
0x02, 0x21, 0x00, 0xC5, 0x3A, 0x85, 0x7E, 0x76, 0xB7, 0x24, 0xFC,
|
||||
0x14, 0xD4, 0x53, 0x11, 0xEA, 0xC5, 0x01, 0x96, 0x50, 0xD4, 0x15,
|
||||
0xC3, 0xAB, 0xB5, 0x42, 0x8F, 0x3A, 0xAE, 0x16, 0xD8, 0xE6, 0x9B,
|
||||
0xEC, 0x23, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x20, 0x89, 0xE3, 0x34, 0x91, 0x69, 0x50, 0x80, 0xC9, 0xED, 0xC1,
|
||||
0x8A, 0x42, 0x8F, 0x7D, 0x83, 0x4D, 0xB5, 0xB6, 0xD3, 0x72, 0xDF,
|
||||
0x13, 0xCE, 0x2B, 0x1B, 0x0E, 0x0C, 0xBC, 0xB1, 0xE6, 0xC1, 0x00,
|
||||
0x00, 0x00, 0x00, 0x49, 0x48, 0x30, 0x45, 0x02, 0x21, 0x00, 0xD4,
|
||||
0xCE, 0x67, 0xC5, 0x89, 0x6E, 0xE2, 0x51, 0xC8, 0x10, 0xAC, 0x1F,
|
||||
0xF9, 0xCE, 0xCC, 0xD3, 0x28, 0xB4, 0x97, 0xC8, 0xF5, 0x53, 0xAB,
|
||||
0x6E, 0x08, 0x43, 0x1E, 0x7D, 0x40, 0xBA, 0xD6, 0xB5, 0x02, 0x20,
|
||||
0x33, 0x11, 0x9C, 0x0C, 0x2B, 0x7D, 0x79, 0x2D, 0x31, 0xF1, 0x18,
|
||||
0x77, 0x79, 0xC7, 0xBD, 0x95, 0xAE, 0xFD, 0x93, 0xD9, 0x0A, 0x71,
|
||||
0x55, 0x86, 0xD7, 0x38, 0x01, 0xD9, 0xB4, 0x74, 0x71, 0xC6, 0x01,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x71,
|
||||
0x44, 0x60, 0x03, 0x00, 0x00, 0x00, 0x19, 0x76, 0xA9, 0x14, 0xC7,
|
||||
0xB5, 0x51, 0x41, 0xD0, 0x97, 0xEA, 0x5D, 0xF7, 0xA0, 0xED, 0x33,
|
||||
0x0C, 0xF7, 0x94, 0x37, 0x6E, 0x53, 0xEC, 0x8D, 0x88, 0xAC, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x04, 0x5B, 0xF0, 0xE2, 0x14, 0xAA, 0x40, // Txs[3]
|
||||
0x69, 0xA3, 0xE7, 0x92, 0xEC, 0xEE, 0x1E, 0x1B, 0xF0, 0xC1, 0xD3,
|
||||
0x97, 0xCD, 0xE8, 0xDD, 0x08, 0x13, 0x8F, 0x4B, 0x72, 0xA0, 0x06,
|
||||
0x81, 0x74, 0x34, 0x47, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x48, 0x30,
|
||||
0x45, 0x02, 0x20, 0x0C, 0x45, 0xDE, 0x8C, 0x4F, 0x3E, 0x2C, 0x18,
|
||||
0x21, 0xF2, 0xFC, 0x87, 0x8C, 0xBA, 0x97, 0xB1, 0xE6, 0xF8, 0x80,
|
||||
0x7D, 0x94, 0x93, 0x07, 0x13, 0xAA, 0x1C, 0x86, 0xA6, 0x7B, 0x9B,
|
||||
0xF1, 0xE4, 0x02, 0x21, 0x00, 0x85, 0x81, 0xAB, 0xFE, 0xF2, 0xE3,
|
||||
0x0F, 0x95, 0x78, 0x15, 0xFC, 0x89, 0x97, 0x84, 0x23, 0x74, 0x6B,
|
||||
0x20, 0x86, 0x37, 0x5C, 0xA8, 0xEC, 0xF3, 0x59, 0xC8, 0x5C, 0x2A,
|
||||
0x5B, 0x7C, 0x88, 0xAD, 0x01, 0x41, 0x04, 0x62, 0xBB, 0x73, 0xF7,
|
||||
0x6C, 0xA0, 0x99, 0x4F, 0xCB, 0x8B, 0x42, 0x71, 0xE6, 0xFB, 0x75,
|
||||
0x61, 0xF5, 0xC0, 0xF9, 0xCA, 0x0C, 0xF6, 0x48, 0x52, 0x61, 0xC4,
|
||||
0xA0, 0xDC, 0x89, 0x4F, 0x4A, 0xB8, 0x44, 0xC6, 0xCD, 0xFB, 0x97,
|
||||
0xCD, 0x0B, 0x60, 0xFF, 0xB5, 0x01, 0x8F, 0xFD, 0x62, 0x38, 0xF4,
|
||||
0xD8, 0x72, 0x70, 0xEF, 0xB1, 0xD3, 0xAE, 0x37, 0x07, 0x9B, 0x79,
|
||||
0x4A, 0x92, 0xD7, 0xEC, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xD6, 0x69, 0xF7, 0xD7, 0x95, 0x8D, 0x40, 0xFC, 0x59,
|
||||
0xD2, 0x25, 0x3D, 0x88, 0xE0, 0xF2, 0x48, 0xE2, 0x9B, 0x59, 0x9C,
|
||||
0x80, 0xBB, 0xCE, 0xC3, 0x44, 0xA8, 0x3D, 0xDA, 0x5F, 0x9A, 0xA7,
|
||||
0x2C, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x47, 0x30, 0x44, 0x02, 0x20,
|
||||
0x78, 0x12, 0x4C, 0x8B, 0xEE, 0xAA, 0x82, 0x5F, 0x9E, 0x0B, 0x30,
|
||||
0xBF, 0xF9, 0x6E, 0x56, 0x4D, 0xD8, 0x59, 0x43, 0x2F, 0x2D, 0x0C,
|
||||
0xB3, 0xB7, 0x2D, 0x3D, 0x5D, 0x93, 0xD3, 0x8D, 0x7E, 0x93, 0x02,
|
||||
0x20, 0x69, 0x1D, 0x23, 0x3B, 0x6C, 0x0F, 0x99, 0x5B, 0xE5, 0xAC,
|
||||
0xB0, 0x3D, 0x70, 0xA7, 0xF7, 0xA6, 0x5B, 0x6B, 0xC9, 0xBD, 0xD4,
|
||||
0x26, 0x26, 0x0F, 0x38, 0xA1, 0x34, 0x66, 0x69, 0x50, 0x7A, 0x36,
|
||||
0x01, 0x41, 0x04, 0x62, 0xBB, 0x73, 0xF7, 0x6C, 0xA0, 0x99, 0x4F,
|
||||
0xCB, 0x8B, 0x42, 0x71, 0xE6, 0xFB, 0x75, 0x61, 0xF5, 0xC0, 0xF9,
|
||||
0xCA, 0x0C, 0xF6, 0x48, 0x52, 0x61, 0xC4, 0xA0, 0xDC, 0x89, 0x4F,
|
||||
0x4A, 0xB8, 0x44, 0xC6, 0xCD, 0xFB, 0x97, 0xCD, 0x0B, 0x60, 0xFF,
|
||||
0xB5, 0x01, 0x8F, 0xFD, 0x62, 0x38, 0xF4, 0xD8, 0x72, 0x70, 0xEF,
|
||||
0xB1, 0xD3, 0xAE, 0x37, 0x07, 0x9B, 0x79, 0x4A, 0x92, 0xD7, 0xEC,
|
||||
0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x78,
|
||||
0xAF, 0x0D, 0x93, 0xF5, 0x22, 0x9A, 0x68, 0x16, 0x6C, 0xF0, 0x51,
|
||||
0xFD, 0x37, 0x2B, 0xB7, 0xA5, 0x37, 0x23, 0x29, 0x46, 0xE0, 0xA4,
|
||||
0x6F, 0x53, 0x63, 0x6B, 0x4D, 0xAF, 0xDA, 0xA4, 0x00, 0x00, 0x00,
|
||||
0x00, 0x8C, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00,
|
||||
0xC7, 0x17, 0xD1, 0x71, 0x45, 0x51, 0x66, 0x3F, 0x69, 0xC3, 0xC5,
|
||||
0x75, 0x9B, 0xDB, 0xB3, 0xA0, 0xFC, 0xD3, 0xFA, 0xB0, 0x23, 0xAB,
|
||||
0xC0, 0xE5, 0x22, 0xFE, 0x64, 0x40, 0xDE, 0x35, 0xD8, 0x29, 0x02,
|
||||
0x21, 0x00, 0x8D, 0x9C, 0xBE, 0x25, 0xBF, 0xFC, 0x44, 0xAF, 0x2B,
|
||||
0x18, 0xE8, 0x1C, 0x58, 0xEB, 0x37, 0x29, 0x3F, 0xD7, 0xFE, 0x1C,
|
||||
0x2E, 0x7B, 0x46, 0xFC, 0x37, 0xEE, 0x8C, 0x96, 0xC5, 0x0A, 0xB1,
|
||||
0xE2, 0x01, 0x41, 0x04, 0x62, 0xBB, 0x73, 0xF7, 0x6C, 0xA0, 0x99,
|
||||
0x4F, 0xCB, 0x8B, 0x42, 0x71, 0xE6, 0xFB, 0x75, 0x61, 0xF5, 0xC0,
|
||||
0xF9, 0xCA, 0x0C, 0xF6, 0x48, 0x52, 0x61, 0xC4, 0xA0, 0xDC, 0x89,
|
||||
0x4F, 0x4A, 0xB8, 0x44, 0xC6, 0xCD, 0xFB, 0x97, 0xCD, 0x0B, 0x60,
|
||||
0xFF, 0xB5, 0x01, 0x8F, 0xFD, 0x62, 0x38, 0xF4, 0xD8, 0x72, 0x70,
|
||||
0xEF, 0xB1, 0xD3, 0xAE, 0x37, 0x07, 0x9B, 0x79, 0x4A, 0x92, 0xD7,
|
||||
0xEC, 0x95, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x27,
|
||||
0xF2, 0xB6, 0x68, 0x85, 0x9C, 0xD7, 0xF2, 0xF8, 0x94, 0xAA, 0x0F,
|
||||
0xD2, 0xD9, 0xE6, 0x09, 0x63, 0xBC, 0xD0, 0x7C, 0x88, 0x97, 0x3F,
|
||||
0x42, 0x5F, 0x99, 0x9B, 0x8C, 0xBF, 0xD7, 0xA1, 0xE2, 0x00, 0x00,
|
||||
0x00, 0x00, 0x8C, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xE0, 0x08,
|
||||
0x47, 0x14, 0x7C, 0xBF, 0x51, 0x7B, 0xCC, 0x2F, 0x50, 0x2F, 0x3D,
|
||||
0xDC, 0x6D, 0x28, 0x43, 0x58, 0xD1, 0x02, 0xED, 0x20, 0xD4, 0x7A,
|
||||
0x8A, 0xA7, 0x88, 0xA6, 0x2F, 0x0D, 0xB7, 0x80, 0x02, 0x21, 0x00,
|
||||
0xD1, 0x7B, 0x2D, 0x6F, 0xA8, 0x4D, 0xCA, 0xF1, 0xC9, 0x5D, 0x88,
|
||||
0xD7, 0xE7, 0xC3, 0x03, 0x85, 0xAE, 0xCF, 0x41, 0x55, 0x88, 0xD7,
|
||||
0x49, 0xAF, 0xD3, 0xEC, 0x81, 0xF6, 0x02, 0x2C, 0xEC, 0xD7, 0x01,
|
||||
0x41, 0x04, 0x62, 0xBB, 0x73, 0xF7, 0x6C, 0xA0, 0x99, 0x4F, 0xCB,
|
||||
0x8B, 0x42, 0x71, 0xE6, 0xFB, 0x75, 0x61, 0xF5, 0xC0, 0xF9, 0xCA,
|
||||
0x0C, 0xF6, 0x48, 0x52, 0x61, 0xC4, 0xA0, 0xDC, 0x89, 0x4F, 0x4A,
|
||||
0xB8, 0x44, 0xC6, 0xCD, 0xFB, 0x97, 0xCD, 0x0B, 0x60, 0xFF, 0xB5,
|
||||
0x01, 0x8F, 0xFD, 0x62, 0x38, 0xF4, 0xD8, 0x72, 0x70, 0xEF, 0xB1,
|
||||
0xD3, 0xAE, 0x37, 0x07, 0x9B, 0x79, 0x4A, 0x92, 0xD7, 0xEC, 0x95,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0xC8,
|
||||
0x17, 0xA8, 0x04, 0x00, 0x00, 0x00, 0x19, 0x76, 0xA9, 0x14, 0xB6,
|
||||
0xEF, 0xD8, 0x0D, 0x99, 0x17, 0x9F, 0x4F, 0x4F, 0xF6, 0xF4, 0xDD,
|
||||
0x0A, 0x00, 0x7D, 0x01, 0x8C, 0x38, 0x5D, 0x21,
|
||||
0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x83, 0x45, 0x37, 0xB2, 0xF1, 0xCE, // Txs[4]
|
||||
0x8E, 0xF9, 0x37, 0x3A, 0x25, 0x8E, 0x10, 0x54, 0x5C, 0xE5, 0xA5,
|
||||
0x0B, 0x75, 0x8D, 0xF6, 0x16, 0xCD, 0x43, 0x56, 0xE0, 0x03, 0x25,
|
||||
0x54, 0xEB, 0xD3, 0xC4, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x48, 0x30,
|
||||
0x45, 0x02, 0x21, 0x00, 0xE6, 0x8F, 0x42, 0x2D, 0xD7, 0xC3, 0x4F,
|
||||
0xDC, 0xE1, 0x1E, 0xEB, 0x45, 0x09, 0xDD, 0xAE, 0x38, 0x20, 0x17,
|
||||
0x73, 0xDD, 0x62, 0xF2, 0x84, 0xE8, 0xAA, 0x9D, 0x96, 0xF8, 0x50,
|
||||
0x99, 0xD0, 0xB0, 0x02, 0x20, 0x22, 0x43, 0xBD, 0x39, 0x9F, 0xF9,
|
||||
0x6B, 0x64, 0x9A, 0x0F, 0xAD, 0x05, 0xFA, 0x75, 0x9D, 0x6A, 0x88,
|
||||
0x2F, 0x0A, 0xF8, 0xC9, 0x0C, 0xF7, 0x63, 0x2C, 0x28, 0x40, 0xC2,
|
||||
0x90, 0x70, 0xAE, 0xC2, 0x01, 0x41, 0x04, 0x5E, 0x58, 0x06, 0x7E,
|
||||
0x81, 0x5C, 0x2F, 0x46, 0x4C, 0x6A, 0x2A, 0x15, 0xF9, 0x87, 0x75,
|
||||
0x83, 0x74, 0x20, 0x38, 0x95, 0x71, 0x0C, 0x2D, 0x45, 0x24, 0x42,
|
||||
0xE2, 0x84, 0x96, 0xFF, 0x38, 0xBA, 0x8F, 0x5F, 0xD9, 0x01, 0xDC,
|
||||
0x20, 0xE2, 0x9E, 0x88, 0x47, 0x71, 0x67, 0xFE, 0x4F, 0xC2, 0x99,
|
||||
0xBF, 0x81, 0x8F, 0xD0, 0xD9, 0xE1, 0x63, 0x2D, 0x46, 0x7B, 0x2A,
|
||||
0x3D, 0x95, 0x03, 0xB1, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x02, 0x80, 0xD7, 0xE6, 0x36, 0x03, 0x00, 0x00, 0x00,
|
||||
0x19, 0x76, 0xA9, 0x14, 0xF3, 0x4C, 0x3E, 0x10, 0xEB, 0x38, 0x7E,
|
||||
0xFE, 0x87, 0x2A, 0xCB, 0x61, 0x4C, 0x89, 0xE7, 0x8B, 0xFC, 0xA7,
|
||||
0x81, 0x5D, 0x88, 0xAC, 0x40, 0x4B, 0x4C, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x19, 0x76, 0xA9, 0x14, 0xA8, 0x4E, 0x27, 0x29, 0x33, 0xAA,
|
||||
0xF8, 0x7E, 0x17, 0x15, 0xD7, 0x78, 0x6C, 0x51, 0xDF, 0xAE, 0xB5,
|
||||
0xB6, 0x5A, 0x6F, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x43, 0xAC, 0x81, 0xC8, 0xE6, 0xF6, // Txs[5]
|
||||
0xEF, 0x30, 0x7D, 0xFE, 0x17, 0xF3, 0xD9, 0x06, 0xD9, 0x99, 0xE2,
|
||||
0x3E, 0x01, 0x89, 0xFD, 0xA8, 0x38, 0xC5, 0x51, 0x0D, 0x85, 0x09,
|
||||
0x27, 0xE0, 0x3A, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x8C, 0x49, 0x30,
|
||||
0x46, 0x02, 0x21, 0x00, 0x9C, 0x87, 0xC3, 0x44, 0x76, 0x0A, 0x64,
|
||||
0xCB, 0x8A, 0xE6, 0x68, 0x5A, 0x3E, 0xEC, 0x2C, 0x1A, 0xC1, 0xBE,
|
||||
0xD5, 0xB8, 0x8C, 0x87, 0xDE, 0x51, 0xAC, 0xD0, 0xE1, 0x24, 0xF2,
|
||||
0x66, 0xC1, 0x66, 0x02, 0x21, 0x00, 0x82, 0xD0, 0x7C, 0x03, 0x73,
|
||||
0x59, 0xC3, 0xA2, 0x57, 0xB5, 0xC6, 0x3E, 0xBD, 0x90, 0xF5, 0xA5,
|
||||
0xED, 0xF9, 0x7B, 0x2A, 0xC1, 0xC4, 0x34, 0xB0, 0x8C, 0xA9, 0x98,
|
||||
0x83, 0x9F, 0x34, 0x6D, 0xD4, 0x01, 0x41, 0x04, 0x0B, 0xA7, 0xE5,
|
||||
0x21, 0xFA, 0x79, 0x46, 0xD1, 0x2E, 0xDB, 0xB1, 0xD1, 0xE9, 0x5A,
|
||||
0x15, 0xC3, 0x4B, 0xD4, 0x39, 0x81, 0x95, 0xE8, 0x64, 0x33, 0xC9,
|
||||
0x2B, 0x43, 0x1C, 0xD3, 0x15, 0xF4, 0x55, 0xFE, 0x30, 0x03, 0x2E,
|
||||
0xDE, 0x69, 0xCA, 0xD9, 0xD1, 0xE1, 0xED, 0x6C, 0x3C, 0x4E, 0xC0,
|
||||
0xDB, 0xFC, 0xED, 0x53, 0x43, 0x8C, 0x62, 0x54, 0x62, 0xAF, 0xB7,
|
||||
0x92, 0xDC, 0xB0, 0x98, 0x54, 0x4B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x02, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x19, 0x76, 0xA9, 0x14, 0x46, 0x76, 0xD1, 0xB8, 0x20, 0xD6,
|
||||
0x3E, 0xC2, 0x72, 0xF1, 0x90, 0x0D, 0x59, 0xD4, 0x3B, 0xC6, 0x46,
|
||||
0x3D, 0x96, 0xF8, 0x88, 0xAC, 0x40, 0x42, 0x0F, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x19, 0x76, 0xA9, 0x14, 0x64, 0x8D, 0x04, 0x34, 0x1D,
|
||||
0x00, 0xD7, 0x96, 0x8B, 0x34, 0x05, 0xC0, 0x34, 0xAD, 0xC3, 0x8D,
|
||||
0x4D, 0x8F, 0xB9, 0xBD, 0x88, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x02, 0x48, 0xCC, 0x91, 0x75, 0x01, 0xEA, // Txs[6]
|
||||
0x5C, 0x55, 0xF4, 0xA8, 0xD2, 0x00, 0x9C, 0x05, 0x67, 0xC4, 0x0C,
|
||||
0xFE, 0x03, 0x7C, 0x2E, 0x71, 0xAF, 0x01, 0x7D, 0x0A, 0x45, 0x2F,
|
||||
0xF7, 0x05, 0xE3, 0xF1, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x48, 0x30,
|
||||
0x45, 0x02, 0x21, 0x00, 0xBF, 0x5F, 0xDC, 0x86, 0xDC, 0x5F, 0x08,
|
||||
0xA5, 0xD5, 0xC8, 0xE4, 0x3A, 0x8C, 0x9D, 0x5B, 0x1E, 0xD8, 0xC6,
|
||||
0x55, 0x62, 0xE2, 0x80, 0x00, 0x7B, 0x52, 0xB1, 0x33, 0x02, 0x1A,
|
||||
0xCD, 0x9A, 0xCC, 0x02, 0x20, 0x5E, 0x32, 0x5D, 0x61, 0x3E, 0x55,
|
||||
0x5F, 0x77, 0x28, 0x02, 0xBF, 0x41, 0x3D, 0x36, 0xBA, 0x80, 0x78,
|
||||
0x92, 0xED, 0x1A, 0x69, 0x0A, 0x77, 0x81, 0x1D, 0x30, 0x33, 0xB3,
|
||||
0xDE, 0x22, 0x6E, 0x0A, 0x01, 0x41, 0x04, 0x29, 0xFA, 0x71, 0x3B,
|
||||
0x12, 0x44, 0x84, 0xCB, 0x2B, 0xD7, 0xB5, 0x55, 0x7B, 0x2C, 0x0B,
|
||||
0x9D, 0xF7, 0xB2, 0xB1, 0xFE, 0xE6, 0x18, 0x25, 0xEA, 0xDC, 0x5A,
|
||||
0xE6, 0xC3, 0x7A, 0x99, 0x20, 0xD3, 0x8B, 0xFC, 0xCD, 0xC7, 0xDC,
|
||||
0x3C, 0xB0, 0xC4, 0x7D, 0x7B, 0x17, 0x3D, 0xBC, 0x9D, 0xB8, 0xD3,
|
||||
0x7D, 0xB0, 0xA3, 0x3A, 0xE4, 0x87, 0x98, 0x2C, 0x59, 0xC6, 0xF8,
|
||||
0x60, 0x6E, 0x9D, 0x17, 0x91, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x41, 0xED, 0x70, 0x55, 0x1D, 0xD7, 0xE8, 0x41, 0x88,
|
||||
0x3A, 0xB8, 0xF0, 0xB1, 0x6B, 0xF0, 0x41, 0x76, 0xB7, 0xD1, 0x48,
|
||||
0x0E, 0x4F, 0x0A, 0xF9, 0xF3, 0xD4, 0xC3, 0x59, 0x57, 0x68, 0xD0,
|
||||
0x68, 0x00, 0x00, 0x00, 0x00, 0x8B, 0x48, 0x30, 0x45, 0x02, 0x21,
|
||||
0x00, 0x85, 0x13, 0xAD, 0x65, 0x18, 0x7B, 0x90, 0x3A, 0xED, 0x11,
|
||||
0x02, 0xD1, 0xD0, 0xC4,
|
||||
0x76, 0x88, 0x12, 0x76, 0x58, 0xC5, 0x11, 0x06, 0x75, 0x3F, 0xED,
|
||||
0x01, 0x51, 0xCE, 0x9C, 0x16, 0xB8, 0x09, 0x02, 0x20, 0x14, 0x32,
|
||||
0xB9, 0xEB, 0xCB, 0x87, 0xBD, 0x04, 0xCE, 0xB2, 0xDE, 0x66, 0x03,
|
||||
0x5F, 0xBB, 0xAF, 0x4B, 0xF8, 0xB0, 0x0D, 0x1C, 0xFE, 0x41, 0xF1,
|
||||
0xA1, 0xF7, 0x33, 0x8F, 0x9A, 0xD7, 0x9D, 0x21, 0x01, 0x41, 0x04,
|
||||
0x9D, 0x4C, 0xF8, 0x01, 0x25, 0xBF, 0x50, 0xBE, 0x17, 0x09, 0xF7,
|
||||
0x18, 0xC0, 0x7A, 0xD1, 0x5D, 0x0F, 0xC6, 0x12, 0xB7, 0xDA, 0x1F,
|
||||
0x55, 0x70, 0xDD, 0xDC, 0x35, 0xF2, 0xA3, 0x52, 0xF0, 0xF2, 0x7C,
|
||||
0x97, 0x8B, 0x06, 0x82, 0x0E, 0xDC, 0xA9, 0xEF, 0x98, 0x2C, 0x35,
|
||||
0xFD, 0xA2, 0xD2, 0x55, 0xAF, 0xBA, 0x34, 0x00, 0x68, 0xC5, 0x03,
|
||||
0x55, 0x52, 0x36, 0x8B, 0xC7, 0x20, 0x0C, 0x14, 0x88, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x09, 0x3D, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xA9, 0x14, 0x8E, 0xDB, 0x68,
|
||||
0x82, 0x2F, 0x1A, 0xD5, 0x80, 0xB0, 0x43, 0xC7, 0xB3, 0xDF, 0x2E,
|
||||
0x40, 0x0F, 0x86, 0x99, 0xEB, 0x48, 0x88, 0xAC, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
}
|
||||
block, err := util.NewBlockFromBytes(blockBytes)
|
||||
if err != nil {
|
||||
t.Errorf("TestFilterInsertP2PubKeyOnly NewBlockFromBytes failed: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateP2PubkeyOnly)
|
||||
|
||||
// Generation pubkey
|
||||
inputStr := "04eaafc2314def4ca98ac970241bcab022b9c1e1f4ea423a20f134c" +
|
||||
"876f2c01ec0f0dd5b2e86e7168cefe0d81113c3807420ce13ad1357231a" +
|
||||
"2252247d97a46a91"
|
||||
inputBytes, err := hex.DecodeString(inputStr)
|
||||
if err != nil {
|
||||
t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
|
||||
return
|
||||
}
|
||||
f.Add(inputBytes)
|
||||
|
||||
// Public key hash of 4th transaction
|
||||
inputStr = "b6efd80d99179f4f4ff6f4dd0a007d018c385d21"
|
||||
inputBytes, err = hex.DecodeString(inputStr)
|
||||
if err != nil {
|
||||
t.Errorf("TestFilterInsertP2PubKeyOnly DecodeString failed: %v", err)
|
||||
return
|
||||
}
|
||||
f.Add(inputBytes)
|
||||
|
||||
// Ignore return value -- this is just used to update the filter.
|
||||
_, _ = bloom.NewMerkleBlock(block, f)
|
||||
|
||||
// We should match the generation pubkey
|
||||
inputStr = "c2254e4d610867ee48decf60d8bd8e1d361eeeab5d1052ce3e98184a5b4d0923" // 0st tx ID
|
||||
txID, err := daghash.NewTxIDFromStr(inputStr)
|
||||
if err != nil {
|
||||
t.Errorf("TestFilterInsertP2PubKeyOnly NewHashFromStr failed: %v", err)
|
||||
return
|
||||
}
|
||||
outpoint := wire.NewOutpoint(txID, 0)
|
||||
if !f.MatchesOutpoint(outpoint) {
|
||||
t.Errorf("TestFilterInsertP2PubKeyOnly didn't match the generation "+
|
||||
"outpoint %s", inputStr)
|
||||
return
|
||||
}
|
||||
|
||||
// We should not match the 4th transaction, which is not p2pk
|
||||
inputStr = "f9a116ecc107b6b1b0bdcd0d727bfaa3355f27f8fed08347bf0004244949d9eb"
|
||||
txID, err = daghash.NewTxIDFromStr(inputStr)
|
||||
if err != nil {
|
||||
t.Errorf("TestFilterInsertP2PubKeyOnly NewHashFromStr failed: %v", err)
|
||||
return
|
||||
}
|
||||
outpoint = wire.NewOutpoint(txID, 0)
|
||||
if f.MatchesOutpoint(outpoint) {
|
||||
t.Errorf("TestFilterInsertP2PubKeyOnly matched outpoint %s", inputStr)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterReload(t *testing.T) {
|
||||
f := bloom.NewFilter(10, 0, 0.000001, wire.BloomUpdateAll)
|
||||
|
||||
|
@ -12,7 +12,6 @@ interface. The functions are only exported while the tests are being run.
|
||||
package util
|
||||
|
||||
import (
|
||||
"github.com/daglabs/btcd/btcec"
|
||||
"github.com/daglabs/btcd/util/bech32"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
@ -47,19 +46,6 @@ func TstAddressScriptHash(prefix Bech32Prefix, hash [ripemd160.Size]byte) *Addre
|
||||
}
|
||||
}
|
||||
|
||||
// TstAddressPubKey makes an AddressPubKey, setting the unexported fields with
|
||||
// the parameters.
|
||||
func TstAddressPubKey(serializedPubKey []byte, pubKeyFormat PubKeyFormat,
|
||||
netID byte) *AddressPubKey {
|
||||
|
||||
pubKey, _ := btcec.ParsePubKey(serializedPubKey, btcec.S256())
|
||||
return &AddressPubKey{
|
||||
pubKeyFormat: pubKeyFormat,
|
||||
pubKey: (*btcec.PublicKey)(pubKey),
|
||||
pubKeyHashID: netID,
|
||||
}
|
||||
}
|
||||
|
||||
// TstAddressSAddr returns the expected script address bytes for
|
||||
// P2PKH and P2SH bitcoin addresses.
|
||||
func TstAddressSAddr(addr string) []byte {
|
||||
|
@ -21,12 +21,6 @@ const (
|
||||
// public key script, the outpoint is serialized and inserted into the
|
||||
// filter.
|
||||
BloomUpdateAll BloomUpdateType = 1
|
||||
|
||||
// BloomUpdateP2PubkeyOnly indicates if the filter matches a data
|
||||
// element in a public key script and the script is of the standard
|
||||
// pay-to-pubkey or multisig, the outpoint is serialized and inserted
|
||||
// into the filter.
|
||||
BloomUpdateP2PubkeyOnly BloomUpdateType = 2
|
||||
)
|
||||
|
||||
const (
|
||||
|
Loading…
x
Reference in New Issue
Block a user