github.com/amazechain/amc@v0.1.3/modules/utils.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package modules
    18  
    19  import (
    20  	"encoding/binary"
    21  	"errors"
    22  	"fmt"
    23  	"github.com/amazechain/amc/common/types"
    24  )
    25  
    26  const NumberLength = 8
    27  const Incarnation = 2
    28  
    29  var configPrefix = []byte("chainConfig-")
    30  
    31  // EncodeBlockNumber encodes a block number as big endian uint64
    32  func EncodeBlockNumber(number uint64) []byte {
    33  	enc := make([]byte, NumberLength)
    34  	binary.BigEndian.PutUint64(enc, number)
    35  	return enc
    36  }
    37  
    38  var ErrInvalidSize = errors.New("bit endian number has an invalid size")
    39  
    40  func DecodeBlockNumber(number []byte) (uint64, error) {
    41  	if len(number) != NumberLength {
    42  		return 0, fmt.Errorf("%w: %d", ErrInvalidSize, len(number))
    43  	}
    44  	return binary.BigEndian.Uint64(number), nil
    45  }
    46  
    47  // HeaderKey = num (uint64 big endian) + hash
    48  func HeaderKey(number uint64, hash types.Hash) []byte {
    49  	k := make([]byte, NumberLength+types.HashLength)
    50  	binary.BigEndian.PutUint64(k, number)
    51  	copy(k[NumberLength:], hash[:])
    52  	return k
    53  }
    54  
    55  // BlockBodyKey = num (uint64 big endian) + hash
    56  func BlockBodyKey(number uint64, hash types.Hash) []byte {
    57  	k := make([]byte, NumberLength+types.HashLength)
    58  	binary.BigEndian.PutUint64(k, number)
    59  	copy(k[NumberLength:], hash[:])
    60  	return k
    61  }
    62  
    63  func BodyStorageValue(baseTx uint64, txAmount uint32) []byte {
    64  	v := make([]byte, 8+4)
    65  	binary.BigEndian.PutUint64(v, baseTx)
    66  	binary.BigEndian.PutUint32(v[8:], txAmount)
    67  	return v
    68  }
    69  
    70  // LogKey = blockN (uint64 big endian) + txId (uint32 big endian)
    71  func LogKey(blockNumber uint64, txId uint32) []byte {
    72  	newK := make([]byte, 8+4)
    73  	binary.BigEndian.PutUint64(newK, blockNumber)
    74  	binary.BigEndian.PutUint32(newK[8:], txId)
    75  	return newK
    76  }
    77  
    78  func PlainParseCompositeStorageKey(compositeKey []byte) (types.Address, uint16, types.Hash) {
    79  	prefixLen := types.AddressLength + types.IncarnationLength
    80  	addr, inc := PlainParseStoragePrefix(compositeKey[:prefixLen])
    81  	var key types.Hash
    82  	copy(key[:], compositeKey[prefixLen:prefixLen+types.HashLength])
    83  	return addr, inc, key
    84  }
    85  
    86  // AddrHash + incarnation + StorageHashPrefix
    87  func GenerateCompositeStoragePrefix(addressHash []byte, incarnation uint16, storageHashPrefix []byte) []byte {
    88  	key := make([]byte, types.HashLength+types.IncarnationLength+len(storageHashPrefix))
    89  	copy(key, addressHash)
    90  	binary.BigEndian.PutUint16(key[types.HashLength:], incarnation)
    91  	copy(key[types.HashLength+types.IncarnationLength:], storageHashPrefix)
    92  	return key
    93  }
    94  
    95  // address hash + incarnation prefix
    96  func GenerateStoragePrefix(addressHash []byte, incarnation uint16) []byte {
    97  	prefix := make([]byte, types.HashLength+NumberLength)
    98  	copy(prefix, addressHash)
    99  	binary.BigEndian.PutUint16(prefix[types.HashLength:], incarnation)
   100  	return prefix
   101  }
   102  
   103  // address hash + incarnation prefix (for plain state)
   104  func PlainGenerateStoragePrefix(address []byte, incarnation uint16) []byte {
   105  	prefix := make([]byte, types.AddressLength+NumberLength)
   106  	copy(prefix, address)
   107  	binary.BigEndian.PutUint16(prefix[types.AddressLength:], incarnation)
   108  	return prefix
   109  }
   110  
   111  // AddrHash + incarnation + KeyHash
   112  // For contract storage (for plain state)
   113  func PlainGenerateCompositeStorageKey(address []byte, incarnation uint16, key []byte) []byte {
   114  	compositeKey := make([]byte, types.AddressLength+types.IncarnationLength+types.HashLength)
   115  	copy(compositeKey, address)
   116  	binary.BigEndian.PutUint16(compositeKey[types.AddressLength:], incarnation)
   117  	copy(compositeKey[types.AddressLength+types.IncarnationLength:], key)
   118  	return compositeKey
   119  }
   120  
   121  func StorageIndexChunkKey(key []byte, blockNumber uint64) []byte {
   122  	//remove incarnation and add block number
   123  	blockNumBytes := make([]byte, types.AddressLength+types.HashLength+8)
   124  	copy(blockNumBytes, key[:types.AddressLength])
   125  	copy(blockNumBytes[types.AddressLength:], key[types.AddressLength+types.IncarnationLength:])
   126  	binary.BigEndian.PutUint64(blockNumBytes[types.AddressLength+types.HashLength:], blockNumber)
   127  
   128  	return blockNumBytes
   129  }
   130  
   131  func AccountIndexChunkKey(key []byte, blockNumber uint64) []byte {
   132  	blockNumBytes := make([]byte, types.AddressLength+8)
   133  	copy(blockNumBytes, key)
   134  	binary.BigEndian.PutUint64(blockNumBytes[types.AddressLength:], blockNumber)
   135  
   136  	return blockNumBytes
   137  }
   138  
   139  func PlainParseStoragePrefix(prefix []byte) (types.Address, uint16) {
   140  	var addr types.Address
   141  	copy(addr[:], prefix[:types.AddressLength])
   142  	inc := binary.BigEndian.Uint16(prefix[types.AddressLength : types.AddressLength+types.IncarnationLength])
   143  	return addr, inc
   144  }
   145  
   146  func CompositeKeyWithoutIncarnation(key []byte) []byte {
   147  	if len(key) == types.HashLength*2+types.IncarnationLength {
   148  		kk := make([]byte, types.HashLength*2)
   149  		copy(kk, key[:types.HashLength])
   150  		copy(kk[types.HashLength:], key[types.HashLength+types.IncarnationLength:])
   151  		return kk
   152  	}
   153  	if len(key) == types.AddressLength+types.HashLength+types.IncarnationLength {
   154  		kk := make([]byte, types.AddressLength+types.HashLength)
   155  		copy(kk, key[:types.AddressLength])
   156  		copy(kk[types.AddressLength:], key[types.AddressLength+types.IncarnationLength:])
   157  		return kk
   158  	}
   159  	return key
   160  }
   161  
   162  // ConfigKey = configPrefix + hash
   163  func ConfigKey(hash types.Hash) []byte {
   164  	return append(configPrefix, hash.Bytes()...)
   165  }