lbcd/address.go

91 lines
2.9 KiB
Go
Raw Normal View History

2014-01-09 06:47:23 +01:00
// Copyright (c) 2013-2014 Conformal Systems LLC.
2013-06-12 23:35:27 +02:00
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package btcscript
import (
"github.com/conformal/btcnet"
"github.com/conformal/btcutil"
2013-06-12 23:35:27 +02:00
)
// 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
2013-06-12 23:35:27 +02:00
}
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)
2013-06-12 23:35:27 +02:00
}
case PubKeyTy:
// A pay-to-pubkey script is of the form:
// <pubkey> OP_CHECKSIG
2014-02-20 18:19:48 +01:00
// 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)
2013-06-12 23:35:27 +02:00
}
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)
2013-06-12 23:35:27 +02:00
}
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)
}
2013-06-12 23:35:27 +02:00
}
case NullDataTy:
// Null data transactions have no addresses or required
// signatures.
2013-06-12 23:35:27 +02:00
case NonStandardTy:
// Don't attempt to extract addresses or required signatures for
// nonstandard transactions.
2013-06-12 23:35:27 +02:00
}
return scriptClass, addrs, requiredSigs, nil
}