mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 21:26:42 +00:00
crypto, common, xeth: implemented checksum addresses
This commit is contained in:
parent
cd81356ace
commit
b9e93b69a7
6 changed files with 138 additions and 19 deletions
|
|
@ -117,6 +117,33 @@ func (a *Address) Set(other Address) {
|
|||
}
|
||||
}
|
||||
|
||||
// ChecksumAddress is an address with an included checksum. A checksum address
|
||||
// is usually made out of SHA3(A) + A
|
||||
type ChecksumAddress struct {
|
||||
Checksum [4]byte
|
||||
Address
|
||||
}
|
||||
|
||||
// HexToChecksumAddress converts a hex checksum address to a ChecksumAddress
|
||||
// type
|
||||
func HexToChecksumAddress(s string) ChecksumAddress {
|
||||
if len(s) > 2 && s[:2] == "0x" {
|
||||
s = s[2:]
|
||||
}
|
||||
if len(s) != 48 {
|
||||
return ChecksumAddress{}
|
||||
}
|
||||
|
||||
addr := ChecksumAddress{[4]byte{}, HexToAddress(s[4:])}
|
||||
copy(addr.Checksum[:], Hex2Bytes(s[:8]))
|
||||
return addr
|
||||
}
|
||||
|
||||
// Hex returns the hexadecimal representation of a checksum address
|
||||
func (ca ChecksumAddress) Hex() string {
|
||||
return "0x" + Bytes2Hex(ca.Checksum[:]) + ca.Address.Hex()[2:]
|
||||
}
|
||||
|
||||
// PP Pretty Prints a byte slice in the following format:
|
||||
// hex(value[:4])...(hex[len(value)-4:])
|
||||
func PP(value []byte) string {
|
||||
|
|
|
|||
44
crypto/address.go
Normal file
44
crypto/address.go
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"fmt"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
)
|
||||
|
||||
const checksumLen = 4
|
||||
|
||||
// Creates an ethereum address given the bytes and the nonce
|
||||
func CreateAddress(b common.Address, nonce uint64) common.Address {
|
||||
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
|
||||
return common.BytesToAddress(Sha3(data)[12:])
|
||||
}
|
||||
|
||||
// ChecksumAddress creates modifies an address to include a checksum
|
||||
func ChecksumAddress(addr common.Address) common.ChecksumAddress {
|
||||
var checksumaddr common.ChecksumAddress
|
||||
checksumaddr.Address = addr
|
||||
copy(checksumaddr.Checksum[:], Sha3(addr.Bytes())[:4])
|
||||
|
||||
return checksumaddr
|
||||
}
|
||||
|
||||
// ValidateAddress validates the given address. It must include a checksum
|
||||
// on the end. It returns the address or an error if the checksum or length of
|
||||
// the input failed.
|
||||
func ValidateAddress(addr common.ChecksumAddress) (common.Address, error) {
|
||||
if !bytes.Equal(Sha3(addr.Address[:])[:4], addr.Checksum[:]) {
|
||||
return common.Address{}, fmt.Errorf("checksum failed for address %x (%x)", addr.Address, addr.Checksum)
|
||||
}
|
||||
|
||||
return addr.Address, nil
|
||||
}
|
||||
|
||||
// PubkeyToAddress converts a std ecdsa public key to a common.Address
|
||||
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
|
||||
pubBytes := FromECDSAPub(&p)
|
||||
return common.BytesToAddress(Sha3(pubBytes[1:])[12:])
|
||||
}
|
||||
33
crypto/address_test.go
Normal file
33
crypto/address_test.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
)
|
||||
|
||||
func TestChecksum(t *testing.T) {
|
||||
var addr common.Address
|
||||
addr[0] = 1
|
||||
|
||||
checksumed := ChecksumAddress(addr)
|
||||
if !bytes.Equal(checksumed.Checksum[:], Sha3(checksumed.Address[:])[:4]) {
|
||||
t.Error("checksum failed")
|
||||
}
|
||||
|
||||
addr, err := ValidateAddress(checksumed)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if addr != addr {
|
||||
t.Error("address failed")
|
||||
}
|
||||
|
||||
checksumed.Checksum[3] |= 1
|
||||
_, err = ValidateAddress(checksumed)
|
||||
if err == nil {
|
||||
t.Error("checksum success, should have failed")
|
||||
}
|
||||
}
|
||||
|
|
@ -38,7 +38,6 @@ import (
|
|||
"github.com/ethereum/go-ethereum/crypto/ecies"
|
||||
"github.com/ethereum/go-ethereum/crypto/secp256k1"
|
||||
"github.com/ethereum/go-ethereum/crypto/sha3"
|
||||
"github.com/ethereum/go-ethereum/rlp"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
"golang.org/x/crypto/ripemd160"
|
||||
)
|
||||
|
|
@ -68,13 +67,6 @@ func Sha3Hash(data ...[]byte) (h common.Hash) {
|
|||
return h
|
||||
}
|
||||
|
||||
// Creates an ethereum address given the bytes and the nonce
|
||||
func CreateAddress(b common.Address, nonce uint64) common.Address {
|
||||
data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
|
||||
return common.BytesToAddress(Sha3(data)[12:])
|
||||
//return Sha3(common.NewValue([]interface{}{b, nonce}).Encode())[12:]
|
||||
}
|
||||
|
||||
func Sha256(data []byte) []byte {
|
||||
hash := sha256.Sum256(data)
|
||||
|
||||
|
|
@ -332,8 +324,3 @@ func PKCS7Unpad(in []byte) []byte {
|
|||
}
|
||||
return in[:len(in)-int(padding)]
|
||||
}
|
||||
|
||||
func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
|
||||
pubBytes := FromECDSAPub(&p)
|
||||
return common.BytesToAddress(Sha3(pubBytes[1:])[12:])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2256,6 +2256,17 @@ var isAddress = function (address) {
|
|||
return /^(0x)?[0-9a-f]{40}$/.test(address);
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the given string is an address
|
||||
*
|
||||
* @method isChecksumAddress
|
||||
* @param {String} address the given HEX adress
|
||||
* @return {Boolean}
|
||||
*/
|
||||
var isChecksumAddress = function (address) {
|
||||
return /^(0x)?[0-9a-f]{48}$/.test(address);
|
||||
};
|
||||
|
||||
/**
|
||||
* Transforms given string to valid 20 bytes-length addres with 0x prefix
|
||||
*
|
||||
|
|
@ -2378,6 +2389,7 @@ module.exports = {
|
|||
isBigNumber: isBigNumber,
|
||||
isStrictAddress: isStrictAddress,
|
||||
isAddress: isAddress,
|
||||
isChecksumAddress: isChecksumAddress,
|
||||
isFunction: isFunction,
|
||||
isString: isString,
|
||||
isObject: isObject,
|
||||
|
|
@ -2513,6 +2525,7 @@ web3.toBigNumber = utils.toBigNumber;
|
|||
web3.toWei = utils.toWei;
|
||||
web3.fromWei = utils.fromWei;
|
||||
web3.isAddress = utils.isAddress;
|
||||
web3.isChecksumAddress = utils.isChecksumAddress;
|
||||
web3.isIBAN = utils.isIBAN;
|
||||
web3.sha3 = sha3;
|
||||
web3.createBatch = function () {
|
||||
|
|
@ -3735,8 +3748,10 @@ var inputAddressFormatter = function (address) {
|
|||
return address;
|
||||
} else if (utils.isAddress(address)) {
|
||||
return '0x' + address;
|
||||
} else if (utils.isChecksumAddress(address)) {
|
||||
return address;
|
||||
}
|
||||
throw 'invalid address';
|
||||
throw 'invalid address'
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
|
|
|
|||
23
xeth/xeth.go
23
xeth/xeth.go
|
|
@ -389,7 +389,7 @@ func (self *XEth) Accounts() []string {
|
|||
accounts, _ := self.backend.AccountManager().Accounts()
|
||||
accountAddresses := make([]string, len(accounts))
|
||||
for i, ac := range accounts {
|
||||
accountAddresses[i] = ac.Address.Hex()
|
||||
accountAddresses[i] = crypto.ChecksumAddress(ac.Address).Hex()
|
||||
}
|
||||
return accountAddresses
|
||||
}
|
||||
|
|
@ -890,7 +890,6 @@ func (self *XEth) Frontend() Frontend {
|
|||
}
|
||||
|
||||
func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
|
||||
|
||||
// this minimalistic recoding is enough (works for natspec.js)
|
||||
var jsontx = fmt.Sprintf(`{"params":[{"to":"%s","data": "%s"}]}`, toStr, codeStr)
|
||||
if !self.ConfirmTransaction(jsontx) {
|
||||
|
|
@ -898,13 +897,27 @@ func (self *XEth) Transact(fromStr, toStr, nonceStr, valueStr, gasStr, gasPriceS
|
|||
return "", err
|
||||
}
|
||||
|
||||
if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) {
|
||||
return "", errors.New("Invalid address")
|
||||
var (
|
||||
to common.Address
|
||||
err error
|
||||
)
|
||||
// If the address is larges than 20 bytes (+ 0x) assume a checksum
|
||||
// address and verify.
|
||||
if len(toStr) > 42 {
|
||||
checkAddr := common.HexToChecksumAddress(toStr)
|
||||
to, err = crypto.ValidateAddress(checkAddr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
} else {
|
||||
if len(toStr) > 0 && toStr != "0x" && !isAddress(toStr) {
|
||||
return "", errors.New("Invalid address")
|
||||
}
|
||||
to = common.HexToAddress(toStr)
|
||||
}
|
||||
|
||||
var (
|
||||
from = common.HexToAddress(fromStr)
|
||||
to = common.HexToAddress(toStr)
|
||||
value = common.Big(valueStr)
|
||||
gas *big.Int
|
||||
price *big.Int
|
||||
|
|
|
|||
Loading…
Reference in a new issue