OSDN Git Service

Merge pull request #935 from Bytom/dev
[bytom/bytom.git] / common / address.go
index c77eaee..4c81d94 100644 (file)
@@ -1,43 +1,41 @@
 package common
 
 import (
-    "bytes"
-    "errors"
-    "fmt"
-    "strings"
+       "bytes"
+       "errors"
+       "fmt"
+       "strings"
 
-    "github.com/bytom/consensus"
-    "github.com/bytom/common/bech32"
+       "github.com/bytom/common/bech32"
+       "github.com/bytom/consensus"
 )
 
 var (
-    // ErrChecksumMismatch describes an error where decoding failed due
-    // to a bad checksum.
-    ErrChecksumMismatch = errors.New("checksum mismatch")
-
-    // ErrUnknownAddressType describes an error where an address can not
-    // decoded as a specific address type due to the string encoding
-    // begining with an identifier byte unknown to any standard or
-    // registered (via chaincfg.Register) network.
-    ErrUnknownAddressType = errors.New("unknown address type")
-
-    // ErrAddressCollision describes an error where an address can not
-    // be uniquely determined as either a pay-to-pubkey-hash or
-    // pay-to-script-hash address since the leading identifier is used for
-    // describing both address kinds, but for different networks.  Rather
-    // than assuming or defaulting to one or the other, this error is
-    // returned and the caller must decide how to decode the address.
-    ErrAddressCollision = errors.New("address collision")
-
-    // ErrUnsupportedWitnessVer describes an error where a segwit address being
-    // decoded has an unsupported witness version.
-    ErrUnsupportedWitnessVer = errors.New("unsupported witness version")
-
-    // ErrUnsupportedWitnessProgLen describes an error where a segwit address
-    // being decoded has an unsupported witness program length.
-    ErrUnsupportedWitnessProgLen = errors.New("unsupported witness program length")
-
-
+       // ErrChecksumMismatch describes an error where decoding failed due
+       // to a bad checksum.
+       ErrChecksumMismatch = errors.New("checksum mismatch")
+
+       // ErrUnknownAddressType describes an error where an address can not
+       // decoded as a specific address type due to the string encoding
+       // begining with an identifier byte unknown to any standard or
+       // registered (via chaincfg.Register) network.
+       ErrUnknownAddressType = errors.New("unknown address type")
+
+       // ErrAddressCollision describes an error where an address can not
+       // be uniquely determined as either a pay-to-pubkey-hash or
+       // pay-to-script-hash address since the leading identifier is used for
+       // describing both address kinds, but for different networks.  Rather
+       // than assuming or defaulting to one or the other, this error is
+       // returned and the caller must decide how to decode the address.
+       ErrAddressCollision = errors.New("address collision")
+
+       // ErrUnsupportedWitnessVer describes an error where a segwit address being
+       // decoded has an unsupported witness version.
+       ErrUnsupportedWitnessVer = errors.New("unsupported witness version")
+
+       // ErrUnsupportedWitnessProgLen describes an error where a segwit address
+       // being decoded has an unsupported witness program length.
+       ErrUnsupportedWitnessProgLen = errors.New("unsupported witness program length")
 )
 
 // Address is an interface type for any type of destination a transaction
