[NOD-224] Make P2PK and raw Multisig non-standard (#332)

This commit is contained in:
Ori Newman 2019-06-27 12:44:22 +03:00 committed by Svarog
parent f7f44995d6
commit c14c64d534
19 changed files with 22 additions and 2239 deletions

View File

@ -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

View File

@ -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
}

View File

@ -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)
}

View File

@ -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() {

View File

@ -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)
}

View File

@ -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) {

View File

@ -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,

View File

@ -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.

View File

@ -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())

View File

@ -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 {

View File

@ -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 {

View File

@ -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.

View File

@ -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),

View File

@ -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
}

View File

@ -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

View File

@ -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)
}
}
}

View File

@ -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)

View File

@ -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 {

View File

@ -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 (