// Code extracted from vendor/github.com/ethereum/go-ethereum/common/types.go package types import ( "encoding/hex" "fmt" "reflect" ) const ( // HashLength is the expected length of the hash HashLength = 32 ) // Hash represents the 32 byte Keccak256 hash of arbitrary data. type Hash [HashLength]byte var hashT = reflect.TypeOf(Hash{}) // Encode encodes b as a hex string with 0x prefix. func encode(b []byte) string { enc := make([]byte, len(b)*2+2) copy(enc, "0x") hex.Encode(enc[2:], b) return string(enc) } // FromHex returns the bytes represented by the hexadecimal string s. // s may be prefixed with "0x". func FromHex(s string) []byte { if has0xPrefix(s) { s = s[2:] } if len(s)%2 == 1 { s = "0" + s } return Hex2Bytes(s) } // 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)) } // Hex converts a hash to a hex string. func (h *Hash) Hex() string { return encode(h[:]) } // Bytes gets the byte representation of the underlying hash. func (h Hash) Bytes() []byte { return h[:] } // 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() } // 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) } // UnmarshalText parses a hash in hex syntax. func (h *Hash) UnmarshalText(input []byte) error { return UnmarshalFixedText("Hash", input, h[:]) } // UnmarshalJSON parses a hash in hex syntax. func (h *Hash) UnmarshalJSON(input []byte) error { return UnmarshalFixedJSON(hashT, input, h[:]) } // MarshalText returns the hex representation of h. func (h Hash) MarshalText() ([]byte, error) { return HexBytes(h[:]).MarshalText() } // 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 } // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out // determines the required input length. This function is commonly used to implement the // UnmarshalJSON method for fixed-size types. func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error { if !isString(input) { return errNonString(typ) } return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ) } // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out // determines the required input length. This function is commonly used to implement the // UnmarshalText method for fixed-size types. func UnmarshalFixedText(typname string, input, out []byte) error { raw, err := checkText(input, true) if err != nil { return err } if len(raw)/2 != len(out) { return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) } // Pre-verify syntax before modifying out. for _, b := range raw { if decodeNibble(b) == badNibble { return ErrSyntax } } _, err = hex.Decode(out, raw) return err }