@@ -46,67 +44,63 @@ var (
 // enough that other kinds of addresses may be added in the future without
 // changing the decoding and encoding API.
 type Address interface {
-    // String returns the string encoding of the transaction output
-    // destination.
-    //
-    // Please note that String differs subtly from EncodeAddress: String
-    // will return the value as a string without any conversion, while
-    // EncodeAddress may convert destination types (for example,
-    // converting pubkeys to P2PKH addresses) before encoding as a
-    // payment address string.
-    String() string
-
-    // EncodeAddress returns the string encoding of the payment address
-    // associated with the Address value.  See the comment on String
-    // for how this method differs from String.
-    EncodeAddress() string
-
-    // ScriptAddress returns the raw bytes of the address to be used
-    // when inserting the address into a txout's script.
-    ScriptAddress() []byte
-
-    // IsForNet returns whether or not the address is associated with the
-    // passed bytom network.
-    IsForNet(*consensus.Params) bool
+       // String returns the string encoding of the transaction output
+       // destination.
+       //
+       // Please note that String differs subtly from EncodeAddress: String
+       // will return the value as a string without any conversion, while
+       // EncodeAddress may convert destination types (for example,
+       // converting pubkeys to P2PKH addresses) before encoding as a
+       // payment address string.
+       String() string
+
+       // EncodeAddress returns the string encoding of the payment address
+       // associated with the Address value.  See the comment on String
+       // for how this method differs from String.
+       EncodeAddress() string
+
+       // ScriptAddress returns the raw bytes of the address to be used
+       // when inserting the address into a txout's script.
+       ScriptAddress() []byte
+
+       // IsForNet returns whether or not the address is associated with the
+       // passed bytom network.
+       IsForNet(*consensus.Params) bool
 }
 
-
-
 // encodeSegWitAddress creates a bech32 encoded address string representation
 // from witness version and witness program.
 func encodeSegWitAddress(hrp string, witnessVersion byte, witnessProgram []byte) (string, error) {
-    // Group the address bytes into 5 bit groups, as this is what is used to
-    // encode each character in the address string.
-    converted, err := bech32.ConvertBits(witnessProgram, 8, 5, true)
-    if err != nil {
-        return "", err
-    }
-
-    // Concatenate the witness version and program, and encode the resulting
-    // bytes using bech32 encoding.
-    combined := make([]byte, len(converted)+1)
-    combined[0] = witnessVersion
-    copy(combined[1:], converted)
-    bech, err := bech32.Encode(hrp, combined)
-    if err != nil {
-        return "", err
-    }
-
-    // Check validity by decoding the created address.
-    version, program, err := decodeSegWitAddress(bech)
-    if err != nil {
-        return "", fmt.Errorf("invalid segwit address: %v", err)
-    }
-
-    if version != witnessVersion || !bytes.Equal(program, witnessProgram) {
-        return "", fmt.Errorf("invalid segwit address")
-    }
-
-    return bech, nil
+       // Group the address bytes into 5 bit groups, as this is what is used to
+       // encode each character in the address string.
+       converted, err := bech32.ConvertBits(witnessProgram, 8, 5, true)
+       if err != nil {
+               return "", err
+       }
+
+       // Concatenate the witness version and program, and encode the resulting
+       // bytes using bech32 encoding.
+       combined := make([]byte, len(converted)+1)
+       combined[0] = witnessVersion
+       copy(combined[1:], converted)
+       bech, err := bech32.Bech32Encode(hrp, combined)
+       if err != nil {
+               return "", err
+       }
+
+       // Check validity by decoding the created address.
+       version, program, err := decodeSegWitAddress(bech)
+       if err != nil {
+               return "", fmt.Errorf("invalid segwit address: %v", err)
+       }
+
+       if version != witnessVersion || !bytes.Equal(program, witnessProgram) {
+               return "", fmt.Errorf("invalid segwit address")
+       }
+
+       return bech, nil
 }
 
-
-
 // DecodeAddress decodes the string encoding of an address and returns
 // the Address if addr is a valid encoding for a known address type.
 //
@@ -114,145 +108,143 @@ func encodeSegWitAddress(hrp string, witnessVersion byte, witnessProgram []byte)
 // When the address does not encode the network, such as in the case of a raw
 // public key, the address will be associated with the passed defaultNet.
 func DecodeAddress(addr string, param *consensus.Params) (Address, error) {
-    // Bech32 encoded segwit addresses start with a human-readable part
-    // (hrp) followed by '1'. For Bytom mainnet the hrp is "bm", and for
-    // testnet it is "tm". If the address string has a prefix that matches
-    // one of the prefixes for the known networks, we try to decode it as
-    // a segwit address.
-    oneIndex := strings.LastIndexByte(addr, '1')
-    if oneIndex > 1 {
-        prefix := addr[:oneIndex+1]
-        if consensus.IsBech32SegwitPrefix(prefix, param) {
-            witnessVer, witnessProg, err := decodeSegWitAddress(addr)
-            if err != nil {
-                return nil, err
-            }
-
-            // We currently only support P2WPKH and P2WSH, which is
-            // witness version 0.
-            if witnessVer != 0 {
-                return nil, ErrUnsupportedWitnessVer
-            }
-
-            // The HRP is everything before the found '1'.
-            hrp := prefix[:len(prefix)-1]
-
-            switch len(witnessProg) {
-            case 20:
-                return newAddressWitnessPubKeyHash(hrp, witnessProg)
-            case 32:
-                return newAddressWitnessScriptHash(hrp, witnessProg)
-            default:
-                return nil, ErrUnsupportedWitnessProgLen
-            }
-        }
-    }
-    return nil, ErrUnknownAddressType
+       // Bech32 encoded segwit addresses start with a human-readable part
+       // (hrp) followed by '1'. For Bytom mainnet the hrp is "bm", and for
+       // testnet it is "tm". If the address string has a prefix that matches
+       // one of the prefixes for the known networks, we try to decode it as
+       // a segwit address.
+       oneIndex := strings.LastIndexByte(addr, '1')
+       if oneIndex > 1 {
+               prefix := addr[:oneIndex+1]
+               if consensus.IsBech32SegwitPrefix(prefix, param) {
+                       witnessVer, witnessProg, err := decodeSegWitAddress(addr)
+                       if err != nil {
+                               return nil, err
+                       }
+
+                       // We currently only support P2WPKH and P2WSH, which is
+                       // witness version 0.
+                       if witnessVer != 0 {
+                               return nil, ErrUnsupportedWitnessVer
+                       }
+
+                       // The HRP is everything before the found '1'.
+                       hrp := prefix[:len(prefix)-1]
+
+                       switch len(witnessProg) {
+                       case 20:
+                               return newAddressWitnessPubKeyHash(hrp, witnessProg)
+                       case 32:
+                               return newAddressWitnessScriptHash(hrp, witnessProg)
+                       default:
+                               return nil, ErrUnsupportedWitnessProgLen
+                       }
+               }
+       }
+       return nil, ErrUnknownAddressType
 }
 
 // decodeSegWitAddress parses a bech32 encoded segwit address string and
 // returns the witness version and witness program byte representation.
 func decodeSegWitAddress(address string) (byte, []byte, error) {
-    // Decode the bech32 encoded address.
-    _, data, err := bech32.Decode(address)
-    if err != nil {
-        return 0, nil, err
-    }
-
-    // The first byte of the decoded address is the witness version, it must
-    // exist.
-    if len(data) < 1 {
-        return 0, nil, fmt.Errorf("no witness version")
-    }
-
-    // ...and be <= 16.
-    version := data[0]
-    if version > 16 {
-        return 0, nil, fmt.Errorf("invalid witness version: %v", version)
-    }
-
-    // The remaining characters of the address returned are grouped into
-    // words of 5 bits. In order to restore the original witness program
-    // bytes, we'll need to regroup into 8 bit words.
-    regrouped, err := bech32.ConvertBits(data[1:], 5, 8, false)
-    if err != nil {
-        return 0, nil, err
-    }
-
-    // The regrouped data must be between 2 and 40 bytes.
-    if len(regrouped) < 2 || len(regrouped) > 40 {
-        return 0, nil, fmt.Errorf("invalid data length")
-    }
-
-    // For witness version 0, address MUST be exactly 20 or 32 bytes.
-    if version == 0 && len(regrouped) != 20 && len(regrouped) != 32 {
-        return 0, nil, fmt.Errorf("invalid data length for witness "+
-            "version 0: %v", len(regrouped))
-    }
-
-    return version, regrouped, nil
+       // Decode the bech32 encoded address.
+       _, data, err := bech32.Bech32Decode(address)
+       if err != nil {
+               return 0, nil, err
+       }
+
+       // The first byte of the decoded address is the witness version, it must
+       // exist.
+       if len(data) < 1 {
+               return 0, nil, fmt.Errorf("no witness version")
+       }
+
+       // ...and be <= 16.
+       version := data[0]
+       if version > 16 {
+               return 0, nil, fmt.Errorf("invalid witness version: %v", version)
+       }
+
+       // The remaining characters of the address returned are grouped into
+       // words of 5 bits. In order to restore the original witness program
+       // bytes, we'll need to regroup into 8 bit words.
+       regrouped, err := bech32.ConvertBits(data[1:], 5, 8, false)
+       if err != nil {
+               return 0, nil, err
+       }
+
+       // The regrouped data must be between 2 and 40 bytes.
+       if len(regrouped) < 2 || len(regrouped) > 40 {
+               return 0, nil, fmt.Errorf("invalid data length")
+       }
+
+       // For witness version 0, address MUST be exactly 20 or 32 bytes.
+       if version == 0 && len(regrouped) != 20 && len(regrouped) != 32 {
+               return 0, nil, fmt.Errorf("invalid data length for witness "+
+                       "version 0: %v", len(regrouped))
+       }
+
+       return version, regrouped, nil
 }
 
-
 // AddressWitnessPubKeyHash is an Address for a pay-to-witness-pubkey-hash
 // (P2WPKH) output. See BIP 173 for further details regarding native segregated
 // witness address encoding:
 // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
 type AddressWitnessPubKeyHash struct {
-    hrp            string
-    witnessVersion byte
-    witnessProgram [20]byte
+       hrp            string
+       witnessVersion byte
+       witnessProgram [20]byte
 }
 
 // NewAddressWitnessPubKeyHash returns a new AddressWitnessPubKeyHash.
 func NewAddressWitnessPubKeyHash(witnessProg []byte, param *consensus.Params) (*AddressWitnessPubKeyHash, error) {
-    return newAddressWitnessPubKeyHash(param.Bech32HRPSegwit, witnessProg)
+       return newAddressWitnessPubKeyHash(param.Bech32HRPSegwit, witnessProg)
 }
 
 // newAddressWitnessPubKeyHash is an internal helper function to create an
 // AddressWitnessPubKeyHash with a known human-readable part, rather than
 // looking it up through its parameters.
 func newAddressWitnessPubKeyHash(hrp string, witnessProg []byte) (*AddressWitnessPubKeyHash, error) {
-    // Check for valid program length for witness version 0, which is 20
-    // for P2WPKH.
-    if len(witnessProg) != 20 {
-        return nil, errors.New("witness program must be 20 " +
-            "bytes for p2wpkh")
-    }
+       // Check for valid program length for witness version 0, which is 20
+       // for P2WPKH.
+       if len(witnessProg) != 20 {
+               return nil, errors.New("witness program must be 20 bytes for p2wpkh")
+       }
 
-    addr := &AddressWitnessPubKeyHash{
-        hrp:            strings.ToLower(hrp),
-        witnessVersion: 0x00,
-    }
+       addr := &AddressWitnessPubKeyHash{
+               hrp:            strings.ToLower(hrp),
+               witnessVersion: 0x00,
+       }
 
-    copy(addr.witnessProgram[:], witnessProg)
+       copy(addr.witnessProgram[:], witnessProg)
 
-    return addr, nil
+       return addr, nil
 }
 
 // EncodeAddress returns the bech32 string encoding of an
 // AddressWitnessPubKeyHash.
 // Part of the Address interface.
 func (a *AddressWitnessPubKeyHash) EncodeAddress() string {
-    str, err := encodeSegWitAddress(a.hrp, a.witnessVersion,
-        a.witnessProgram[:])
-    if err != nil {
-        return ""
-    }
-    return str
+       str, err := encodeSegWitAddress(a.hrp, a.witnessVersion,
+               a.witnessProgram[:])
+       if err != nil {
+               return ""
+       }
+       return str
 }
 
 // ScriptAddress returns the witness program for this address.
 // Part of the Address interface.
 func (a *AddressWitnessPubKeyHash) ScriptAddress() []byte {
-    return a.witnessProgram[:]
+       return a.witnessProgram[:]
 }
 
 // IsForNet returns whether or not the AddressWitnessPubKeyHash is associated
 // with the passed bitcoin network.
 // Part of the Address interface.
 func (a *AddressWitnessPubKeyHash) IsForNet(param *consensus.Params) bool {
-    return a.hrp == param.Bech32HRPSegwit
+       return a.hrp == param.Bech32HRPSegwit
 }
 
 // String returns a human-readable string for the AddressWitnessPubKeyHash.
@@ -260,29 +252,29 @@ func (a *AddressWitnessPubKeyHash) IsForNet(param *consensus.Params) bool {
 // can be used as a fmt.Stringer.
 // Part of the Address interface.
 func (a *AddressWitnessPubKeyHash) String() string {
-    return a.EncodeAddress()
+       return a.EncodeAddress()
 }
 
 // Hrp returns the human-readable part of the bech32 encoded
 // AddressWitnessPubKeyHash.
 func (a *AddressWitnessPubKeyHash) Hrp() string {
-    return a.hrp
+       return a.hrp
 }
 
 // WitnessVersion returns the witness version of the AddressWitnessPubKeyHash.
 func (a *AddressWitnessPubKeyHash) WitnessVersion() byte {
-    return a.witnessVersion
+       return a.witnessVersion
 }
 
 // WitnessProgram returns the witness program of the AddressWitnessPubKeyHash.
 func (a *AddressWitnessPubKeyHash) WitnessProgram() []byte {
-    return a.witnessProgram[:]
+       return a.witnessProgram[:]
 }
 
 // Hash160 returns the witness program of the AddressWitnessPubKeyHash as a
 // byte array.
 func (a *AddressWitnessPubKeyHash) Hash160() *[20]byte {
-    return &a.witnessProgram
+       return &a.witnessProgram
 }
 
 // AddressWitnessScriptHash is an Address for a pay-to-witness-script-hash
@@ -290,60 +282,59 @@ func (a *AddressWitnessPubKeyHash) Hash160() *[20]byte {
 // witness address encoding:
 // https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki
 type AddressWitnessScriptHash struct {
-    hrp            string
-    witnessVersion byte
-    witnessProgram [32]byte
+       hrp            string
+       witnessVersion byte
+       witnessProgram [32]byte
 }
 
 // NewAddressWitnessScriptHash returns a new AddressWitnessPubKeyHash.
 func NewAddressWitnessScriptHash(witnessProg []byte, param *consensus.Params) (*AddressWitnessScriptHash, error) {
-    return newAddressWitnessScriptHash(param.Bech32HRPSegwit, witnessProg)
+       return newAddressWitnessScriptHash(param.Bech32HRPSegwit, witnessProg)
 }
 
 // newAddressWitnessScriptHash is an internal helper function to create an
 // AddressWitnessScriptHash with a known human-readable part, rather than
 // looking it up through its parameters.
 func newAddressWitnessScriptHash(hrp string, witnessProg []byte) (*AddressWitnessScriptHash, error) {
-    // Check for valid program length for witness version 0, which is 32
-    // for P2WSH.
-    if len(witnessProg) != 32 {
-        return nil, errors.New("witness program must be 32 " +
-            "bytes for p2wsh")
-    }
+       // Check for valid program length for witness version 0, which is 32
+       // for P2WSH.
+       if len(witnessProg) != 32 {
+               return nil, errors.New("witness program must be 32 bytes for p2wsh")
+       }
 
-    addr := &AddressWitnessScriptHash{
-        hrp:            strings.ToLower(hrp),
-        witnessVersion: 0x00,
-    }
+       addr := &AddressWitnessScriptHash{
+               hrp:            strings.ToLower(hrp),
+               witnessVersion: 0x00,
+       }
 
-    copy(addr.witnessProgram[:], witnessProg)
+       copy(addr.witnessProgram[:], witnessProg)
 
-    return addr, nil
+       return addr, nil
 }
 
 // EncodeAddress returns the bech32 string encoding of an
 // AddressWitnessScriptHash.
 // Part of the Address interface.
 func (a *AddressWitnessScriptHash) EncodeAddress() string {
-    str, err := encodeSegWitAddress(a.hrp, a.witnessVersion,
-        a.witnessProgram[:])
-    if err != nil {
-        return ""
-    }
-    return str
+       str, err := encodeSegWitAddress(a.hrp, a.witnessVersion,
+               a.witnessProgram[:])
+       if err != nil {
+               return ""
+       }
+       return str
 }
 
 // ScriptAddress returns the witness program for this address.
 // Part of the Address interface.
 func (a *AddressWitnessScriptHash) ScriptAddress() []byte {
-    return a.witnessProgram[:]
+       return a.witnessProgram[:]
 }
 
 // IsForNet returns whether or not the AddressWitnessScriptHash is associated
 // with the passed bytom network.
 // Part of the Address interface.
 func (a *AddressWitnessScriptHash) IsForNet(param *consensus.Params) bool {
-    return a.hrp == param.Bech32HRPSegwit
+       return a.hrp == param.Bech32HRPSegwit
 }
 
 // String returns a human-readable string for the AddressWitnessScriptHash.
@@ -351,27 +342,27 @@ func (a *AddressWitnessScriptHash) IsForNet(param *consensus.Params) bool {
 // can be used as a fmt.Stringer.
 // Part of the Address interface.
 func (a *AddressWitnessScriptHash) String() string {
-    return a.EncodeAddress()
+       return a.EncodeAddress()
 }
 
 // Hrp returns the human-readable part of the bech32 encoded
 // AddressWitnessScriptHash.
 func (a *AddressWitnessScriptHash) Hrp() string {
-    return a.hrp
+       return a.hrp
 }
 
 // WitnessVersion returns the witness version of the AddressWitnessScriptHash.
 func (a *AddressWitnessScriptHash) WitnessVersion() byte {
-    return a.witnessVersion
+       return a.witnessVersion
 }
 
 // WitnessProgram returns the witness program of the AddressWitnessScriptHash.
 func (a *AddressWitnessScriptHash) WitnessProgram() []byte {
-    return a.witnessProgram[:]
+       return a.witnessProgram[:]
 }
 
-// Hash160 returns the witness program of the AddressWitnessPubKeyHash as a
+// Sha256 returns the witness program of the AddressWitnessPubKeyHash as a
 // byte array.
 func (a *AddressWitnessScriptHash) Sha256() *[32]byte {
-    return &a.witnessProgram
-}
\ No newline at end of file
+       return &a.witnessProgram
+}