github.com/ledgerwatch/erigon-lib@v1.0.0/types/txn_test.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 "crypto/rand" 22 "strconv" 23 "testing" 24 25 gokzg4844 "github.com/crate-crypto/go-kzg-4844" 26 "github.com/holiman/uint256" 27 "github.com/stretchr/testify/assert" 28 "github.com/stretchr/testify/require" 29 30 "github.com/ledgerwatch/erigon-lib/common/fixedgas" 31 "github.com/ledgerwatch/erigon-lib/common/hexutility" 32 ) 33 34 func TestParseTransactionRLP(t *testing.T) { 35 for _, testSet := range allNetsTestCases { 36 testSet := testSet 37 t.Run(strconv.Itoa(int(testSet.chainID.Uint64())), func(t *testing.T) { 38 require := require.New(t) 39 ctx := NewTxParseContext(testSet.chainID) 40 tx, txSender := &TxSlot{}, [20]byte{} 41 for i, tt := range testSet.tests { 42 tt := tt 43 t.Run(strconv.Itoa(i), func(t *testing.T) { 44 payload := hexutility.MustDecodeHex(tt.PayloadStr) 45 parseEnd, err := ctx.ParseTransaction(payload, 0, tx, txSender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil) 46 require.NoError(err) 47 require.Equal(len(payload), parseEnd) 48 if tt.SignHashStr != "" { 49 signHash := hexutility.MustDecodeHex(tt.SignHashStr) 50 if !bytes.Equal(signHash, ctx.Sighash[:]) { 51 t.Errorf("signHash expected %x, got %x", signHash, ctx.Sighash) 52 } 53 } 54 if tt.IdHashStr != "" { 55 idHash := hexutility.MustDecodeHex(tt.IdHashStr) 56 if !bytes.Equal(idHash, tx.IDHash[:]) { 57 t.Errorf("IdHash expected %x, got %x", idHash, tx.IDHash) 58 } 59 } 60 if tt.SenderStr != "" { 61 expectSender := hexutility.MustDecodeHex(tt.SenderStr) 62 if !bytes.Equal(expectSender, txSender[:]) { 63 t.Errorf("expectSender expected %x, got %x", expectSender, txSender) 64 } 65 } 66 require.Equal(tt.Nonce, tx.Nonce) 67 }) 68 } 69 }) 70 } 71 } 72 73 func TestTransactionSignatureValidity1(t *testing.T) { 74 chainId := new(uint256.Int).SetUint64(1) 75 ctx := NewTxParseContext(*chainId) 76 ctx.WithAllowPreEip2s(true) 77 78 tx, txSender := &TxSlot{}, [20]byte{} 79 validTxn := hexutility.MustDecodeHex("f83f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870b801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a3664935301") 80 _, err := ctx.ParseTransaction(validTxn, 0, tx, txSender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil) 81 assert.NoError(t, err) 82 83 preEip2Txn := hexutility.MustDecodeHex("f85f800182520894095e7baea6a6c7c4c2dfeb977efac326af552d870b801ba048b55bfa915ac795c431978d8a6a992b628d557da5ff759b307d495a36649353a07fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1") 84 _, err = ctx.ParseTransaction(preEip2Txn, 0, tx, txSender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil) 85 assert.NoError(t, err) 86 87 // Now enforce EIP-2 88 ctx.WithAllowPreEip2s(false) 89 _, err = ctx.ParseTransaction(validTxn, 0, tx, txSender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil) 90 assert.NoError(t, err) 91 92 _, err = ctx.ParseTransaction(preEip2Txn, 0, tx, txSender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil) 93 assert.Error(t, err) 94 } 95 96 // Problematic txn included in a bad block on Görli 97 func TestTransactionSignatureValidity2(t *testing.T) { 98 chainId := new(uint256.Int).SetUint64(5) 99 ctx := NewTxParseContext(*chainId) 100 slot, sender := &TxSlot{}, [20]byte{} 101 rlp := hexutility.MustDecodeHex("02f8720513844190ab00848321560082520894cab441d2f45a3fee83d15c6b6b6c36a139f55b6288054607fc96a6000080c001a0dffe4cb5651e663d0eac8c4d002de734dd24db0f1109b062d17da290a133cc02a0913fb9f53f7a792bcd9e4d7cced1b8545d1ab82c77432b0bc2e9384ba6c250c5") 102 _, err := ctx.ParseTransaction(rlp, 0, slot, sender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil) 103 assert.Error(t, err) 104 105 // Only legacy transactions can happen before EIP-2 106 ctx.WithAllowPreEip2s(true) 107 _, err = ctx.ParseTransaction(rlp, 0, slot, sender[:], false /* hasEnvelope */, true /* wrappedWithBlobs */, nil) 108 assert.Error(t, err) 109 } 110 111 func TestTxSlotsGrowth(t *testing.T) { 112 assert := assert.New(t) 113 s := &TxSlots{} 114 s.Resize(11) 115 assert.Equal(11, len(s.Txs)) 116 assert.Equal(11, s.Senders.Len()) 117 s.Resize(23) 118 assert.Equal(23, len(s.Txs)) 119 assert.Equal(23, s.Senders.Len()) 120 121 s = &TxSlots{Txs: make([]*TxSlot, 20), Senders: make(Addresses, 20*20)} 122 s.Resize(20) 123 assert.Equal(20, len(s.Txs)) 124 assert.Equal(20, s.Senders.Len()) 125 s.Resize(23) 126 assert.Equal(23, len(s.Txs)) 127 assert.Equal(23, s.Senders.Len()) 128 129 s.Resize(2) 130 assert.Equal(2, len(s.Txs)) 131 assert.Equal(2, s.Senders.Len()) 132 } 133 134 func TestDedupHashes(t *testing.T) { 135 assert := assert.New(t) 136 h := toHashes(2, 6, 2, 5, 2, 4) 137 c := h.DedupCopy() 138 assert.Equal(6, h.Len()) 139 assert.Equal(4, c.Len()) 140 assert.Equal(toHashes(2, 2, 2, 4, 5, 6), h) 141 assert.Equal(toHashes(2, 4, 5, 6), c) 142 143 h = toHashes(2, 2) 144 c = h.DedupCopy() 145 assert.Equal(toHashes(2, 2), h) 146 assert.Equal(toHashes(2), c) 147 148 h = toHashes(1) 149 c = h.DedupCopy() 150 assert.Equal(1, h.Len()) 151 assert.Equal(1, c.Len()) 152 assert.Equal(toHashes(1), h) 153 assert.Equal(toHashes(1), c) 154 155 h = toHashes() 156 c = h.DedupCopy() 157 assert.Equal(0, h.Len()) 158 assert.Equal(0, c.Len()) 159 assert.Equal(0, len(h)) 160 assert.Equal(0, len(c)) 161 162 h = toHashes(1, 2, 3, 4) 163 c = h.DedupCopy() 164 assert.Equal(toHashes(1, 2, 3, 4), h) 165 assert.Equal(toHashes(1, 2, 3, 4), c) 166 167 h = toHashes(4, 2, 1, 3) 168 c = h.DedupCopy() 169 assert.Equal(toHashes(1, 2, 3, 4), h) 170 assert.Equal(toHashes(1, 2, 3, 4), c) 171 172 } 173 174 func toHashes(h ...byte) (out Hashes) { 175 for i := range h { 176 hash := [32]byte{h[i]} 177 out = append(out, hash[:]...) 178 } 179 return out 180 } 181 182 func TestBlobTxParsing(t *testing.T) { 183 // First parse a blob transaction body (no blobs/commitments/proofs) 184 wrappedWithBlobs := false 185 // Some arbitrary hardcoded example 186 bodyRlpHex := "f9012705078502540be4008506fc23ac008357b58494811a752c8cd697e3cb27" + 187 "279c330ed1ada745a8d7808204f7f872f85994de0b295669a9fd93d5f28d9ec85e40f4cb697b" + 188 "aef842a00000000000000000000000000000000000000000000000000000000000000003a000" + 189 "00000000000000000000000000000000000000000000000000000000000007d694bb9bc244d7" + 190 "98123fde783fcc1c72d3bb8c189413c07bf842a0c6bdd1de713471bd6cfa62dd8b5a5b42969e" + 191 "d09e26212d3377f3f8426d8ec210a08aaeccaf3873d07cef005aca28c39f8a9f8bdb1ec8d79f" + 192 "fc25afc0a4fa2ab73601a036b241b061a36a32ab7fe86c7aa9eb592dd59018cd0443adc09035" + 193 "90c16b02b0a05edcc541b4741c5cc6dd347c5ed9577ef293a62787b4510465fadbfe39ee4094" 194 bodyRlp := hexutility.MustDecodeHex(bodyRlpHex) 195 196 hasEnvelope := true 197 bodyEnvelope := hexutility.MustDecodeHex("b9012b03") 198 bodyEnvelope = append(bodyEnvelope, bodyRlp...) 199 200 ctx := NewTxParseContext(*uint256.NewInt(5)) 201 ctx.withSender = false 202 203 var thinTx TxSlot // only tx body, no blobs 204 txType, err := PeekTransactionType(bodyEnvelope) 205 require.NoError(t, err) 206 assert.Equal(t, BlobTxType, txType) 207 208 p, err := ctx.ParseTransaction(bodyEnvelope, 0, &thinTx, nil, hasEnvelope, wrappedWithBlobs, nil) 209 require.NoError(t, err) 210 assert.Equal(t, len(bodyEnvelope), p) 211 assert.Equal(t, len(bodyEnvelope), int(thinTx.Size)) 212 assert.Equal(t, bodyEnvelope[3:], thinTx.Rlp) 213 assert.Equal(t, BlobTxType, thinTx.Type) 214 assert.Equal(t, 2, len(thinTx.BlobHashes)) 215 assert.Equal(t, 0, len(thinTx.Blobs)) 216 assert.Equal(t, 0, len(thinTx.Commitments)) 217 assert.Equal(t, 0, len(thinTx.Proofs)) 218 219 // Now parse the same tx body, but wrapped with blobs/commitments/proofs 220 wrappedWithBlobs = true 221 hasEnvelope = false 222 223 blobsRlpPrefix := hexutility.MustDecodeHex("fa040008") 224 blobRlpPrefix := hexutility.MustDecodeHex("ba020000") 225 blob0 := make([]byte, fixedgas.BlobSize) 226 rand.Read(blob0) 227 blob1 := make([]byte, fixedgas.BlobSize) 228 rand.Read(blob1) 229 230 proofsRlpPrefix := hexutility.MustDecodeHex("f862") 231 var commitment0, commitment1 gokzg4844.KZGCommitment 232 rand.Read(commitment0[:]) 233 rand.Read(commitment1[:]) 234 var proof0, proof1 gokzg4844.KZGProof 235 rand.Read(proof0[:]) 236 rand.Read(proof1[:]) 237 238 wrapperRlp := hexutility.MustDecodeHex("03fa0401fe") 239 wrapperRlp = append(wrapperRlp, bodyRlp...) 240 wrapperRlp = append(wrapperRlp, blobsRlpPrefix...) 241 wrapperRlp = append(wrapperRlp, blobRlpPrefix...) 242 wrapperRlp = append(wrapperRlp, blob0...) 243 wrapperRlp = append(wrapperRlp, blobRlpPrefix...) 244 wrapperRlp = append(wrapperRlp, blob1...) 245 wrapperRlp = append(wrapperRlp, proofsRlpPrefix...) 246 wrapperRlp = append(wrapperRlp, 0xb0) 247 wrapperRlp = append(wrapperRlp, commitment0[:]...) 248 wrapperRlp = append(wrapperRlp, 0xb0) 249 wrapperRlp = append(wrapperRlp, commitment1[:]...) 250 wrapperRlp = append(wrapperRlp, proofsRlpPrefix...) 251 wrapperRlp = append(wrapperRlp, 0xb0) 252 wrapperRlp = append(wrapperRlp, proof0[:]...) 253 wrapperRlp = append(wrapperRlp, 0xb0) 254 wrapperRlp = append(wrapperRlp, proof1[:]...) 255 256 var fatTx TxSlot // with blobs/commitments/proofs 257 txType, err = PeekTransactionType(wrapperRlp) 258 require.NoError(t, err) 259 assert.Equal(t, BlobTxType, txType) 260 261 p, err = ctx.ParseTransaction(wrapperRlp, 0, &fatTx, nil, hasEnvelope, wrappedWithBlobs, nil) 262 require.NoError(t, err) 263 assert.Equal(t, len(wrapperRlp), p) 264 assert.Equal(t, len(wrapperRlp), int(fatTx.Size)) 265 assert.Equal(t, wrapperRlp, fatTx.Rlp) 266 assert.Equal(t, BlobTxType, fatTx.Type) 267 268 assert.Equal(t, thinTx.Value, fatTx.Value) 269 assert.Equal(t, thinTx.Tip, fatTx.Tip) 270 assert.Equal(t, thinTx.FeeCap, fatTx.FeeCap) 271 assert.Equal(t, thinTx.Nonce, fatTx.Nonce) 272 assert.Equal(t, thinTx.DataLen, fatTx.DataLen) 273 assert.Equal(t, thinTx.DataNonZeroLen, fatTx.DataNonZeroLen) 274 assert.Equal(t, thinTx.AlAddrCount, fatTx.AlAddrCount) 275 assert.Equal(t, thinTx.AlStorCount, fatTx.AlStorCount) 276 assert.Equal(t, thinTx.Gas, fatTx.Gas) 277 assert.Equal(t, thinTx.IDHash, fatTx.IDHash) 278 assert.Equal(t, thinTx.Creation, fatTx.Creation) 279 assert.Equal(t, thinTx.BlobFeeCap, fatTx.BlobFeeCap) 280 assert.Equal(t, thinTx.BlobHashes, fatTx.BlobHashes) 281 282 require.Equal(t, 2, len(fatTx.Blobs)) 283 require.Equal(t, 2, len(fatTx.Commitments)) 284 require.Equal(t, 2, len(fatTx.Proofs)) 285 assert.Equal(t, blob0, fatTx.Blobs[0]) 286 assert.Equal(t, blob1, fatTx.Blobs[1]) 287 assert.Equal(t, commitment0, fatTx.Commitments[0]) 288 assert.Equal(t, commitment1, fatTx.Commitments[1]) 289 assert.Equal(t, proof0, fatTx.Proofs[0]) 290 assert.Equal(t, proof1, fatTx.Proofs[1]) 291 }