// Copyright 2015 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package common import ( "bytes" "encoding/hex" "fmt" "math/big" "math/rand" "reflect" "github.com/XinFinOrg/XDPoSChain/common/hexutil" "github.com/XinFinOrg/XDPoSChain/crypto/sha3" ) const ( HashLength = 32 AddressLength = 20 BlockSigners = "xdc0000000000000000000000000000000000000089" MasternodeVotingSMC = "xdc0000000000000000000000000000000000000088" RandomizeSMC = "xdc0000000000000000000000000000000000000090" FoudationAddr = "xdc0000000000000000000000000000000000000068" TeamAddr = "xdc0000000000000000000000000000000000000099" XDCXAddr = "xdc0000000000000000000000000000000000000091" TradingStateAddr = "xdc0000000000000000000000000000000000000092" XDCXLendingAddress = "xdc0000000000000000000000000000000000000093" XDCXLendingFinalizedTradeAddress = "xdc0000000000000000000000000000000000000094" XDCNativeAddress = "xdc0000000000000000000000000000000000000001" LendingLockAddress = "xdc0000000000000000000000000000000000000011" VoteMethod = "0x6dd7d8ea" UnvoteMethod = "0x02aa9be2" ProposeMethod = "0x01267951" ResignMethod = "0xae6e43f5" SignMethod = "0xe341eaa4" XDCXApplyMethod = "0xc6b32f34" XDCZApplyMethod = "0xc6b32f34" ) var ( BlockSignersBinary = Address{19: 0x89} // xdc0000000000000000000000000000000000000089 MasternodeVotingSMCBinary = Address{19: 0x88} // xdc0000000000000000000000000000000000000088 RandomizeSMCBinary = Address{19: 0x90} // xdc0000000000000000000000000000000000000090 FoudationAddrBinary = Address{19: 0x68} // xdc0000000000000000000000000000000000000068 TeamAddrBinary = Address{19: 0x99} // xdc0000000000000000000000000000000000000099 XDCXAddrBinary = Address{19: 0x91} // xdc0000000000000000000000000000000000000091 TradingStateAddrBinary = Address{19: 0x92} // xdc0000000000000000000000000000000000000092 XDCXLendingAddressBinary = Address{19: 0x93} // xdc0000000000000000000000000000000000000093 XDCXLendingFinalizedTradeAddressBinary = Address{19: 0x94} // xdc0000000000000000000000000000000000000094 XDCNativeAddressBinary = Address{19: 0x01} // xdc0000000000000000000000000000000000000001 LendingLockAddressBinary = Address{19: 0x11} // xdc0000000000000000000000000000000000000011 ) var ( hashT = reflect.TypeOf(Hash{}) addressT = reflect.TypeOf(Address{}) ) // Hash represents the 32 byte Keccak256 hash of arbitrary data. type Hash [HashLength]byte type Vote struct { Masternode Address Voter Address } // BytesToHash sets b to hash. // If b is larger than len(h), b will be cropped from the left. func BytesToHash(b []byte) Hash { var h Hash h.SetBytes(b) return h } func StringToHash(s string) Hash { return BytesToHash([]byte(s)) } // BigToHash sets byte representation of b to hash. // If b is larger than len(h), b will be cropped from the left. func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) } func Uint64ToHash(b uint64) Hash { return BytesToHash(new(big.Int).SetUint64(b).Bytes()) } // HexToHash sets byte representation of s to hash. // If b is larger than len(h), b will be cropped from the left. func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) } // Cmp compares two hashes. func (h Hash) Cmp(other Hash) int { return bytes.Compare(h[:], other[:]) } // IsZero returns if a Hash is empty func (h Hash) IsZero() bool { return h == Hash{} } // Get the string representation of the underlying hash func (h Hash) Str() string { return string(h[:]) } // Bytes gets the byte representation of the underlying hash. func (h Hash) Bytes() []byte { return h[:] } // Big converts a hash to a big integer. func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) } // Hex converts a hash to a hex string. func (h Hash) Hex() string { return hexutil.Encode(h[:]) } // TerminalString implements log.TerminalStringer, formatting a string for console // output during logging. func (h Hash) TerminalString() string { return fmt.Sprintf("%x…%x", h[:3], h[29:]) } // String implements the stringer interface and is used also by the logger when // doing full logging into a file. func (h Hash) String() string { return h.Hex() } // Format implements fmt.Formatter, forcing the byte slice to be formatted as is, // without going through the stringer interface used for logging. func (h Hash) Format(s fmt.State, c rune) { fmt.Fprintf(s, "%"+string(c), h[:]) } // UnmarshalText parses a hash in hex syntax. func (h *Hash) UnmarshalText(input []byte) error { return hexutil.UnmarshalFixedText("Hash", input, h[:]) } // UnmarshalJSON parses a hash in hex syntax. func (h *Hash) UnmarshalJSON(input []byte) error { return hexutil.UnmarshalFixedJSON(hashT, input, h[:]) } // MarshalText returns the hex representation of h. func (h Hash) MarshalText() ([]byte, error) { return hexutil.Bytes(h[:]).MarshalText() } // SetBytes sets the hash to the value of b. // If b is larger than len(h), b will be cropped from the left. func (h *Hash) SetBytes(b []byte) { if len(b) > len(h) { b = b[len(b)-HashLength:] } copy(h[HashLength-len(b):], b) } // Set string `s` to h. If s is larger than len(h) s will be cropped (from left) to fit. func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) } // Sets h to other func (h *Hash) Set(other Hash) { copy(h[:], other[:]) } // Generate implements testing/quick.Generator. func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value { m := rand.Intn(len(h)) for i := len(h) - 1; i > m; i-- { h[i] = byte(rand.Uint32()) } return reflect.ValueOf(h) } func EmptyHash(h Hash) bool { return h == Hash{} } // UnprefixedHash allows marshaling a Hash without 0x prefix. type UnprefixedHash Hash // UnmarshalText decodes the hash from hex. The 0x prefix is optional. func (h *UnprefixedHash) UnmarshalText(input []byte) error { return hexutil.UnmarshalFixedUnprefixedText("UnprefixedHash", input, h[:]) } // MarshalText encodes the hash as hex. func (h UnprefixedHash) MarshalText() ([]byte, error) { return []byte(hex.EncodeToString(h[:])), nil } /////////// Address // Address represents the 20 byte address of an Ethereum account. type Address [AddressLength]byte func BytesToAddress(b []byte) Address { var a Address a.SetBytes(b) return a } func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) } // BigToAddress returns Address with byte values of b. // If b is larger than len(h), b will be cropped from the left. func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) } // HexToAddress returns Address with byte values of s. // If s is larger than len(h), s will be cropped from the left. func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) } // IsHexAddress verifies whether a string can represent a valid hex-encoded // Ethereum address or not. func IsHexAddress(s string) bool { if hasXDCPrefix(s) { s = s[3:] } if hasHexPrefix(s) { s = s[2:] } return len(s) == 2*AddressLength && isHex(s) } // IsZero returns if a address is empty func (a Address) IsZero() bool { return a == Address{} } // Get the string representation of the underlying address func (a Address) Str() string { return string(a[:]) } func (a Address) Bytes() []byte { return a[:] } func (a Address) Big() *big.Int { return new(big.Int).SetBytes(a[:]) } func (a Address) Hash() Hash { return BytesToHash(a[:]) } // Hex returns an EIP55-compliant hex string representation of the address. func (a Address) Hex() string { unchecksummed := hex.EncodeToString(a[:]) sha := sha3.NewKeccak256() sha.Write([]byte(unchecksummed)) hash := sha.Sum(nil) result := []byte(unchecksummed) for i := 0; i < len(result); i++ { hashByte := hash[i/2] if i%2 == 0 { hashByte = hashByte >> 4 } else { hashByte &= 0xf } if result[i] > '9' && hashByte > 7 { result[i] -= 32 } } return "xdc" + string(result) } // String implements the stringer interface and is used also by the logger. func (a Address) String() string { return a.Hex() } // Format implements fmt.Formatter, forcing the byte slice to be formatted as is, // without going through the stringer interface used for logging. func (a Address) Format(s fmt.State, c rune) { fmt.Fprintf(s, "%"+string(c), a[:]) } // Sets the address to the value of b. If b is larger than len(a) it will panic func (a *Address) SetBytes(b []byte) { if len(b) > len(a) { b = b[len(b)-AddressLength:] } copy(a[AddressLength-len(b):], b) } // Set string `s` to a. If s is larger than len(a) it will panic func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) } // Sets a to other func (a *Address) Set(other Address) { copy(a[:], other[:]) } // MarshalText returns the hex representation of a. func (a Address) MarshalText() ([]byte, error) { // Handle '0x' or 'xdc' prefix here. if Enable0xPrefix { return hexutil.Bytes(a[:]).MarshalText() } else { return hexutil.Bytes(a[:]).MarshalXDCText() } } // UnmarshalText parses a hash in hex syntax. func (a *Address) UnmarshalText(input []byte) error { return hexutil.UnmarshalFixedText("Address", input, a[:]) } // UnmarshalJSON parses a hash in hex syntax. func (a *Address) UnmarshalJSON(input []byte) error { return hexutil.UnmarshalFixedJSON(addressT, input, a[:]) } // UnprefixedHash allows marshaling an Address without 0x prefix. type UnprefixedAddress Address // UnmarshalText decodes the address from hex. The 0x prefix is optional. func (a *UnprefixedAddress) UnmarshalText(input []byte) error { return hexutil.UnmarshalFixedUnprefixedText("UnprefixedAddress", input, a[:]) } // MarshalText encodes the address as hex. func (a UnprefixedAddress) MarshalText() ([]byte, error) { return []byte(hex.EncodeToString(a[:])), nil } // Extract validators from byte array. func RemoveItemFromArray(array []Address, items []Address) []Address { // Create newArray to stop append change array value newArray := make([]Address, len(array)) copy(newArray, array) if len(items) == 0 { return newArray } for _, item := range items { for i := len(newArray) - 1; i >= 0; i-- { if newArray[i] == item { newArray = append(newArray[:i], newArray[i+1:]...) } } } return newArray } // Extract validators from byte array. func ExtractAddressToBytes(penalties []Address) []byte { data := []byte{} for _, signer := range penalties { data = append(data, signer[:]...) } return data } func ExtractAddressFromBytes(bytePenalties []byte) []Address { if bytePenalties != nil && len(bytePenalties) < AddressLength { return []Address{} } penalties := make([]Address, len(bytePenalties)/AddressLength) for i := 0; i < len(penalties); i++ { copy(penalties[i][:], bytePenalties[i*AddressLength:]) } return penalties }