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 }