github.com/0xPolygon/supernets2-node@v0.0.0-20230711153321-2fe574524eaa/state/helper.go (about) 1 package state 2 3 import ( 4 "fmt" 5 "math/big" 6 "strconv" 7 8 "github.com/0xPolygon/supernets2-node/hex" 9 "github.com/0xPolygon/supernets2-node/log" 10 "github.com/ethereum/go-ethereum/core/types" 11 "github.com/ethereum/go-ethereum/rlp" 12 ) 13 14 const ( 15 double = 2 16 ether155V = 27 17 etherPre155V = 35 18 ) 19 20 // EncodeTransactions RLP encodes the given transactions 21 func EncodeTransactions(txs []types.Transaction) ([]byte, error) { 22 var batchL2Data []byte 23 24 for _, tx := range txs { 25 v, r, s := tx.RawSignatureValues() 26 sign := 1 - (v.Uint64() & 1) 27 28 nonce, gasPrice, gas, to, value, data, chainID := tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.ChainId() 29 log.Debug(nonce, " ", gasPrice, " ", gas, " ", to, " ", value, " ", len(data), " ", chainID) 30 31 rlpFieldsToEncode := []interface{}{ 32 nonce, 33 gasPrice, 34 gas, 35 to, 36 value, 37 data, 38 } 39 40 if tx.ChainId().Uint64() > 0 { 41 rlpFieldsToEncode = append(rlpFieldsToEncode, chainID) 42 rlpFieldsToEncode = append(rlpFieldsToEncode, uint(0)) 43 rlpFieldsToEncode = append(rlpFieldsToEncode, uint(0)) 44 } 45 46 txCodedRlp, err := rlp.EncodeToBytes(rlpFieldsToEncode) 47 if err != nil { 48 return nil, err 49 } 50 51 newV := new(big.Int).Add(big.NewInt(ether155V), big.NewInt(int64(sign))) 52 newRPadded := fmt.Sprintf("%064s", r.Text(hex.Base)) 53 newSPadded := fmt.Sprintf("%064s", s.Text(hex.Base)) 54 newVPadded := fmt.Sprintf("%02s", newV.Text(hex.Base)) 55 txData, err := hex.DecodeString(hex.EncodeToString(txCodedRlp) + newRPadded + newSPadded + newVPadded) 56 if err != nil { 57 return nil, err 58 } 59 60 batchL2Data = append(batchL2Data, txData...) 61 } 62 63 return batchL2Data, nil 64 } 65 66 // EncodeTransaction RLP encodes the given transaction 67 func EncodeTransaction(tx types.Transaction) ([]byte, error) { 68 transactions := []types.Transaction{tx} 69 return EncodeTransactions(transactions) 70 } 71 72 // EncodeUnsignedTransaction RLP encodes the given unsigned transaction 73 func EncodeUnsignedTransaction(tx types.Transaction, chainID uint64, forcedNonce *uint64) ([]byte, error) { 74 v, _ := new(big.Int).SetString("0x1c", 0) 75 r, _ := new(big.Int).SetString("0xa54492cfacf71aef702421b7fbc70636537a7b2fbe5718c5ed970a001bb7756b", 0) 76 s, _ := new(big.Int).SetString("0x2e9fb27acc75955b898f0b12ec52aa34bf08f01db654374484b80bf12f0d841e", 0) 77 78 sign := 1 - (v.Uint64() & 1) 79 80 nonce, gasPrice, gas, to, value, data, chainID := tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID //nolint:gomnd 81 log.Debug(nonce, " ", gasPrice, " ", gas, " ", to, " ", value, " ", len(data), " ", chainID) 82 83 if forcedNonce != nil { 84 nonce = *forcedNonce 85 log.Debug("Forced nonce: ", nonce) 86 } 87 88 txCodedRlp, err := rlp.EncodeToBytes([]interface{}{ 89 nonce, 90 gasPrice, 91 gas, 92 to, 93 value, 94 data, 95 big.NewInt(0).SetUint64(chainID), uint(0), uint(0), 96 }) 97 98 if err != nil { 99 return nil, err 100 } 101 102 newV := new(big.Int).Add(big.NewInt(ether155V), big.NewInt(int64(sign))) 103 newRPadded := fmt.Sprintf("%064s", r.Text(hex.Base)) 104 newSPadded := fmt.Sprintf("%064s", s.Text(hex.Base)) 105 newVPadded := fmt.Sprintf("%02s", newV.Text(hex.Base)) 106 txData, err := hex.DecodeString(hex.EncodeToString(txCodedRlp) + newRPadded + newSPadded + newVPadded) 107 if err != nil { 108 return nil, err 109 } 110 111 return txData, nil 112 } 113 114 // DecodeTxs extracts Transactions for its encoded form 115 func DecodeTxs(txsData []byte) ([]types.Transaction, []byte, error) { 116 // Process coded txs 117 var pos uint64 118 var txs []types.Transaction 119 const ( 120 headerByteLength uint64 = 1 121 sLength uint64 = 32 122 rLength uint64 = 32 123 vLength uint64 = 1 124 c0 uint64 = 192 // 192 is c0. This value is defined by the rlp protocol 125 ff uint64 = 255 // max value of rlp header 126 shortRlp uint64 = 55 // length of the short rlp codification 127 f7 uint64 = 247 // 192 + 55 = c0 + shortRlp 128 ) 129 txDataLength := uint64(len(txsData)) 130 if txDataLength == 0 { 131 return txs, txsData, nil 132 } 133 for pos < txDataLength { 134 num, err := strconv.ParseUint(hex.EncodeToString(txsData[pos:pos+1]), hex.Base, hex.BitSize64) 135 if err != nil { 136 log.Debug("error parsing header length: ", err) 137 return []types.Transaction{}, txsData, err 138 } 139 // First byte is the length and must be ignored 140 if num < c0 { 141 log.Debugf("error num < c0 : %d, %d", num, c0) 142 return []types.Transaction{}, txsData, ErrInvalidData 143 } 144 length := uint64(num - c0) 145 if length > shortRlp { // If rlp is bigger than length 55 146 // n is the length of the rlp data without the header (1 byte) for example "0xf7" 147 if (pos + 1 + num - f7) > txDataLength { 148 log.Debug("error parsing length: ", err) 149 return []types.Transaction{}, txsData, err 150 } 151 n, err := strconv.ParseUint(hex.EncodeToString(txsData[pos+1:pos+1+num-f7]), hex.Base, hex.BitSize64) // +1 is the header. For example 0xf7 152 if err != nil { 153 log.Debug("error parsing length: ", err) 154 return []types.Transaction{}, txsData, err 155 } 156 if n+num < f7 { 157 log.Debug("error n + num < f7: ", err) 158 return []types.Transaction{}, txsData, ErrInvalidData 159 } 160 length = n + num - f7 // num - f7 is the header. For example 0xf7 161 } 162 163 endPos := pos + length + rLength + sLength + vLength + headerByteLength 164 165 if endPos > txDataLength { 166 err := fmt.Errorf("endPos %d is bigger than txDataLength %d", endPos, txDataLength) 167 log.Debug("error parsing header: ", err) 168 return []types.Transaction{}, txsData, ErrInvalidData 169 } 170 171 fullDataTx := txsData[pos:endPos] 172 txInfo := txsData[pos : pos+length+headerByteLength] 173 rData := txsData[pos+length+headerByteLength : pos+length+rLength+headerByteLength] 174 sData := txsData[pos+length+rLength+headerByteLength : pos+length+rLength+sLength+headerByteLength] 175 vData := txsData[pos+length+rLength+sLength+headerByteLength : endPos] 176 177 pos = endPos 178 179 // Decode rlpFields 180 var rlpFields [][]byte 181 err = rlp.DecodeBytes(txInfo, &rlpFields) 182 if err != nil { 183 log.Error("error decoding tx Bytes: ", err, ". fullDataTx: ", hex.EncodeToString(fullDataTx), "\n tx: ", hex.EncodeToString(txInfo), "\n Txs received: ", hex.EncodeToString(txsData)) 184 return []types.Transaction{}, txsData, ErrInvalidData 185 } 186 187 legacyTx, err := RlpFieldsToLegacyTx(rlpFields, vData, rData, sData) 188 if err != nil { 189 log.Debug("error creating tx from rlp fields: ", err, ". fullDataTx: ", hex.EncodeToString(fullDataTx), "\n tx: ", hex.EncodeToString(txInfo), "\n Txs received: ", hex.EncodeToString(txsData)) 190 return []types.Transaction{}, txsData, err 191 } 192 193 tx := types.NewTx(legacyTx) 194 txs = append(txs, *tx) 195 } 196 return txs, txsData, nil 197 } 198 199 // DecodeTx decodes a string rlp tx representation into a types.Transaction instance 200 func DecodeTx(encodedTx string) (*types.Transaction, error) { 201 b, err := hex.DecodeHex(encodedTx) 202 if err != nil { 203 return nil, err 204 } 205 206 tx := new(types.Transaction) 207 if err := tx.UnmarshalBinary(b); err != nil { 208 return nil, err 209 } 210 return tx, nil 211 } 212 213 func generateReceipt(blockNumber *big.Int, processedTx *ProcessTransactionResponse) *types.Receipt { 214 receipt := &types.Receipt{ 215 Type: uint8(processedTx.Type), 216 PostState: processedTx.StateRoot.Bytes(), 217 CumulativeGasUsed: processedTx.GasUsed, 218 BlockNumber: blockNumber, 219 GasUsed: processedTx.GasUsed, 220 TxHash: processedTx.Tx.Hash(), 221 TransactionIndex: 0, 222 ContractAddress: processedTx.CreateAddress, 223 Logs: processedTx.Logs, 224 } 225 226 // TODO: this fix is temporary while the Executor is returning a 227 // different Tx hash for the TxHash, Log.TxHash and Tx.Hash(). 228 // At the moment, the processedTx.TxHash and Log[n].TxHash are 229 // returning a different hash than the Hash of the transaction 230 // sent to be processed by the Executor. 231 // The processedTx.Tx.Hash() is correct. 232 for i := 0; i < len(receipt.Logs); i++ { 233 receipt.Logs[i].TxHash = processedTx.Tx.Hash() 234 } 235 if processedTx.RomError == nil { 236 receipt.Status = types.ReceiptStatusSuccessful 237 } else { 238 receipt.Status = types.ReceiptStatusFailed 239 } 240 241 return receipt 242 } 243 244 func toPostgresInterval(duration string) (string, error) { 245 unit := duration[len(duration)-1] 246 var pgUnit string 247 248 switch unit { 249 case 's': 250 pgUnit = "second" 251 case 'm': 252 pgUnit = "minute" 253 case 'h': 254 pgUnit = "hour" 255 default: 256 return "", ErrUnsupportedDuration 257 } 258 259 isMoreThanOne := duration[0] != '1' || len(duration) > 2 //nolint:gomnd 260 if isMoreThanOne { 261 pgUnit = pgUnit + "s" 262 } 263 264 return fmt.Sprintf("%s %s", duration[:len(duration)-1], pgUnit), nil 265 }