// newAddressScriptHash returns a new btcutil.AddressScriptHash 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 // test source code. func newAddressScriptHash(scriptHash []byte) btcutil.Address { addr, err := btcutil.NewAddressScriptHashFromHash(scriptHash, &btcnet.MainNetParams) if err != nil { panic("invalid script hash in test source") } return addr }
// ExtractPkScriptAddrs returns the type of script, addresses and required // signatures associated with the passed PkScript. Note that it only works for // 'standard' transaction script types. Any data such as public keys which are // invalid are omitted from the results. func ExtractPkScriptAddrs(pkScript []byte, net *btcnet.Params) (ScriptClass, []btcutil.Address, int, error) { var addrs []btcutil.Address var requiredSigs int // No valid addresses or required signatures if the script doesn't // parse. pops, err := parseScript(pkScript) if err != nil { return NonStandardTy, nil, 0, err } scriptClass := typeOfScript(pops) switch scriptClass { case PubKeyHashTy: // A pay-to-pubkey-hash script is of the form: // OP_DUP OP_HASH160 <hash> OP_EQUALVERIFY OP_CHECKSIG // Therefore the pubkey hash is the 3rd item on the stack. // Skip the pubkey hash if it's invalid for some reason. requiredSigs = 1 addr, err := btcutil.NewAddressPubKeyHash(pops[2].data, net) if err == nil { 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 := btcutil.NewAddressPubKey(pops[0].data, net) if err == nil { addrs = append(addrs, addr) } case ScriptHashTy: // A pay-to-script-hash script is of the form: // OP_HASH160 <scripthash> OP_EQUAL // Therefore the script hash is the 2nd item on the stack. // Skip the script hash if it's invalid for some reason. requiredSigs = 1 addr, err := btcutil.NewAddressScriptHashFromHash(pops[1].data, net) if err == nil { 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([]btcutil.Address, 0, numPubKeys) for i := 0; i < numPubKeys; i++ { addr, err := btcutil.NewAddressPubKey(pops[i+1].data, net) if err == nil { addrs = append(addrs, addr) } } case NullDataTy: // Null data transactions have no addresses or required // signatures. case NonStandardTy: // Don't attempt to extract addresses or required signatures for // nonstandard transactions. } return scriptClass, addrs, requiredSigs, nil }