github.com/ledgerwatch/erigon-lib@v1.0.0/types/txn.go (about) 1 /* 2 Copyright 2021 The 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 17 package types 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "errors" 23 "fmt" 24 "hash" 25 "io" 26 "math/bits" 27 "sort" 28 29 gokzg4844 "github.com/crate-crypto/go-kzg-4844" 30 "github.com/holiman/uint256" 31 "github.com/ledgerwatch/secp256k1" 32 "golang.org/x/crypto/sha3" 33 34 "github.com/ledgerwatch/erigon-lib/common" 35 "github.com/ledgerwatch/erigon-lib/common/fixedgas" 36 "github.com/ledgerwatch/erigon-lib/common/length" 37 "github.com/ledgerwatch/erigon-lib/common/u256" 38 "github.com/ledgerwatch/erigon-lib/crypto" 39 "github.com/ledgerwatch/erigon-lib/gointerfaces/types" 40 "github.com/ledgerwatch/erigon-lib/rlp" 41 ) 42 43 type TxParseConfig struct { 44 ChainID uint256.Int 45 } 46 47 // TxParseContext is object that is required to parse transactions and turn transaction payload into TxSlot objects 48 // usage of TxContext helps avoid extra memory allocations 49 type TxParseContext struct { 50 Keccak2 hash.Hash 51 Keccak1 hash.Hash 52 validateRlp func([]byte) error 53 ChainID uint256.Int // Signature values 54 R uint256.Int // Signature values 55 S uint256.Int // Signature values 56 V uint256.Int // Signature values 57 ChainIDMul uint256.Int 58 DeriveChainID uint256.Int // pre-allocated variable to calculate Sub(&ctx.v, &ctx.chainIDMul) 59 cfg TxParseConfig 60 buf [65]byte // buffer needs to be enough for hashes (32 bytes) and for public key (65 bytes) 61 Sig [65]byte 62 Sighash [32]byte 63 withSender bool 64 allowPreEip2s bool // Allow s > secp256k1n/2; see EIP-2 65 chainIDRequired bool 66 IsProtected bool 67 } 68 69 func NewTxParseContext(chainID uint256.Int) *TxParseContext { 70 if chainID.IsZero() { 71 panic("wrong chainID") 72 } 73 ctx := &TxParseContext{ 74 withSender: true, 75 Keccak1: sha3.NewLegacyKeccak256(), 76 Keccak2: sha3.NewLegacyKeccak256(), 77 } 78 79 // behave as of London enabled 80 ctx.cfg.ChainID.Set(&chainID) 81 ctx.ChainIDMul.Mul(&chainID, u256.N2) 82 return ctx 83 } 84 85 // TxSlot contains information extracted from an Ethereum transaction, which is enough to manage it inside the transaction. 86 // Also, it contains some auxillary information, like ephemeral fields, and indices within priority queues 87 type TxSlot struct { 88 Rlp []byte // Is set to nil after flushing to db, frees memory, later we look for it in the db, if needed 89 Value uint256.Int // Value transferred by the transaction 90 Tip uint256.Int // Maximum tip that transaction is giving to miner/block proposer 91 FeeCap uint256.Int // Maximum fee that transaction burns and gives to the miner/block proposer 92 SenderID uint64 // SenderID - require external mapping to it's address 93 Nonce uint64 // Nonce of the transaction 94 DataLen int // Length of transaction's data (for calculation of intrinsic gas) 95 DataNonZeroLen int 96 AlAddrCount int // Number of addresses in the access list 97 AlStorCount int // Number of storage keys in the access list 98 Gas uint64 // Gas limit of the transaction 99 IDHash [32]byte // Transaction hash for the purposes of using it as a transaction Id 100 Traced bool // Whether transaction needs to be traced throughout transaction pool code and generate debug printing 101 Creation bool // Set to true if "To" field of the transaction is not set 102 Type byte // Transaction type 103 Size uint32 // Size of the payload 104 105 // EIP-4844: Shard Blob Transactions 106 BlobFeeCap uint256.Int // max_fee_per_blob_gas 107 BlobHashes []common.Hash 108 Blobs [][]byte 109 Commitments []gokzg4844.KZGCommitment 110 Proofs []gokzg4844.KZGProof 111 } 112 113 const ( 114 LegacyTxType byte = 0 115 AccessListTxType byte = 1 // EIP-2930 116 DynamicFeeTxType byte = 2 // EIP-1559 117 BlobTxType byte = 3 // EIP-4844 118 ) 119 120 var ErrParseTxn = fmt.Errorf("%w transaction", rlp.ErrParse) 121 122 var ErrRejected = errors.New("rejected") 123 var ErrAlreadyKnown = errors.New("already known") 124 var ErrRlpTooBig = errors.New("txn rlp too big") 125 126 // Set the RLP validate function 127 func (ctx *TxParseContext) ValidateRLP(f func(txnRlp []byte) error) { ctx.validateRlp = f } 128 129 // Set the with sender flag 130 func (ctx *TxParseContext) WithSender(v bool) { ctx.withSender = v } 131 132 // Set the AllowPreEIP2s flag 133 func (ctx *TxParseContext) WithAllowPreEip2s(v bool) { ctx.allowPreEip2s = v } 134 135 // Set ChainID-Required flag in the Parse context and return it 136 func (ctx *TxParseContext) ChainIDRequired() *TxParseContext { 137 ctx.chainIDRequired = true 138 return ctx 139 } 140 141 func PeekTransactionType(serialized []byte) (byte, error) { 142 dataPos, _, legacy, err := rlp.Prefix(serialized, 0) 143 if err != nil { 144 return LegacyTxType, fmt.Errorf("%w: size Prefix: %s", ErrParseTxn, err) //nolint 145 } 146 if legacy { 147 return LegacyTxType, nil 148 } 149 return serialized[dataPos], nil 150 } 151 152 // ParseTransaction extracts all the information from the transactions's payload (RLP) necessary to build TxSlot. 153 // It also performs syntactic validation of the transactions. 154 // wrappedWithBlobs means that for blob (type 3) transactions the full version with blobs/commitments/proofs is expected 155 // (see https://eips.ethereum.org/EIPS/eip-4844#networking). 156 func (ctx *TxParseContext) ParseTransaction(payload []byte, pos int, slot *TxSlot, sender []byte, hasEnvelope, wrappedWithBlobs bool, validateHash func([]byte) error) (p int, err error) { 157 if len(payload) == 0 { 158 return 0, fmt.Errorf("%w: empty rlp", ErrParseTxn) 159 } 160 if ctx.withSender && len(sender) != 20 { 161 return 0, fmt.Errorf("%w: expect sender buffer of len 20", ErrParseTxn) 162 } 163 164 // Legacy transactions have list Prefix, whereas EIP-2718 transactions have string Prefix 165 // therefore we assign the first returned value of Prefix function (list) to legacy variable 166 dataPos, dataLen, legacy, err := rlp.Prefix(payload, pos) 167 if err != nil { 168 return 0, fmt.Errorf("%w: size Prefix: %s", ErrParseTxn, err) //nolint 169 } 170 // This handles the transactions coming from other Erigon peers of older versions, which add 0x80 (empty) transactions into packets 171 if dataLen == 0 { 172 return 0, fmt.Errorf("%w: transaction must be either 1 list or 1 string", ErrParseTxn) 173 } 174 if dataLen == 1 && !legacy { 175 if hasEnvelope { 176 return 0, fmt.Errorf("%w: expected envelope in the payload, got %x", ErrParseTxn, payload[dataPos:dataPos+dataLen]) 177 } 178 } 179 180 p = dataPos 181 182 var wrapperDataPos, wrapperDataLen int 183 184 // If it is non-legacy transaction, the transaction type follows, and then the the list 185 if !legacy { 186 slot.Type = payload[p] 187 if slot.Type > BlobTxType { 188 return 0, fmt.Errorf("%w: unknown transaction type: %d", ErrParseTxn, slot.Type) 189 } 190 p++ 191 if p >= len(payload) { 192 return 0, fmt.Errorf("%w: unexpected end of payload after txType", ErrParseTxn) 193 } 194 dataPos, dataLen, err = rlp.List(payload, p) 195 if err != nil { 196 return 0, fmt.Errorf("%w: envelope Prefix: %s", ErrParseTxn, err) //nolint 197 } 198 // For legacy transaction, the entire payload in expected to be in "rlp" field 199 // whereas for non-legacy, only the content of the envelope (start with position p) 200 slot.Rlp = payload[p-1 : dataPos+dataLen] 201 202 if slot.Type == BlobTxType && wrappedWithBlobs { 203 p = dataPos 204 wrapperDataPos = dataPos 205 wrapperDataLen = dataLen 206 dataPos, dataLen, err = rlp.List(payload, dataPos) 207 if err != nil { 208 return 0, fmt.Errorf("%w: wrapped blob tx: %s", ErrParseTxn, err) //nolint 209 } 210 } 211 } else { 212 slot.Type = LegacyTxType 213 slot.Rlp = payload[pos : dataPos+dataLen] 214 } 215 216 p, err = ctx.parseTransactionBody(payload, pos, p, slot, sender, validateHash) 217 if err != nil { 218 return p, err 219 } 220 221 if slot.Type == BlobTxType && wrappedWithBlobs { 222 if p != dataPos+dataLen { 223 return 0, fmt.Errorf("%w: unexpected leftover after blob tx body", ErrParseTxn) 224 } 225 226 dataPos, dataLen, err = rlp.List(payload, p) 227 if err != nil { 228 return 0, fmt.Errorf("%w: blobs len: %s", ErrParseTxn, err) //nolint 229 } 230 blobPos := dataPos 231 for blobPos < dataPos+dataLen { 232 blobPos, err = rlp.StringOfLen(payload, blobPos, fixedgas.BlobSize) 233 if err != nil { 234 return 0, fmt.Errorf("%w: blob: %s", ErrParseTxn, err) //nolint 235 } 236 slot.Blobs = append(slot.Blobs, payload[blobPos:blobPos+fixedgas.BlobSize]) 237 blobPos += fixedgas.BlobSize 238 } 239 if blobPos != dataPos+dataLen { 240 return 0, fmt.Errorf("%w: extraneous space in blobs", ErrParseTxn) 241 } 242 p = blobPos 243 244 dataPos, dataLen, err = rlp.List(payload, p) 245 if err != nil { 246 return 0, fmt.Errorf("%w: commitments len: %s", ErrParseTxn, err) //nolint 247 } 248 commitmentPos := dataPos 249 for commitmentPos < dataPos+dataLen { 250 commitmentPos, err = rlp.StringOfLen(payload, commitmentPos, 48) 251 if err != nil { 252 return 0, fmt.Errorf("%w: commitment: %s", ErrParseTxn, err) //nolint 253 } 254 var commitment gokzg4844.KZGCommitment 255 copy(commitment[:], payload[commitmentPos:commitmentPos+48]) 256 slot.Commitments = append(slot.Commitments, commitment) 257 commitmentPos += 48 258 } 259 if commitmentPos != dataPos+dataLen { 260 return 0, fmt.Errorf("%w: extraneous space in commitments", ErrParseTxn) 261 } 262 p = commitmentPos 263 264 dataPos, dataLen, err = rlp.List(payload, p) 265 if err != nil { 266 return 0, fmt.Errorf("%w: proofs len: %s", ErrParseTxn, err) //nolint 267 } 268 proofPos := dataPos 269 for proofPos < dataPos+dataLen { 270 proofPos, err = rlp.StringOfLen(payload, proofPos, 48) 271 if err != nil { 272 return 0, fmt.Errorf("%w: proof: %s", ErrParseTxn, err) //nolint 273 } 274 var proof gokzg4844.KZGProof 275 copy(proof[:], payload[proofPos:proofPos+48]) 276 slot.Proofs = append(slot.Proofs, proof) 277 proofPos += 48 278 } 279 if proofPos != dataPos+dataLen { 280 return 0, fmt.Errorf("%w: extraneous space in proofs", ErrParseTxn) 281 } 282 p = proofPos 283 284 if p != wrapperDataPos+wrapperDataLen { 285 return 0, fmt.Errorf("%w: extraneous elements in blobs wrapper", ErrParseTxn) 286 } 287 } 288 289 slot.Size = uint32(p - pos) 290 return p, err 291 } 292 293 func (ctx *TxParseContext) parseTransactionBody(payload []byte, pos, p0 int, slot *TxSlot, sender []byte, validateHash func([]byte) error) (p int, err error) { 294 p = p0 295 legacy := slot.Type == LegacyTxType 296 297 // Compute transaction hash 298 ctx.Keccak1.Reset() 299 ctx.Keccak2.Reset() 300 if !legacy { 301 typeByte := []byte{slot.Type} 302 if _, err = ctx.Keccak1.Write(typeByte); err != nil { 303 return 0, fmt.Errorf("%w: computing IdHash (hashing type Prefix): %s", ErrParseTxn, err) //nolint 304 } 305 if _, err = ctx.Keccak2.Write(typeByte); err != nil { 306 return 0, fmt.Errorf("%w: computing signHash (hashing type Prefix): %s", ErrParseTxn, err) //nolint 307 } 308 dataPos, dataLen, err := rlp.List(payload, p) 309 if err != nil { 310 return 0, fmt.Errorf("%w: envelope Prefix: %s", ErrParseTxn, err) //nolint 311 } 312 // Hash the content of envelope, not the full payload 313 if _, err = ctx.Keccak1.Write(payload[p : dataPos+dataLen]); err != nil { 314 return 0, fmt.Errorf("%w: computing IdHash (hashing the envelope): %s", ErrParseTxn, err) //nolint 315 } 316 p = dataPos 317 } 318 319 if ctx.validateRlp != nil { 320 if err := ctx.validateRlp(slot.Rlp); err != nil { 321 return p, err 322 } 323 } 324 325 // Remember where signing hash data begins (it will need to be wrapped in an RLP list) 326 sigHashPos := p 327 if !legacy { 328 p, err = rlp.U256(payload, p, &ctx.ChainID) 329 if err != nil { 330 return 0, fmt.Errorf("%w: chainId len: %s", ErrParseTxn, err) //nolint 331 } 332 if ctx.ChainID.IsZero() { // zero indicates that the chain ID was not specified in the tx. 333 if ctx.chainIDRequired { 334 return 0, fmt.Errorf("%w: chainID is required", ErrParseTxn) 335 } 336 ctx.ChainID.Set(&ctx.cfg.ChainID) 337 } 338 if !ctx.ChainID.Eq(&ctx.cfg.ChainID) { 339 return 0, fmt.Errorf("%w: %s, %d (expected %d)", ErrParseTxn, "invalid chainID", ctx.ChainID.Uint64(), ctx.cfg.ChainID.Uint64()) 340 } 341 } 342 // Next follows the nonce, which we need to parse 343 p, slot.Nonce, err = rlp.U64(payload, p) 344 if err != nil { 345 return 0, fmt.Errorf("%w: nonce: %s", ErrParseTxn, err) //nolint 346 } 347 // Next follows gas price or tip 348 p, err = rlp.U256(payload, p, &slot.Tip) 349 if err != nil { 350 return 0, fmt.Errorf("%w: tip: %s", ErrParseTxn, err) //nolint 351 } 352 // Next follows feeCap, but only for dynamic fee transactions, for legacy transaction, it is 353 // equal to tip 354 if slot.Type < DynamicFeeTxType { 355 slot.FeeCap = slot.Tip 356 } else { 357 p, err = rlp.U256(payload, p, &slot.FeeCap) 358 if err != nil { 359 return 0, fmt.Errorf("%w: feeCap: %s", ErrParseTxn, err) //nolint 360 } 361 } 362 // Next follows gas 363 p, slot.Gas, err = rlp.U64(payload, p) 364 if err != nil { 365 return 0, fmt.Errorf("%w: gas: %s", ErrParseTxn, err) //nolint 366 } 367 // Next follows the destination address (if present) 368 dataPos, dataLen, err := rlp.String(payload, p) 369 if err != nil { 370 return 0, fmt.Errorf("%w: to len: %s", ErrParseTxn, err) //nolint 371 } 372 if dataLen != 0 && dataLen != 20 { 373 return 0, fmt.Errorf("%w: unexpected length of to field: %d", ErrParseTxn, dataLen) 374 } 375 376 // Only note if To field is empty or not 377 slot.Creation = dataLen == 0 378 p = dataPos + dataLen 379 // Next follows value 380 p, err = rlp.U256(payload, p, &slot.Value) 381 if err != nil { 382 return 0, fmt.Errorf("%w: value: %s", ErrParseTxn, err) //nolint 383 } 384 // Next goes data, but we are only interesting in its length 385 dataPos, dataLen, err = rlp.String(payload, p) 386 if err != nil { 387 return 0, fmt.Errorf("%w: data len: %s", ErrParseTxn, err) //nolint 388 } 389 slot.DataLen = dataLen 390 391 // Zero and non-zero bytes are priced differently 392 slot.DataNonZeroLen = 0 393 for _, byt := range payload[dataPos : dataPos+dataLen] { 394 if byt != 0 { 395 slot.DataNonZeroLen++ 396 } 397 } 398 399 p = dataPos + dataLen 400 401 // Next follows access list for non-legacy transactions, we are only interesting in number of addresses and storage keys 402 if !legacy { 403 dataPos, dataLen, err = rlp.List(payload, p) 404 if err != nil { 405 return 0, fmt.Errorf("%w: access list len: %s", ErrParseTxn, err) //nolint 406 } 407 tuplePos := dataPos 408 for tuplePos < dataPos+dataLen { 409 var tupleLen int 410 tuplePos, tupleLen, err = rlp.List(payload, tuplePos) 411 if err != nil { 412 return 0, fmt.Errorf("%w: tuple len: %s", ErrParseTxn, err) //nolint 413 } 414 var addrPos int 415 addrPos, err = rlp.StringOfLen(payload, tuplePos, 20) 416 if err != nil { 417 return 0, fmt.Errorf("%w: tuple addr len: %s", ErrParseTxn, err) //nolint 418 } 419 slot.AlAddrCount++ 420 var storagePos, storageLen int 421 storagePos, storageLen, err = rlp.List(payload, addrPos+20) 422 if err != nil { 423 return 0, fmt.Errorf("%w: storage key list len: %s", ErrParseTxn, err) //nolint 424 } 425 skeyPos := storagePos 426 for skeyPos < storagePos+storageLen { 427 skeyPos, err = rlp.StringOfLen(payload, skeyPos, 32) 428 if err != nil { 429 return 0, fmt.Errorf("%w: tuple storage key len: %s", ErrParseTxn, err) //nolint 430 } 431 slot.AlStorCount++ 432 skeyPos += 32 433 } 434 if skeyPos != storagePos+storageLen { 435 return 0, fmt.Errorf("%w: extraneous space in the tuple after storage key list", ErrParseTxn) 436 } 437 tuplePos += tupleLen 438 } 439 if tuplePos != dataPos+dataLen { 440 return 0, fmt.Errorf("%w: extraneous space in the access list after all tuples", ErrParseTxn) 441 } 442 p = dataPos + dataLen 443 } 444 if slot.Type == BlobTxType { 445 p, err = rlp.U256(payload, p, &slot.BlobFeeCap) 446 if err != nil { 447 return 0, fmt.Errorf("%w: blob fee cap: %s", ErrParseTxn, err) //nolint 448 } 449 dataPos, dataLen, err = rlp.List(payload, p) 450 if err != nil { 451 return 0, fmt.Errorf("%w: blob hashes len: %s", ErrParseTxn, err) //nolint 452 } 453 hashPos := dataPos 454 for hashPos < dataPos+dataLen { 455 var hash common.Hash 456 hashPos, err = rlp.ParseHash(payload, hashPos, hash[:]) 457 if err != nil { 458 return 0, fmt.Errorf("%w: blob hash: %s", ErrParseTxn, err) //nolint 459 } 460 slot.BlobHashes = append(slot.BlobHashes, hash) 461 } 462 if hashPos != dataPos+dataLen { 463 return 0, fmt.Errorf("%w: extraneous space in the blob versioned hashes", ErrParseTxn) 464 } 465 p = dataPos + dataLen 466 } 467 // This is where the data for Sighash ends 468 // Next follows V of the signature 469 var vByte byte 470 sigHashEnd := p 471 sigHashLen := uint(sigHashEnd - sigHashPos) 472 var chainIDBits, chainIDLen int 473 if legacy { 474 p, err = rlp.U256(payload, p, &ctx.V) 475 if err != nil { 476 return 0, fmt.Errorf("%w: V: %s", ErrParseTxn, err) //nolint 477 } 478 ctx.IsProtected = ctx.V.Eq(u256.N27) || ctx.V.Eq(u256.N28) 479 // Compute chainId from V 480 if ctx.IsProtected { 481 // Do not add chain id and two extra zeros 482 vByte = byte(ctx.V.Uint64() - 27) 483 ctx.ChainID.Set(&ctx.cfg.ChainID) 484 } else { 485 ctx.ChainID.Sub(&ctx.V, u256.N35) 486 ctx.ChainID.Rsh(&ctx.ChainID, 1) 487 if !ctx.ChainID.Eq(&ctx.cfg.ChainID) { 488 return 0, fmt.Errorf("%w: %s, %d (expected %d)", ErrParseTxn, "invalid chainID", ctx.ChainID.Uint64(), ctx.cfg.ChainID.Uint64()) 489 } 490 491 chainIDBits = ctx.ChainID.BitLen() 492 if chainIDBits <= 7 { 493 chainIDLen = 1 494 } else { 495 chainIDLen = common.BitLenToByteLen(chainIDBits) // It is always < 56 bytes 496 sigHashLen++ // For chainId len Prefix 497 } 498 sigHashLen += uint(chainIDLen) // For chainId 499 sigHashLen += 2 // For two extra zeros 500 501 ctx.DeriveChainID.Sub(&ctx.V, &ctx.ChainIDMul) 502 vByte = byte(ctx.DeriveChainID.Sub(&ctx.DeriveChainID, u256.N8).Uint64() - 27) 503 } 504 } else { 505 var v uint64 506 p, v, err = rlp.U64(payload, p) 507 if err != nil { 508 return 0, fmt.Errorf("%w: V: %s", ErrParseTxn, err) //nolint 509 } 510 if v > 1 { 511 return 0, fmt.Errorf("%w: V is loo large: %d", ErrParseTxn, v) 512 } 513 vByte = byte(v) 514 ctx.IsProtected = true 515 } 516 517 // Next follows R of the signature 518 p, err = rlp.U256(payload, p, &ctx.R) 519 if err != nil { 520 return 0, fmt.Errorf("%w: R: %s", ErrParseTxn, err) //nolint 521 } 522 // New follows S of the signature 523 p, err = rlp.U256(payload, p, &ctx.S) 524 if err != nil { 525 return 0, fmt.Errorf("%w: S: %s", ErrParseTxn, err) //nolint 526 } 527 528 // For legacy transactions, hash the full payload 529 if legacy { 530 if _, err = ctx.Keccak1.Write(payload[pos:p]); err != nil { 531 return 0, fmt.Errorf("%w: computing IdHash: %s", ErrParseTxn, err) //nolint 532 } 533 } 534 //ctx.keccak1.Sum(slot.IdHash[:0]) 535 _, _ = ctx.Keccak1.(io.Reader).Read(slot.IDHash[:32]) 536 if validateHash != nil { 537 if err := validateHash(slot.IDHash[:32]); err != nil { 538 return p, err 539 } 540 } 541 542 if !ctx.withSender { 543 return p, nil 544 } 545 546 if !crypto.TransactionSignatureIsValid(vByte, &ctx.R, &ctx.S, ctx.allowPreEip2s && legacy) { 547 return 0, fmt.Errorf("%w: invalid v, r, s: %d, %s, %s", ErrParseTxn, vByte, &ctx.R, &ctx.S) 548 } 549 550 // Computing sigHash (hash used to recover sender from the signature) 551 // Write len Prefix to the Sighash 552 if sigHashLen < 56 { 553 ctx.buf[0] = byte(sigHashLen) + 192 554 if _, err := ctx.Keccak2.Write(ctx.buf[:1]); err != nil { 555 return 0, fmt.Errorf("%w: computing signHash (hashing len Prefix): %s", ErrParseTxn, err) //nolint 556 } 557 } else { 558 beLen := common.BitLenToByteLen(bits.Len(sigHashLen)) 559 binary.BigEndian.PutUint64(ctx.buf[1:], uint64(sigHashLen)) 560 ctx.buf[8-beLen] = byte(beLen) + 247 561 if _, err := ctx.Keccak2.Write(ctx.buf[8-beLen : 9]); err != nil { 562 return 0, fmt.Errorf("%w: computing signHash (hashing len Prefix): %s", ErrParseTxn, err) //nolint 563 } 564 } 565 if _, err = ctx.Keccak2.Write(payload[sigHashPos:sigHashEnd]); err != nil { 566 return 0, fmt.Errorf("%w: computing signHash: %s", ErrParseTxn, err) //nolint 567 } 568 if legacy { 569 if chainIDLen > 0 { 570 if chainIDBits <= 7 { 571 ctx.buf[0] = byte(ctx.ChainID.Uint64()) 572 if _, err := ctx.Keccak2.Write(ctx.buf[:1]); err != nil { 573 return 0, fmt.Errorf("%w: computing signHash (hashing legacy chainId): %s", ErrParseTxn, err) //nolint 574 } 575 } else { 576 binary.BigEndian.PutUint64(ctx.buf[1:9], ctx.ChainID[3]) 577 binary.BigEndian.PutUint64(ctx.buf[9:17], ctx.ChainID[2]) 578 binary.BigEndian.PutUint64(ctx.buf[17:25], ctx.ChainID[1]) 579 binary.BigEndian.PutUint64(ctx.buf[25:33], ctx.ChainID[0]) 580 ctx.buf[32-chainIDLen] = 128 + byte(chainIDLen) 581 if _, err = ctx.Keccak2.Write(ctx.buf[32-chainIDLen : 33]); err != nil { 582 return 0, fmt.Errorf("%w: computing signHash (hashing legacy chainId): %s", ErrParseTxn, err) //nolint 583 } 584 } 585 // Encode two zeros 586 ctx.buf[0] = 128 587 ctx.buf[1] = 128 588 if _, err := ctx.Keccak2.Write(ctx.buf[:2]); err != nil { 589 return 0, fmt.Errorf("%w: computing signHash (hashing zeros after legacy chainId): %s", ErrParseTxn, err) //nolint 590 } 591 } 592 } 593 // Squeeze Sighash 594 _, _ = ctx.Keccak2.(io.Reader).Read(ctx.Sighash[:32]) 595 //ctx.keccak2.Sum(ctx.Sighash[:0]) 596 binary.BigEndian.PutUint64(ctx.Sig[0:8], ctx.R[3]) 597 binary.BigEndian.PutUint64(ctx.Sig[8:16], ctx.R[2]) 598 binary.BigEndian.PutUint64(ctx.Sig[16:24], ctx.R[1]) 599 binary.BigEndian.PutUint64(ctx.Sig[24:32], ctx.R[0]) 600 binary.BigEndian.PutUint64(ctx.Sig[32:40], ctx.S[3]) 601 binary.BigEndian.PutUint64(ctx.Sig[40:48], ctx.S[2]) 602 binary.BigEndian.PutUint64(ctx.Sig[48:56], ctx.S[1]) 603 binary.BigEndian.PutUint64(ctx.Sig[56:64], ctx.S[0]) 604 ctx.Sig[64] = vByte 605 // recover sender 606 if _, err = secp256k1.RecoverPubkeyWithContext(secp256k1.DefaultContext, ctx.Sighash[:], ctx.Sig[:], ctx.buf[:0]); err != nil { 607 return 0, fmt.Errorf("%w: recovering sender from signature: %s", ErrParseTxn, err) //nolint 608 } 609 //apply keccak to the public key 610 ctx.Keccak2.Reset() 611 if _, err = ctx.Keccak2.Write(ctx.buf[1:65]); err != nil { 612 return 0, fmt.Errorf("%w: computing sender from public key: %s", ErrParseTxn, err) //nolint 613 } 614 // squeeze the hash of the public key 615 //ctx.keccak2.Sum(ctx.buf[:0]) 616 _, _ = ctx.Keccak2.(io.Reader).Read(ctx.buf[:32]) 617 //take last 20 bytes as address 618 copy(sender, ctx.buf[12:32]) 619 620 return p, nil 621 } 622 623 type PeerID *types.H512 624 625 type Hashes []byte // flatten list of 32-byte hashes 626 627 func (h Hashes) At(i int) []byte { return h[i*length.Hash : (i+1)*length.Hash] } 628 func (h Hashes) Len() int { return len(h) / length.Hash } 629 func (h Hashes) Less(i, j int) bool { 630 return bytes.Compare(h[i*length.Hash:(i+1)*length.Hash], h[j*length.Hash:(j+1)*length.Hash]) < 0 631 } 632 func (h Hashes) Swap(i, j int) { 633 ii := i * length.Hash 634 jj := j * length.Hash 635 for k := 0; k < length.Hash; k++ { 636 h[ii], h[jj] = h[jj], h[ii] 637 ii++ 638 jj++ 639 } 640 } 641 642 // DedupCopy sorts hashes, and creates deduplicated copy 643 func (h Hashes) DedupCopy() Hashes { 644 if len(h) == 0 { 645 return h 646 } 647 sort.Sort(h) 648 unique := 1 649 for i := length.Hash; i < len(h); i += length.Hash { 650 if !bytes.Equal(h[i:i+length.Hash], h[i-length.Hash:i]) { 651 unique++ 652 } 653 } 654 c := make(Hashes, unique*length.Hash) 655 copy(c[:], h[0:length.Hash]) 656 dest := length.Hash 657 for i := dest; i < len(h); i += length.Hash { 658 if !bytes.Equal(h[i:i+length.Hash], h[i-length.Hash:i]) { 659 copy(c[dest:dest+length.Hash], h[i:i+length.Hash]) 660 dest += length.Hash 661 } 662 } 663 return c 664 } 665 666 type Announcements struct { 667 ts []byte 668 sizes []uint32 669 hashes []byte 670 } 671 672 func (a *Announcements) Append(t byte, size uint32, hash []byte) { 673 a.ts = append(a.ts, t) 674 a.sizes = append(a.sizes, size) 675 a.hashes = append(a.hashes, hash...) 676 } 677 678 func (a *Announcements) AppendOther(other Announcements) { 679 a.ts = append(a.ts, other.ts...) 680 a.sizes = append(a.sizes, other.sizes...) 681 a.hashes = append(a.hashes, other.hashes...) 682 } 683 684 func (a *Announcements) Reset() { 685 a.ts = a.ts[:0] 686 a.sizes = a.sizes[:0] 687 a.hashes = a.hashes[:0] 688 } 689 690 func (a Announcements) At(i int) (byte, uint32, []byte) { 691 return a.ts[i], a.sizes[i], a.hashes[i*length.Hash : (i+1)*length.Hash] 692 } 693 func (a Announcements) Len() int { return len(a.ts) } 694 func (a Announcements) Less(i, j int) bool { 695 return bytes.Compare(a.hashes[i*length.Hash:(i+1)*length.Hash], a.hashes[j*length.Hash:(j+1)*length.Hash]) < 0 696 } 697 func (a Announcements) Swap(i, j int) { 698 a.ts[i], a.ts[j] = a.ts[j], a.ts[i] 699 a.sizes[i], a.sizes[j] = a.sizes[j], a.sizes[i] 700 ii := i * length.Hash 701 jj := j * length.Hash 702 for k := 0; k < length.Hash; k++ { 703 a.hashes[ii], a.hashes[jj] = a.hashes[jj], a.hashes[ii] 704 ii++ 705 jj++ 706 } 707 } 708 709 // DedupCopy sorts hashes, and creates deduplicated copy 710 func (a Announcements) DedupCopy() Announcements { 711 if len(a.ts) == 0 { 712 return a 713 } 714 sort.Sort(a) 715 unique := 1 716 for i := length.Hash; i < len(a.hashes); i += length.Hash { 717 if !bytes.Equal(a.hashes[i:i+length.Hash], a.hashes[i-length.Hash:i]) { 718 unique++ 719 } 720 } 721 c := Announcements{ 722 ts: make([]byte, unique), 723 sizes: make([]uint32, unique), 724 hashes: make([]byte, unique*length.Hash), 725 } 726 copy(c.hashes, a.hashes[0:length.Hash]) 727 c.ts[0] = a.ts[0] 728 c.sizes[0] = a.sizes[0] 729 dest := length.Hash 730 j := 1 731 origin := length.Hash 732 for i := 1; i < len(a.ts); i++ { 733 if !bytes.Equal(a.hashes[origin:origin+length.Hash], a.hashes[origin-length.Hash:origin]) { 734 copy(c.hashes[dest:dest+length.Hash], a.hashes[origin:origin+length.Hash]) 735 c.ts[j] = a.ts[i] 736 c.sizes[j] = a.sizes[i] 737 dest += length.Hash 738 j++ 739 } 740 origin += length.Hash 741 } 742 return c 743 } 744 745 func (a Announcements) DedupHashes() Hashes { 746 if len(a.ts) == 0 { 747 return Hashes{} 748 } 749 sort.Sort(a) 750 unique := 1 751 for i := length.Hash; i < len(a.hashes); i += length.Hash { 752 if !bytes.Equal(a.hashes[i:i+length.Hash], a.hashes[i-length.Hash:i]) { 753 unique++ 754 } 755 } 756 c := make(Hashes, unique*length.Hash) 757 copy(c[:], a.hashes[0:length.Hash]) 758 dest := length.Hash 759 j := 1 760 origin := length.Hash 761 for i := 1; i < len(a.ts); i++ { 762 if !bytes.Equal(a.hashes[origin:origin+length.Hash], a.hashes[origin-length.Hash:origin]) { 763 copy(c[dest:dest+length.Hash], a.hashes[origin:origin+length.Hash]) 764 dest += length.Hash 765 j++ 766 } 767 origin += length.Hash 768 } 769 return c 770 } 771 772 func (a Announcements) Hashes() Hashes { 773 return Hashes(a.hashes) 774 } 775 776 func (a Announcements) Copy() Announcements { 777 if len(a.ts) == 0 { 778 return a 779 } 780 c := Announcements{ 781 ts: common.Copy(a.ts), 782 sizes: make([]uint32, len(a.sizes)), 783 hashes: common.Copy(a.hashes), 784 } 785 copy(c.sizes, a.sizes) 786 return c 787 } 788 789 type Addresses []byte // flatten list of 20-byte addresses 790 791 // AddressAt returns an address at the given index in the flattened list. 792 // Use this method if you want to reduce memory allocations 793 func (h Addresses) AddressAt(i int) common.Address { 794 return *(*[20]byte)(h[i*length.Addr : (i+1)*length.Addr]) 795 } 796 797 func (h Addresses) At(i int) []byte { return h[i*length.Addr : (i+1)*length.Addr] } 798 func (h Addresses) Len() int { return len(h) / length.Addr } 799 800 type TxSlots struct { 801 Txs []*TxSlot 802 Senders Addresses 803 IsLocal []bool 804 } 805 806 func (s *TxSlots) Valid() error { 807 if len(s.Txs) != len(s.IsLocal) { 808 return fmt.Errorf("TxSlots: expect equal len of isLocal=%d and txs=%d", len(s.IsLocal), len(s.Txs)) 809 } 810 if len(s.Txs) != s.Senders.Len() { 811 return fmt.Errorf("TxSlots: expect equal len of senders=%d and txs=%d", s.Senders.Len(), len(s.Txs)) 812 } 813 return nil 814 } 815 816 var zeroAddr = make([]byte, 20) 817 818 // Resize internal arrays to len=targetSize, shrinks if need. It rely on `append` algorithm to realloc 819 func (s *TxSlots) Resize(targetSize uint) { 820 for uint(len(s.Txs)) < targetSize { 821 s.Txs = append(s.Txs, nil) 822 } 823 for uint(s.Senders.Len()) < targetSize { 824 s.Senders = append(s.Senders, addressesGrowth...) 825 } 826 for uint(len(s.IsLocal)) < targetSize { 827 s.IsLocal = append(s.IsLocal, false) 828 } 829 //todo: set nil to overflow txs 830 oldLen := uint(len(s.Txs)) 831 s.Txs = s.Txs[:targetSize] 832 for i := oldLen; i < targetSize; i++ { 833 s.Txs[i] = nil 834 } 835 s.Senders = s.Senders[:length.Addr*targetSize] 836 for i := oldLen; i < targetSize; i++ { 837 copy(s.Senders.At(int(i)), zeroAddr) 838 } 839 s.IsLocal = s.IsLocal[:targetSize] 840 for i := oldLen; i < targetSize; i++ { 841 s.IsLocal[i] = false 842 } 843 } 844 func (s *TxSlots) Append(slot *TxSlot, sender []byte, isLocal bool) { 845 n := len(s.Txs) 846 s.Resize(uint(len(s.Txs) + 1)) 847 s.Txs[n] = slot 848 s.IsLocal[n] = isLocal 849 copy(s.Senders.At(n), sender) 850 } 851 852 type TxsRlp struct { 853 Txs [][]byte 854 Senders Addresses 855 IsLocal []bool 856 } 857 858 // Resize internal arrays to len=targetSize, shrinks if need. It rely on `append` algorithm to realloc 859 func (s *TxsRlp) Resize(targetSize uint) { 860 for uint(len(s.Txs)) < targetSize { 861 s.Txs = append(s.Txs, nil) 862 } 863 for uint(s.Senders.Len()) < targetSize { 864 s.Senders = append(s.Senders, addressesGrowth...) 865 } 866 for uint(len(s.IsLocal)) < targetSize { 867 s.IsLocal = append(s.IsLocal, false) 868 } 869 //todo: set nil to overflow txs 870 s.Txs = s.Txs[:targetSize] 871 s.Senders = s.Senders[:length.Addr*targetSize] 872 s.IsLocal = s.IsLocal[:targetSize] 873 } 874 875 var addressesGrowth = make([]byte, length.Addr) 876 877 func EncodeSenderLengthForStorage(nonce uint64, balance uint256.Int) uint { 878 var structLength uint = 1 // 1 byte for fieldset 879 if !balance.IsZero() { 880 structLength += uint(balance.ByteLen()) + 1 881 } 882 if nonce > 0 { 883 structLength += uint(common.BitLenToByteLen(bits.Len64(nonce))) + 1 884 } 885 return structLength 886 } 887 888 // Encode the details of txn sender into the given "buffer" byte-slice that should be big enough 889 func EncodeSender(nonce uint64, balance uint256.Int, buffer []byte) { 890 var fieldSet = 0 // start with first bit set to 0 891 var pos = 1 892 if nonce > 0 { 893 fieldSet = 1 894 nonceBytes := common.BitLenToByteLen(bits.Len64(nonce)) 895 buffer[pos] = byte(nonceBytes) 896 var nonce = nonce 897 for i := nonceBytes; i > 0; i-- { 898 buffer[pos+i] = byte(nonce) 899 nonce >>= 8 900 } 901 pos += nonceBytes + 1 902 } 903 904 // Encoding balance 905 if !balance.IsZero() { 906 fieldSet |= 2 907 balanceBytes := balance.ByteLen() 908 buffer[pos] = byte(balanceBytes) 909 pos++ 910 balance.WriteToSlice(buffer[pos : pos+balanceBytes]) 911 pos += balanceBytes //nolint 912 } 913 914 buffer[0] = byte(fieldSet) 915 } 916 917 // Decode the sender's balance and nonce from encoded byte-slice 918 func DecodeSender(enc []byte) (nonce uint64, balance uint256.Int, err error) { 919 if len(enc) == 0 { 920 return 921 } 922 923 var fieldSet = enc[0] 924 var pos = 1 925 926 if fieldSet&1 > 0 { 927 decodeLength := int(enc[pos]) 928 929 if len(enc) < pos+decodeLength+1 { 930 return nonce, balance, fmt.Errorf( 931 "malformed CBOR for Account.Nonce: %s, Length %d", 932 enc[pos+1:], decodeLength) 933 } 934 935 nonce = bytesToUint64(enc[pos+1 : pos+decodeLength+1]) 936 pos += decodeLength + 1 937 } 938 939 if fieldSet&2 > 0 { 940 decodeLength := int(enc[pos]) 941 942 if len(enc) < pos+decodeLength+1 { 943 return nonce, balance, fmt.Errorf( 944 "malformed CBOR for Account.Nonce: %s, Length %d", 945 enc[pos+1:], decodeLength) 946 } 947 948 (&balance).SetBytes(enc[pos+1 : pos+decodeLength+1]) 949 } 950 return 951 } 952 953 func bytesToUint64(buf []byte) (x uint64) { 954 for i, b := range buf { 955 x = x<<8 + uint64(b) 956 if i == 7 { 957 return 958 } 959 } 960 return 961 } 962 963 // nolint 964 func (tx *TxSlot) PrintDebug(prefix string) { 965 fmt.Printf("%s: senderID=%d,nonce=%d,tip=%d,v=%d\n", prefix, tx.SenderID, tx.Nonce, tx.Tip, tx.Value.Uint64()) 966 //fmt.Printf("%s: senderID=%d,nonce=%d,tip=%d,hash=%x\n", prefix, tx.senderID, tx.nonce, tx.tip, tx.IdHash) 967 } 968 969 // AccessList is an EIP-2930 access list. 970 type AccessList []AccessTuple 971 972 // AccessTuple is the element type of an access list. 973 type AccessTuple struct { 974 Address common.Address `json:"address"` 975 StorageKeys []common.Hash `json:"storageKeys"` 976 } 977 978 // StorageKeys returns the total number of storage keys in the access list. 979 func (al AccessList) StorageKeys() int { 980 sum := 0 981 for _, tuple := range al { 982 sum += len(tuple.StorageKeys) 983 } 984 return sum 985 }