github.com/igggame/nebulas-go@v2.1.0+incompatible/core/address.go (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package core
    20  
    21  import (
    22  	"github.com/btcsuite/btcutil/base58"
    23  	"github.com/nebulasio/go-nebulas/crypto/hash"
    24  	"github.com/nebulasio/go-nebulas/util/byteutils"
    25  )
    26  
    27  // AddressType address type
    28  type AddressType byte
    29  
    30  // UndefinedAddressType undefined
    31  const UndefinedAddressType AddressType = 0x00
    32  
    33  // address type enum
    34  const (
    35  	AccountAddress AddressType = 0x57 + iota
    36  	ContractAddress
    37  )
    38  
    39  // const
    40  const (
    41  	Padding byte = 0x19
    42  
    43  	NebulasFaith = 'n'
    44  )
    45  
    46  const (
    47  	// AddressPaddingLength the length of headpadding in byte
    48  	AddressPaddingLength = 1
    49  	// AddressPaddingIndex the index of headpadding bytes
    50  	AddressPaddingIndex = 0
    51  
    52  	// AddressTypeLength the length of address type in byte
    53  	AddressTypeLength = 1
    54  	// AddressTypeIndex the index of address type bytes
    55  	AddressTypeIndex = 1
    56  
    57  	// AddressDataLength the length of data of address in byte.
    58  	AddressDataLength = 20
    59  
    60  	// AddressChecksumLength the checksum of address in byte.
    61  	AddressChecksumLength = 4
    62  
    63  	// AddressLength the length of address in byte.
    64  	AddressLength = AddressPaddingLength + AddressTypeLength + AddressDataLength + AddressChecksumLength
    65  	// AddressDataEnd the end of the address data
    66  	AddressDataEnd = 22
    67  
    68  	// AddressBase58Length length of base58(Address.address)
    69  	AddressBase58Length = 35
    70  	// PublicKeyDataLength length of public key
    71  	PublicKeyDataLength = 65
    72  )
    73  
    74  // Address design of nebulas address
    75  /*
    76  [Account Address]
    77  Similar to Bitcoin and Ethereum, Nebulas also adopts elliptic curve algorithm as its basic encryption algorithm for Nebulas accounts.
    78  The address is derived from **public key**, which is in turn derived from the **private key** that encrypted with user's **passphrase**.
    79  Also we have the checksum design aiming to prevent a user from sending _Nas_ to a wrong user account accidentally due to entry of several incorrect characters.
    80  
    81  The specific calculation formula is as follows:
    82  
    83  	Content = ripemd160( sha3_256( Public Key ) )
    84  	CheckSum = sha3_256( 0x19 + 0x57 + Content )[0:4]
    85  	Address = base58( 0x19 + 0x57 + Content + CheckSum )
    86  
    87   	0x57 is a one-byte "type code" for account address, 0x19 is a one-byte fixed "padding"
    88  
    89  The ripemd160 digest of SHA3-256 digest of a public key serve as the major component of an address,
    90  for which another SHA3-256 digest should be conducted and the first 4 bytes should be used as a checksum. For example:
    91  The final address of Nebulas Wallet should be:  n1TV3sU6jyzR4rJ1D7jCAmtVGSntJagXZHC
    92  
    93  [Smart Contract Address]
    94  Calculating contract address differs slightly from account, passphrase of contract sender is not required but address & nonce.
    95  For more information, plz check (https://github.com/nebulasio/wiki/blob/master/tutorials/%5BEnglish%5D%20Nebulas%20101%20-%2003%20Smart%20Contracts%20JavaScript.md) and [rpc.sendTransaction](https://github.com/nebulasio/wiki/blob/master/rpc.md#sendtransaction).
    96  Calculation formula is as follows:
    97  
    98  	Content = ripemd160( sha3_256( tx.from, tx.nonce ) )
    99  	CheckSum = sha3_256( 0x19 + 0x58 + Content )[0:4]
   100  	Address = base58( 0x19 + 0x58 + Content + CheckSum )
   101  
   102  	0x58 is a one-byte "type code" for smart contract address, 0x19 is a one-byte fixed "padding"
   103  
   104  
   105  [TODO]
   106  In addition to standard address with 50 characters, we also support extended address in order to ensure the security of transfers conducted by users.
   107  The traditional bank transfer design is used for reference:
   108  In the process of a bank transfer, bank card number of the remittee should be verified, in addition to which the remitter must enter the name of the remittee.
   109  The transfer can be correctly processed only when the bank card number and the name match each other.
   110  The generating algorithm for extended address is described as follows:
   111  
   112    ExtData = Utf8Bytes({Nickname or any string})
   113    ExtHash = sha3_256(Data + ExtData)[0:2]
   114    ExtAddress = Account Address + Hex(ExtHash)
   115  
   116  An extended address is generated through addition of 2-byte extended verification to the end of a standard address and contains a total of 54 characters.
   117  Addition of extended information allows the addition of another element verification to the Nebulas Wallet APP. For example:
   118  
   119  	The standard address of Alice’s wallet is  0xdf4d22611412132d3e9bd322f82e2940674ec1bc03b20e40, and the extended address after addition of the nickname "alice" should be 0xdf4d22611412132d3e9bd322f82e2940674ec1bc03b20e40e345.
   120  	Alice tells Bob the extended address 0xdf4d22611412132d3e9bd322f82e2940674ec1bc03b20e40e345 and her nickname alice.
   121  	Bob enters 0xdf4d22611412132d3e9bd322f82e2940674ec1bc03b20e40e345 and alice in the Wallet App.
   122  	The Wallet App verifies the consistency between the wallet address and the nickname in order to avoid the circumstance that Bob enters the account number of another user by mistake.
   123  */
   124  type Address struct {
   125  	address byteutils.Hash
   126  }
   127  
   128  // ContractTxFrom tx from
   129  type ContractTxFrom []byte
   130  
   131  // ContractTxNonce tx nonce
   132  type ContractTxNonce []byte
   133  
   134  // Bytes returns address bytes
   135  func (a *Address) Bytes() []byte {
   136  	return a.address
   137  }
   138  
   139  // String returns address string
   140  func (a *Address) String() string {
   141  	return base58.Encode(a.address)
   142  }
   143  
   144  // Equals compare two Address. True is equal, otherwise false.
   145  func (a *Address) Equals(b *Address) bool {
   146  	if a == nil {
   147  		return b == nil
   148  	}
   149  	if b == nil {
   150  		return false
   151  	}
   152  	return a.address.Equals(b.address)
   153  }
   154  
   155  // Type return the type of address.
   156  func (a *Address) Type() AddressType {
   157  	if len(a.address) <= AddressTypeIndex {
   158  		return UndefinedAddressType
   159  	}
   160  	return AddressType(a.address[AddressTypeIndex])
   161  }
   162  
   163  // NewAddress create new #Address according to data bytes.
   164  func newAddress(t AddressType, args ...[]byte) (*Address, error) {
   165  	if len(args) == 0 {
   166  		return nil, ErrInvalidArgument
   167  	}
   168  
   169  	switch t {
   170  	case AccountAddress, ContractAddress:
   171  	default:
   172  		return nil, ErrInvalidArgument
   173  	}
   174  
   175  	buffer := make([]byte, AddressLength)
   176  	buffer[AddressPaddingIndex] = Padding
   177  	buffer[AddressTypeIndex] = byte(t)
   178  
   179  	sha := hash.Sha3256(args...)
   180  	content := hash.Ripemd160(sha)
   181  	copy(buffer[AddressTypeIndex+1:AddressDataEnd], content)
   182  
   183  	cs := checkSum(buffer[:AddressDataEnd])
   184  	copy(buffer[AddressDataEnd:], cs)
   185  
   186  	return &Address{address: buffer}, nil
   187  }
   188  
   189  // NewAddressFromPublicKey return new address from publickey bytes
   190  func NewAddressFromPublicKey(s []byte) (*Address, error) {
   191  	if len(s) != PublicKeyDataLength {
   192  		return nil, ErrInvalidArgument
   193  	}
   194  	return newAddress(AccountAddress, s)
   195  }
   196  
   197  // NewContractAddressFromData return new contract address from bytes.
   198  func NewContractAddressFromData(from ContractTxFrom, nonce ContractTxNonce) (*Address, error) {
   199  	if len(from) == 0 || len(nonce) == 0 {
   200  		return nil, ErrInvalidArgument
   201  	}
   202  	return newAddress(ContractAddress, from, nonce)
   203  }
   204  
   205  // AddressParse parse address string.
   206  func AddressParse(s string) (*Address, error) {
   207  	if len(s) != AddressBase58Length || s[0] != NebulasFaith {
   208  		return nil, ErrInvalidAddressFormat
   209  	}
   210  
   211  	return AddressParseFromBytes(base58.Decode(s))
   212  }
   213  
   214  // AddressParseFromBytes parse address from bytes.
   215  func AddressParseFromBytes(b []byte) (*Address, error) {
   216  	if len(b) != AddressLength || b[AddressPaddingIndex] != Padding {
   217  		return nil, ErrInvalidAddressFormat
   218  	}
   219  
   220  	switch AddressType(b[AddressTypeIndex]) {
   221  	case AccountAddress, ContractAddress:
   222  	default:
   223  		return nil, ErrInvalidAddressType
   224  	}
   225  
   226  	if !byteutils.Equal(checkSum(b[:AddressDataEnd]), b[AddressDataEnd:]) {
   227  		return nil, ErrInvalidAddressChecksum
   228  	}
   229  
   230  	return &Address{address: b}, nil
   231  }
   232  
   233  func checkSum(data []byte) []byte {
   234  	return hash.Sha3256(data)[:AddressChecksumLength]
   235  }