Skip to content

Commit

Permalink
padding-in-log-bug (erigontech#746)
Browse files Browse the repository at this point in the history
* padding-in-log-bug

* IF -> FOR
  • Loading branch information
kstoykov authored Jul 9, 2024
1 parent 5f856f2 commit 529cb58
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 190 deletions.
8 changes: 6 additions & 2 deletions core/blockchain_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func ExecuteBlockEphemerallyZk(
}

//[hack]TODO: remove this after bug is fixed
localReceipt := *receipt
localReceipt := receipt.Clone()
if !chainConfig.IsForkID8Elderberry(blockNum) && errors.Is(execResult.Err, vm.ErrUnsupportedPrecompile) {
localReceipt.Status = 1
}
Expand Down Expand Up @@ -152,6 +152,10 @@ func ExecuteBlockEphemerallyZk(
receipt.CumulativeGasUsed = receipt.GasUsed
}

for _, l := range receipt.Logs {
l.ApplyPaddingToLogsData(chainConfig.IsForkID8Elderberry(blockNum), chainConfig.IsForkId9Elderberry2(blockNum))
}

if err != nil {
if !vmConfig.StatelessExec {
return nil, fmt.Errorf("could not apply tx %d from block %d [%v]: %w", txIndex, block.NumberU64(), tx.Hash().Hex(), err)
Expand Down Expand Up @@ -180,7 +184,7 @@ func ExecuteBlockEphemerallyZk(

txInfos = append(txInfos, blockinfo.ExecutedTxInfo{
Tx: tx,
Receipt: &localReceipt,
Receipt: localReceipt,
EffectiveGasPrice: effectiveGasPricePercentage,
Signer: &txSender,
})
Expand Down
123 changes: 123 additions & 0 deletions core/types/log_zkevm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package types

import (
"encoding/hex"

libcommon "github.com/gateway-fm/cdk-erigon-lib/common"
)

func (_this *Log) Clone() *Log {
address := libcommon.Address{}
copy(address[:], _this.Address[:])

topics := make([]libcommon.Hash, len(_this.Topics))
for i, t := range _this.Topics {
copy(topics[i][:], t[:])
}

data := make([]byte, len(_this.Data))
copy(data, _this.Data)

txHash := libcommon.Hash{}
copy(txHash[:], _this.TxHash[:])

blockHash := libcommon.Hash{}
copy(blockHash[:], _this.BlockHash[:])

return &Log{
Address: address,
Topics: topics,
Data: data,
BlockNumber: _this.BlockNumber,
TxHash: txHash,
TxIndex: _this.TxIndex,
BlockHash: blockHash,
Index: _this.Index,
Removed: _this.Removed,
}
}

func (_this *Log) ApplyPaddingToLogsData(isForkId8, isForkId9 bool) {
d := _this.Data
mSize := len(d)

if isForkId8 || isForkId9 {
d = applyHexPadBug(d, mSize)
} else {
// [zkEvm] fill 0 at the end
lenMod32 := mSize & 31
if lenMod32 != 0 {
d = append(d, make([]byte, 32-lenMod32)...)
}
}

_this.Data = d
}

func applyHexPadBug(d []byte, msInt int) []byte {
fullMs := msInt

var dLastWord []byte
if len(d) <= 32 {
dLastWord = append(d, make([]byte, 32-len(d))...)
d = []byte{}
} else {
dLastWord, msInt = getLastWordBytes(d, fullMs)
d = d[:len(d)-len(dLastWord)]
}

dataHex := hex.EncodeToString(dLastWord)

dataHex = appendZeros(dataHex, 64)

for len(dataHex) > 0 && dataHex[0] == '0' {
dataHex = dataHex[1:]
}

if len(dataHex) < msInt*2 {
dataHex = prependZeros(dataHex, msInt*2)
}
outputStr := takeFirstN(dataHex, msInt*2)
op, _ := hex.DecodeString(outputStr) // there error is always nil here, because we prepare outputStr to have even length
d = append(d, op...)
d = d[:fullMs]

return d
}

func getLastWordBytes(data []byte, originalMsInt int) ([]byte, int) {
wordLength := 32
dataLength := len(data)

remainderLength := dataLength % wordLength
if remainderLength == 0 {
return data[dataLength-wordLength:], 32
}

toRemove := dataLength / wordLength

msInt := originalMsInt - (toRemove * wordLength)

return data[dataLength-remainderLength:], msInt
}

func prependZeros(data string, size int) string {
for len(data) < size {
data = "0" + data
}
return data
}

func takeFirstN(data string, n int) string {
if len(data) < n {
return data
}
return data[:n]
}

func appendZeros(dataHex string, targetLength int) string {
for len(dataHex) < targetLength {
dataHex += "0"
}
return dataHex
}
69 changes: 69 additions & 0 deletions core/types/log_zkevm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package types

import (
"testing"

"encoding/hex"

"github.com/ledgerwatch/erigon/common"
)

func TestApplyHexPadBug(t *testing.T) {
type testScenario struct {
data string
mSize int
expected string
}

scenarios := map[string]testScenario{
"cardona-bug-block-3177498": {
data: "0x010203",
mSize: 3,
expected: "102030",
},
"singleByteHexWithoutBug": {
data: "0x11",
mSize: 1,
expected: "11",
},
"another": {
data: "0x100000000000000000000000000000000000000000000000000000000000000",
mSize: 1,
expected: "10",
},
"another1": {
data: "0x1020000000000000000000000000000000000000000000000000000000000",
mSize: 3,
expected: "102000",
},
"cardona-897048": {
data: "0x0000000000000000000000000000000000000000000000000000000000000001",
mSize: 32,
expected: "0000000000000000000000000000000000000000000000000000000000000001",
},
"cardona-896194": {
data: "0x0000000000000000000000000000000000000000000000010000000000001e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009af3049dd15616fd627a35563b5282bea5c32e2000000000000000000000000000000000000000000000000000005af3107a4000",
mSize: 160,
expected: "0000000000000000000000000000000000000000000000010000000000001e44000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009af3049dd15616fd627a35563b5282bea5c32e2000000000000000000000000000000000000000000000000000005af3107a4000",
},
"cardona-3816917": {
data: "0x0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f",
mSize: 60,
expected: "0102030405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f010230405060708090a0b0c0d0e0f0102030405060708090a0b0c0d0e0f0",
},
}

for name, scenario := range scenarios {
t.Run(name, func(t *testing.T) {
d := common.FromHex(scenario.data)

result := applyHexPadBug(d, scenario.mSize)

resultHex := hex.EncodeToString(result)

if resultHex != scenario.expected {
t.Errorf("Expected %s but got %s", scenario.expected, resultHex)
}
})
}
}
39 changes: 39 additions & 0 deletions core/types/receipt_zkevm.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,49 @@ import (
"math/big"

"github.com/gateway-fm/cdk-erigon-lib/common"
libcommon "github.com/gateway-fm/cdk-erigon-lib/common"

"github.com/ledgerwatch/erigon/crypto"
)

func (_this *Receipt) Clone() *Receipt {
postState := make([]byte, len(_this.PostState))
copy(postState, _this.PostState)

bloom := Bloom{}
copy(bloom[:], _this.Bloom[:])

logs := make(Logs, len(_this.Logs))
for i, l := range _this.Logs {
logs[i] = l.Clone()
}

txHash := libcommon.Hash{}
copy(txHash[:], _this.TxHash[:])

contractAddress := libcommon.Address{}
copy(contractAddress[:], _this.ContractAddress[:])

blockHash := libcommon.Hash{}
copy(blockHash[:], _this.BlockHash[:])

BlockNumber := big.NewInt(0).Set(_this.BlockNumber)

return &Receipt{
Type: _this.Type,
PostState: postState,
Status: _this.Status,
CumulativeGasUsed: _this.CumulativeGasUsed,
Bloom: bloom,
Logs: logs,
TxHash: txHash,
ContractAddress: contractAddress,
BlockHash: blockHash,
BlockNumber: BlockNumber,
TransactionIndex: _this.TransactionIndex,
}
}

// DeriveFields fills the receipts with their computed fields based on consensus
// data and contextual infos like containing block and transactions.
func (r Receipts) DeriveFields_zkEvm(forkId8BlockNum uint64, hash common.Hash, number uint64, txs Transactions, senders []common.Address) error {
Expand Down
Loading

0 comments on commit 529cb58

Please sign in to comment.