Commit bafe92d3 authored by vicotor's avatar vicotor

fix bug

parent b6152b2f
...@@ -2,11 +2,17 @@ package mockengine ...@@ -2,11 +2,17 @@ package mockengine
import ( import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/log"
"github.com/exchain/go-exchain/exchain" "github.com/exchain/go-exchain/exchain"
"github.com/exchain/go-exchain/exchain/chaindb" "github.com/exchain/go-exchain/exchain/chaindb"
nebulav1 "github.com/exchain/go-exchain/exchain/protocol/gen/go/nebula/v1" nebulav1 "github.com/exchain/go-exchain/exchain/protocol/gen/go/nebula/v1"
"github.com/exchain/go-exchain/exchain/wrapper" "github.com/exchain/go-exchain/exchain/wrapper"
"math/big"
)
var (
testFrom = common.HexToAddress("0x00000000000000000000000000000000000000AB")
) )
type MockEngine struct { type MockEngine struct {
...@@ -19,6 +25,34 @@ func (m MockEngine) Start() error { ...@@ -19,6 +25,34 @@ func (m MockEngine) Start() error {
return nil return nil
} }
func (m MockEngine) fortest(header *nebulav1.BlockHeader) []*nebulav1.Transaction {
if header.Height == 100 {
// add a withdrawal tx.
wtx := nebulav1.WithdrawTransaction{
User: common.HexToAddress("0x9910048204119cCA216a2325A3e2fA05eD4977ef").Bytes(),
Coin: "ETH",
Amount: big.NewInt(5e18).Bytes(),
}
tx := &nebulav1.Transaction{
TxType: nebulav1.TxType_WithdrawTx,
User: testFrom.Hex(),
Nonce: exchain.GetNonce().Bytes(),
Proxy: false,
Tx: &nebulav1.Transaction_WithdrawTx{
WithdrawTx: &wtx,
},
Signature: &nebulav1.Signature{
R: make([]byte, 32),
S: make([]byte, 32),
V: 0,
},
}
return []*nebulav1.Transaction{tx}
}
return nil
}
func (m MockEngine) NewPayload(params exchain.PayloadParams) (exchain.ExecutionResult, error) { func (m MockEngine) NewPayload(params exchain.PayloadParams) (exchain.ExecutionResult, error) {
parent, err := m.chain.GetBlockByLabel(chaindb.ExChainBlockLatest) parent, err := m.chain.GetBlockByLabel(chaindb.ExChainBlockLatest)
if err != nil { if err != nil {
...@@ -34,7 +68,16 @@ func (m MockEngine) NewPayload(params exchain.PayloadParams) (exchain.ExecutionR ...@@ -34,7 +68,16 @@ func (m MockEngine) NewPayload(params exchain.PayloadParams) (exchain.ExecutionR
L1Height: params.L1Info.Number, L1Height: params.L1Info.Number,
AppRoot: make([]byte, 0), AppRoot: make([]byte, 0),
} }
receipts, err := m.ProcessTx(header, params.Transactions) txs := &nebulav1.TransactionList{
Txs: make([]*nebulav1.Transaction, 0),
}
if params.Transactions != nil {
txs.Txs = append(txs.Txs, params.Transactions.Txs...)
}
if testTxs := m.fortest(header); testTxs != nil {
txs.Txs = append(txs.Txs, testTxs...)
}
receipts, err := m.ProcessTx(header, txs)
if err != nil { if err != nil {
m.log.Error("failed to process tx", "err", err) m.log.Error("failed to process tx", "err", err)
return exchain.ExecutionResult{}, err return exchain.ExecutionResult{}, err
...@@ -43,7 +86,7 @@ func (m MockEngine) NewPayload(params exchain.PayloadParams) (exchain.ExecutionR ...@@ -43,7 +86,7 @@ func (m MockEngine) NewPayload(params exchain.PayloadParams) (exchain.ExecutionR
result := exchain.ExecutionResult{ result := exchain.ExecutionResult{
Payload: &nebulav1.Block{ Payload: &nebulav1.Block{
Header: header, Header: header,
Transactions: params.Transactions, Transactions: txs,
}, },
Receipts: receipts, Receipts: receipts,
} }
......
...@@ -65,7 +65,7 @@ func NewOperator(setup DriverSetup, db metadb.Database) (_ *Operator, err error) ...@@ -65,7 +65,7 @@ func NewOperator(setup DriverSetup, db metadb.Database) (_ *Operator, err error)
type OperatorProgress struct { type OperatorProgress struct {
BlockNumber uint64 `json:"block_number"` BlockNumber uint64 `json:"block_number"`
Index uint64 `json:"index"` Finished uint64 `json:"finished"`
Total uint64 `json:"total"` Total uint64 `json:"total"`
} }
...@@ -240,7 +240,7 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -240,7 +240,7 @@ func (l *Operator) DoOperator(ctx context.Context) {
} }
l.Log.Info("operator latest block number from l2oo", "l2Latest", l2Latest, "progress", progress) l.Log.Info("operator latest block number from l2oo", "l2Latest", l2Latest, "progress", progress)
currentFinished := false currentFinished := false
if progress.Total == 0 || progress.Index == (progress.Total-1) { if progress.Total == 0 || progress.Finished == progress.Total {
currentFinished = true currentFinished = true
} }
// 2. check current process is finished. // 2. check current process is finished.
...@@ -263,9 +263,9 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -263,9 +263,9 @@ func (l *Operator) DoOperator(ctx context.Context) {
progress.Total = uint64(len(task)) progress.Total = uint64(len(task))
} }
index := progress.Index finished := progress.Finished
for index < progress.Total { for finished < progress.Total {
tx := task[progress.Index] tx := task[finished]
proof, err := rollupClient.WithdrawalProof(ctx, common.HexToHash(tx.TxHash)) proof, err := rollupClient.WithdrawalProof(ctx, common.HexToHash(tx.TxHash))
if err != nil { if err != nil {
...@@ -293,11 +293,11 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -293,11 +293,11 @@ func (l *Operator) DoOperator(ctx context.Context) {
l.Log.Error("failed to do withdrawal", "err", err) l.Log.Error("failed to do withdrawal", "err", err)
return return
} else { } else {
index++ finished++
// update process. // update process.
l.SetProgress(OperatorProgress{ l.SetProgress(OperatorProgress{
BlockNumber: progress.BlockNumber, BlockNumber: progress.BlockNumber,
Index: index, Finished: finished,
Total: progress.Total, Total: progress.Total,
}) })
} }
...@@ -328,7 +328,7 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -328,7 +328,7 @@ func (l *Operator) DoOperator(ctx context.Context) {
l.SetOperatorTaskList(OperatorTaskList{}) l.SetOperatorTaskList(OperatorTaskList{})
l.SetProgress(OperatorProgress{ l.SetProgress(OperatorProgress{
BlockNumber: blkNum, BlockNumber: blkNum,
Index: 0, Finished: 0,
Total: 0, Total: 0,
}) })
continue continue
...@@ -337,7 +337,7 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -337,7 +337,7 @@ func (l *Operator) DoOperator(ctx context.Context) {
} }
newProgress := OperatorProgress{ newProgress := OperatorProgress{
BlockNumber: blkNum, BlockNumber: blkNum,
Index: 0, Finished: 0,
Total: uint64(len(withDrawalTxs)), Total: uint64(len(withDrawalTxs)),
} }
tasks := make([]OperatorTask, 0) tasks := make([]OperatorTask, 0)
...@@ -351,10 +351,10 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -351,10 +351,10 @@ func (l *Operator) DoOperator(ctx context.Context) {
l.SetProgress(newProgress) l.SetProgress(newProgress)
// 5. to process each withdrawal tx. // 5. to process each withdrawal tx.
index := newProgress.Index finished := newProgress.Finished
for index < newProgress.Total { for finished < newProgress.Total {
tx := tasks[index] tx := tasks[finished]
proof, err := rollupClient.WithdrawalProof(ctx, common.HexToHash(tx.TxHash)) proof, err := rollupClient.WithdrawalProof(ctx, common.HexToHash(tx.TxHash))
if err != nil { if err != nil {
...@@ -382,11 +382,11 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -382,11 +382,11 @@ func (l *Operator) DoOperator(ctx context.Context) {
l.Log.Error("failed to do withdrawal", "err", err) l.Log.Error("failed to do withdrawal", "err", err)
return return
} else { } else {
index++ finished++
// update process. // update process.
l.SetProgress(OperatorProgress{ l.SetProgress(OperatorProgress{
BlockNumber: newProgress.BlockNumber, BlockNumber: newProgress.BlockNumber,
Index: index, Finished: finished,
Total: newProgress.Total, Total: newProgress.Total,
}) })
} }
......
...@@ -430,6 +430,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { ...@@ -430,6 +430,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
// revert GasEstimation(); // revert GasEstimation();
// } // }
} }
event Println(uint256 line);
/// @notice withdrawal for a user. /// @notice withdrawal for a user.
...@@ -446,15 +447,20 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { ...@@ -446,15 +447,20 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
external external
whenNotPaused whenNotPaused
{ {
emit Println(1);
if (_param.user == address(this)) revert BadTarget(); if (_param.user == address(this)) revert BadTarget();
emit Println(2);
bytes32 outputRoot = l2Oracle.getL2Output(_l2OutputIndex).outputRoot; bytes32 outputRoot = l2Oracle.getL2Output(_l2OutputIndex).outputRoot;
emit Println(3);
bytes32 withdrawalHash = Hashing.hashExChainWithdrawal(_param); bytes32 withdrawalHash = Hashing.hashExChainWithdrawal(_param);
emit Println(4);
ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash]; ProvenWithdrawal memory provenWithdrawal = provenWithdrawals[withdrawalHash];
require( require(
provenWithdrawal.timestamp == 0 provenWithdrawal.timestamp == 0
|| l2Oracle.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot != provenWithdrawal.outputRoot, || l2Oracle.getL2Output(provenWithdrawal.l2OutputIndex).outputRoot != provenWithdrawal.outputRoot,
"OptimismPortal: withdrawal hash has already been proven" "OptimismPortal: withdrawal hash has already been proven"
); );
emit Println(5);
// Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract // Verify that the hash of this withdrawal was stored in the L2toL1MessagePasser contract
// on L2. If this is true, under the assumption that the SecureMerkleTrie does not have // on L2. If this is true, under the assumption that the SecureMerkleTrie does not have
...@@ -469,6 +475,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { ...@@ -469,6 +475,7 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
}), }),
"OptimismPortal: invalid withdrawal inclusion proof" "OptimismPortal: invalid withdrawal inclusion proof"
); );
emit Println(6);
// Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and // Designate the withdrawalHash as proven by storing the `outputRoot`, `timestamp`, and
// `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be // `l2BlockNumber` in the `provenWithdrawals` mapping. A `withdrawalHash` can only be
...@@ -478,23 +485,29 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver { ...@@ -478,23 +485,29 @@ contract OptimismPortal is Initializable, ResourceMetering, ISemver {
timestamp: uint128(block.timestamp), timestamp: uint128(block.timestamp),
l2OutputIndex: uint128(_l2OutputIndex) l2OutputIndex: uint128(_l2OutputIndex)
}); });
emit Println(7);
// Check that this withdrawal has not already been finalized, this is replay protection. // Check that this withdrawal has not already been finalized, this is replay protection.
require(finalizedWithdrawals[withdrawalHash] == false, "OptimismPortal: withdrawal has already been finalized"); require(finalizedWithdrawals[withdrawalHash] == false, "OptimismPortal: withdrawal has already been finalized");
emit Println(8);
// Mark the withdrawal as finalized so it can't be replayed. // Mark the withdrawal as finalized so it can't be replayed.
finalizedWithdrawals[withdrawalHash] = true; finalizedWithdrawals[withdrawalHash] = true;
emit Println(9);
// Set the l2Sender so contracts know who triggered this withdrawal on L2. // Set the l2Sender so contracts know who triggered this withdrawal on L2.
// This acts as a reentrancy guard. // This acts as a reentrancy guard.
l2Sender = msg.sender; l2Sender = msg.sender;
bool success; bool success;
emit Println(10);
(address token,) = gasPayingToken(); (address token,) = gasPayingToken();
if (token == Constants.ETHER) { if (token == Constants.ETHER) {
emit Println(11);
success = SafeCall.send(_param.user, _param.value); success = SafeCall.send(_param.user, _param.value);
} else { } else {
// Cannot call the token contract directly from the portal. This would allow an attacker // Cannot call the token contract directly from the portal. This would allow an attacker
// to call approve from a withdrawal and drain the balance of the portal. // to call approve from a withdrawal and drain the balance of the portal.
emit Println(12);
if (_param.user == token) revert BadTarget(); if (_param.user == token) revert BadTarget();
// Only transfer value when a non zero value is specified. This saves gas in the case of // Only transfer value when a non zero value is specified. This saves gas in the case of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment