Skip to content

Commit

Permalink
Merge pull request #2857 from dessaya/fix-evm-logs
Browse files Browse the repository at this point in the history
fix(evm): properly revert emitted logs after revert
  • Loading branch information
fijter authored Sep 8, 2023
2 parents 6c1b772 + 057e86d commit 53f2e22
Show file tree
Hide file tree
Showing 9 changed files with 159 additions and 67 deletions.
2 changes: 1 addition & 1 deletion packages/evm/evmtest/ISCTest.abi
Original file line number Diff line number Diff line change
@@ -1 +1 @@
[{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"CustomError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"entropy","type":"bytes32"}],"name":"EntropyEvent","type":"event"},{"anonymous":false,"inputs":[],"name":"LoopEvent","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct ISCRequestID","name":"reqID","type":"tuple"}],"name":"RequestIDEvent","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct ISCAgentID","name":"sender","type":"tuple"}],"name":"SenderAccountEvent","type":"event"},{"inputs":[],"name":"TokensForGas","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callInccounter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emitEntropy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emitRequestID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emitSenderAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainID","outputs":[{"internalType":"ISCChainID","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"loopWithGasLeft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"makeISCPanic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"foundrySN","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"storageDeposit","type":"uint64"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ISCAgentID","name":"targetAgentID","type":"tuple"},{"components":[{"internalType":"uint64","name":"baseTokens","type":"uint64"},{"components":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct NativeTokenID","name":"ID","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct NativeToken[]","name":"nativeTokens","type":"tuple[]"},{"internalType":"NFTID[]","name":"nfts","type":"bytes32[]"}],"internalType":"struct ISCAssets","name":"allowance","type":"tuple"}],"name":"moveToAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revertWithCustomError","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct L1Address","name":"receiver","type":"tuple"},{"internalType":"uint64","name":"baseTokens","type":"uint64"}],"name":"sendBaseTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct L1Address","name":"receiver","type":"tuple"},{"internalType":"NFTID","name":"id","type":"bytes32"},{"internalType":"uint64","name":"storageDeposit","type":"uint64"}],"name":"sendNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sendTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"testCallViewCaller","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"testRevertReason","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"testSelfDestruct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"testStackOverflow","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"testStaticCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"s","type":"string"}],"name":"triggerEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"s","type":"string"}],"name":"triggerEventFail","outputs":[],"stateMutability":"nonpayable","type":"function"}]
[{"inputs":[{"internalType":"uint8","name":"","type":"uint8"}],"name":"CustomError","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"entropy","type":"bytes32"}],"name":"EntropyEvent","type":"event"},{"anonymous":false,"inputs":[],"name":"LoopEvent","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct ISCRequestID","name":"reqID","type":"tuple"}],"name":"RequestIDEvent","type":"event"},{"anonymous":false,"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"indexed":false,"internalType":"struct ISCAgentID","name":"sender","type":"tuple"}],"name":"SenderAccountEvent","type":"event"},{"anonymous":false,"inputs":[],"name":"SomeEvent","type":"event"},{"inputs":[],"name":"TokensForGas","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"callInccounter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emitEntropy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emitEventAndRevert","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emitRequestID","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"emitSenderAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getChainID","outputs":[{"internalType":"ISCChainID","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"loopWithGasLeft","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"makeISCPanic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"foundrySN","type":"uint32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint64","name":"storageDeposit","type":"uint64"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ISCAgentID","name":"targetAgentID","type":"tuple"},{"components":[{"internalType":"uint64","name":"baseTokens","type":"uint64"},{"components":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct NativeTokenID","name":"ID","type":"tuple"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct NativeToken[]","name":"nativeTokens","type":"tuple[]"},{"internalType":"NFTID[]","name":"nfts","type":"bytes32[]"}],"internalType":"struct ISCAssets","name":"allowance","type":"tuple"}],"name":"moveToAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"revertWithCustomError","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct L1Address","name":"receiver","type":"tuple"},{"internalType":"uint64","name":"baseTokens","type":"uint64"}],"name":"sendBaseTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct L1Address","name":"receiver","type":"tuple"},{"internalType":"NFTID","name":"id","type":"bytes32"},{"internalType":"uint64","name":"storageDeposit","type":"uint64"}],"name":"sendNFT","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sendTo","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"testCallViewCaller","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"testRevertReason","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address payable","name":"beneficiary","type":"address"}],"name":"testSelfDestruct","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"testStackOverflow","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"testStaticCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"s","type":"string"}],"name":"triggerEvent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"s","type":"string"}],"name":"triggerEventFail","outputs":[],"stateMutability":"nonpayable","type":"function"}]
2 changes: 1 addition & 1 deletion packages/evm/evmtest/ISCTest.bin

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions packages/evm/evmtest/ISCTest.sol
Original file line number Diff line number Diff line change
Expand Up @@ -196,4 +196,11 @@ contract ISCTest {
function revertWithCustomError() public pure {
revert CustomError(42);
}

event SomeEvent();

function emitEventAndRevert() public {
emit SomeEvent();
revert();
}
}
31 changes: 13 additions & 18 deletions packages/evm/jsonrpc/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,34 +170,29 @@ func RPCMarshalReceipt(r *types.Receipt, tx *types.Transaction) map[string]inter
"cumulativeGasUsed": hexutil.Uint64(r.CumulativeGasUsed),
"gasUsed": hexutil.Uint64(r.GasUsed),
"contractAddress": r.ContractAddress,
"logs": RPCMarshalLogs(r),
"logs": rpcMarshalLogs(r),
"logsBloom": r.Bloom,
"status": hexutil.Uint64(r.Status),
}
}

func RPCMarshalLogs(r *types.Receipt) []interface{} {
func rpcMarshalLogs(r *types.Receipt) []interface{} {
ret := make([]interface{}, len(r.Logs))
for i := range r.Logs {
ret[i] = RPCMarshalLog(r, uint(i))
for i, log := range r.Logs {
ret[i] = map[string]interface{}{
"logIndex": hexutil.Uint(log.Index),
"blockNumber": hexutil.Uint(log.BlockNumber),
"blockHash": log.BlockHash,
"transactionHash": log.TxHash,
"transactionIndex": hexutil.Uint(log.TxIndex),
"address": log.Address,
"data": hexutil.Bytes(log.Data),
"topics": log.Topics,
}
}
return ret
}

func RPCMarshalLog(r *types.Receipt, logIndex uint) map[string]interface{} {
log := r.Logs[logIndex]
return map[string]interface{}{
"logIndex": hexutil.Uint64(logIndex),
"blockNumber": (*hexutil.Big)(r.BlockNumber),
"blockHash": r.BlockHash,
"transactionHash": r.TxHash,
"transactionIndex": hexutil.Uint64(r.TransactionIndex),
"address": log.Address,
"data": hexutil.Bytes(log.Data),
"topics": log.Topics,
}
}

type RPCCallArgs struct {
From common.Address `json:"from"`
To *common.Address `json:"to"`
Expand Down
53 changes: 38 additions & 15 deletions packages/vm/core/evm/emulator/blockchaindb.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package emulator

import (
"fmt"
"io"
"math/big"

Expand Down Expand Up @@ -131,14 +132,18 @@ func (bc *BlockchainDB) GetPendingHeader(timestamp uint64) *types.Header {
}
}

func (bc *BlockchainDB) GetLatestPendingReceipt() *types.Receipt {
func (bc *BlockchainDB) getPendingCumulativeGasUsed() uint64 {
blockNumber := bc.GetPendingBlockNumber()
receiptArray := bc.getReceiptArray(blockNumber)
n := receiptArray.Len()
if n == 0 {
return nil
return 0
}
r, err := evmtypes.DecodeReceipt(receiptArray.GetAt(n - 1))
if err != nil {
panic(err)
}
return bc.GetReceiptByBlockNumberAndIndex(blockNumber, n-1)
return r.CumulativeGasUsed
}

func (bc *BlockchainDB) AddTransaction(tx *types.Transaction, receipt *types.Receipt) {
Expand Down Expand Up @@ -300,7 +305,7 @@ func (bc *BlockchainDB) addBlock(header *types.Header) {
bc.setNumber(blockNumber)
}

func (bc *BlockchainDB) GetReceiptByBlockNumberAndIndex(blockNumber uint64, txIndex uint32) *types.Receipt {
func (bc *BlockchainDB) getRawReceiptByBlockNumberAndIndex(blockNumber uint64, txIndex uint32) *types.Receipt {
receipts := bc.getReceiptArray(blockNumber)
if txIndex >= receipts.Len() {
return nil
Expand All @@ -309,29 +314,34 @@ func (bc *BlockchainDB) GetReceiptByBlockNumberAndIndex(blockNumber uint64, txIn
if err != nil {
panic(err)
}
return r
}

func (bc *BlockchainDB) getReceiptByBlockNumberAndIndex(
blockNumber uint64,
txIndex uint32,
cumulativeGasUsed uint64,
logIndex uint,
) *types.Receipt {
r := bc.getRawReceiptByBlockNumberAndIndex(blockNumber, txIndex)
tx := bc.GetTransactionByBlockNumberAndIndex(blockNumber, txIndex)

r.TxHash = tx.Hash()
r.BlockHash = bc.GetBlockHashByBlockNumber(blockNumber)
for i, log := range r.Logs {
log.TxHash = r.TxHash
log.TxIndex = uint(txIndex)
log.BlockHash = r.BlockHash
log.BlockNumber = blockNumber
log.Index = uint(i)
log.Index = logIndex + uint(i)
}
if tx.To() == nil {
from, _ := types.Sender(evmutil.Signer(big.NewInt(int64(bc.GetChainID()))), tx)
r.ContractAddress = crypto.CreateAddress(from, tx.Nonce())
}
r.GasUsed = r.CumulativeGasUsed
if txIndex > 0 {
prev, err := evmtypes.DecodeReceipt(receipts.GetAt(txIndex - 1))
if err != nil {
panic(err)
}
r.GasUsed -= prev.CumulativeGasUsed
}
r.GasUsed = r.CumulativeGasUsed - cumulativeGasUsed
r.BlockNumber = new(big.Int).SetUint64(blockNumber)
r.TransactionIndex = uint(txIndex)
return r
}

Expand All @@ -357,7 +367,11 @@ func (bc *BlockchainDB) GetReceiptByTxHash(txHash common.Hash) *types.Receipt {
return nil
}
i := bc.GetTxIndexInBlockByTxHash(txHash)
return bc.GetReceiptByBlockNumberAndIndex(blockNumber, i)
receipts := bc.GetReceiptsByBlockNumber(blockNumber)
if int(i) >= len(receipts) {
panic(fmt.Sprintf("cannot find evm receipt for tx %s", txHash))
}
return receipts[i]
}

func (bc *BlockchainDB) GetTransactionByBlockNumberAndIndex(blockNumber uint64, i uint32) *types.Transaction {
Expand Down Expand Up @@ -479,8 +493,17 @@ func (bc *BlockchainDB) GetTransactionsByBlockNumber(blockNumber uint64) []*type
func (bc *BlockchainDB) GetReceiptsByBlockNumber(blockNumber uint64) []*types.Receipt {
txArray := bc.getTxArray(blockNumber)
receipts := make([]*types.Receipt, txArray.Len())
logIndex := uint(0)
cumulativeGasUsed := uint64(0)
for i := range receipts {
receipts[i] = bc.GetReceiptByBlockNumberAndIndex(blockNumber, uint32(i))
receipts[i] = bc.getReceiptByBlockNumberAndIndex(
blockNumber,
uint32(i),
cumulativeGasUsed,
logIndex,
)
logIndex += uint(len(receipts[i].Logs))
cumulativeGasUsed = receipts[i].CumulativeGasUsed
}
return receipts
}
Expand Down
14 changes: 2 additions & 12 deletions packages/vm/core/evm/emulator/emulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,23 +311,13 @@ func (e *EVMEmulator) SendTransaction(
if result != nil {
gasUsed = result.UsedGas
}

cumulativeGasUsed := gasUsed
index := uint(0)
latest := e.BlockchainDB().GetLatestPendingReceipt()
if latest != nil {
cumulativeGasUsed += latest.CumulativeGasUsed
index = latest.TransactionIndex + 1
}
cumulativeGasUsed := e.BlockchainDB().getPendingCumulativeGasUsed() + gasUsed

receipt = &types.Receipt{
Type: tx.Type(),
CumulativeGasUsed: cumulativeGasUsed,
TxHash: tx.Hash(),
GasUsed: gasUsed,
Logs: statedb.GetLogs(tx.Hash()),
BlockNumber: pendingHeader.Number,
TransactionIndex: index,
Logs: statedb.GetLogs(),
}
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})

Expand Down
Loading

0 comments on commit 53f2e22

Please sign in to comment.