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 }