github.com/ledgerwatch/erigon-lib@v1.0.0/common/hash.go (about)

     1  /*
     2  Copyright 2021 Erigon contributors
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  package common
    17  
    18  import (
    19  	"bytes"
    20  	"database/sql/driver"
    21  	"encoding/hex"
    22  	"fmt"
    23  	"math/big"
    24  	"math/rand"
    25  	"reflect"
    26  
    27  	"github.com/ledgerwatch/erigon-lib/common/hexutility"
    28  	"github.com/ledgerwatch/erigon-lib/common/length"
    29  )
    30  
    31  var (
    32  	hashT = reflect.TypeOf(Hash{})
    33  )
    34  
    35  const (
    36  	hexPrefix = `0x`
    37  )
    38  
    39  // Hash represents the 32 byte Keccak256 hash of arbitrary data.
    40  type Hash [length.Hash]byte
    41  
    42  // BytesToHash sets b to hash.
    43  // If b is larger than len(h), b will be cropped from the left.
    44  func BytesToHash(b []byte) Hash {
    45  	var h Hash
    46  	h.SetBytes(b)
    47  	return h
    48  }
    49  
    50  // CastToHash - sets b to hash
    51  // If b is larger than len(h), b will be cropped from the left.
    52  // panics if input is shorter than 32 bytes, see https://go.dev/doc/go1.17#language
    53  // faster than BytesToHash
    54  func CastToHash(b []byte) Hash { return *(*Hash)(b) }
    55  
    56  // BigToHash sets byte representation of b to hash.
    57  // If b is larger than len(h), b will be cropped from the left.
    58  func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
    59  
    60  // HexToHash sets byte representation of s to hash.
    61  // If b is larger than len(h), b will be cropped from the left.
    62  func HexToHash(s string) Hash { return BytesToHash(hexutility.FromHex(s)) }
    63  
    64  // Bytes gets the byte representation of the underlying hash.
    65  func (h Hash) Bytes() []byte { return h[:] }
    66  
    67  // Big converts a hash to a big integer.
    68  func (h Hash) Big() *big.Int { return new(big.Int).SetBytes(h[:]) }
    69  
    70  // Hex converts a hash to a hex string.
    71  func (h Hash) Hex() string { return hexutility.Encode(h[:]) }
    72  
    73  // TerminalString implements log.TerminalStringer, formatting a string for console
    74  // output during logging.
    75  func (h Hash) TerminalString() string {
    76  	return fmt.Sprintf("%x…%x", h[:3], h[29:])
    77  }
    78  
    79  // String implements the stringer interface and is used also by the logger when
    80  // doing full logging into a file.
    81  func (h Hash) String() string {
    82  	return h.Hex()
    83  }
    84  
    85  // Format implements fmt.Formatter.
    86  // Hash supports the %v, %s, %v, %x, %X and %d format verbs.
    87  func (h Hash) Format(s fmt.State, c rune) {
    88  	hexb := make([]byte, 2+len(h)*2)
    89  	copy(hexb, "0x")
    90  	hex.Encode(hexb[2:], h[:])
    91  
    92  	switch c {
    93  	case 'x', 'X':
    94  		if !s.Flag('#') {
    95  			hexb = hexb[2:]
    96  		}
    97  		if c == 'X' {
    98  			hexb = bytes.ToUpper(hexb)
    99  		}
   100  		fallthrough
   101  	case 'v', 's':
   102  		s.Write(hexb)
   103  	case 'q':
   104  		q := []byte{'"'}
   105  		s.Write(q)
   106  		s.Write(hexb)
   107  		s.Write(q)
   108  	case 'd':
   109  		fmt.Fprint(s, ([len(h)]byte)(h))
   110  	default:
   111  		fmt.Fprintf(s, "%%!%c(hash=%x)", c, h)
   112  	}
   113  }
   114  
   115  // UnmarshalText parses a hash in hex syntax.
   116  func (h *Hash) UnmarshalText(input []byte) error {
   117  	return hexutility.UnmarshalFixedText("Hash", input, h[:])
   118  }
   119  
   120  // UnmarshalJSON parses a hash in hex syntax.
   121  func (h *Hash) UnmarshalJSON(input []byte) error {
   122  	return hexutility.UnmarshalFixedJSON(hashT, input, h[:])
   123  }
   124  
   125  // MarshalText returns the hex representation of h.
   126  func (h Hash) MarshalText() ([]byte, error) {
   127  	b := h[:]
   128  	result := make([]byte, len(b)*2+2)
   129  	copy(result, hexPrefix)
   130  	hex.Encode(result[2:], b)
   131  	return result, nil
   132  }
   133  
   134  // SetBytes sets the hash to the value of b.
   135  // If b is larger than len(h), b will be cropped from the left.
   136  func (h *Hash) SetBytes(b []byte) {
   137  	if len(b) > len(h) {
   138  		b = b[len(b)-length.Hash:]
   139  	}
   140  
   141  	copy(h[length.Hash-len(b):], b)
   142  }
   143  
   144  // Generate implements testing/quick.Generator.
   145  func (h Hash) Generate(rand *rand.Rand, size int) reflect.Value {
   146  	m := rand.Intn(len(h))
   147  	for i := len(h) - 1; i > m; i-- {
   148  		h[i] = byte(rand.Uint32())
   149  	}
   150  	return reflect.ValueOf(h)
   151  }
   152  
   153  // Scan implements Scanner for database/sql.
   154  func (h *Hash) Scan(src interface{}) error {
   155  	srcB, ok := src.([]byte)
   156  	if !ok {
   157  		return fmt.Errorf("can't scan %T into Hash", src)
   158  	}
   159  	if len(srcB) != length.Hash {
   160  		return fmt.Errorf("can't scan []byte of len %d into Hash, want %d", len(srcB), length.Hash)
   161  	}
   162  	copy(h[:], srcB)
   163  	return nil
   164  }
   165  
   166  // Value implements valuer for database/sql.
   167  func (h Hash) Value() (driver.Value, error) {
   168  	return h[:], nil
   169  }
   170  
   171  func FromHex(in string) []byte {
   172  	return hexutility.MustDecodeHex(in)
   173  }
   174  
   175  type CodeRecord struct {
   176  	BlockNumber uint64
   177  	TxNumber    uint64
   178  	CodeHash    Hash
   179  }