Commit 3870897b authored by vicotor's avatar vicotor

fix bug for withdrawal.

parent bafe92d3
...@@ -6,6 +6,7 @@ import ( ...@@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"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"
...@@ -18,7 +19,6 @@ import ( ...@@ -18,7 +19,6 @@ import (
"github.com/exchain/go-exchain/op-service/eth" "github.com/exchain/go-exchain/op-service/eth"
lru "github.com/hashicorp/golang-lru" lru "github.com/hashicorp/golang-lru"
"github.com/holiman/uint256" "github.com/holiman/uint256"
log "github.com/sirupsen/logrus"
"math/big" "math/big"
) )
...@@ -28,6 +28,7 @@ type ExChainAPI struct { ...@@ -28,6 +28,7 @@ type ExChainAPI struct {
chain chaindb.ChainDB chain chaindb.ChainDB
engine exchain.Engine engine exchain.Engine
cached *lru.Cache cached *lru.Cache
Log log.Logger
} }
func (e *ExChainAPI) BlockRefByNumber(ctx context.Context, num uint64) (eth.BlockRef, error) { func (e *ExChainAPI) BlockRefByNumber(ctx context.Context, num uint64) (eth.BlockRef, error) {
...@@ -80,15 +81,17 @@ func (e *ExChainAPI) WithdrawalProof(ctx context.Context, txHash common.Hash) (* ...@@ -80,15 +81,17 @@ func (e *ExChainAPI) WithdrawalProof(ctx context.Context, txHash common.Hash) (*
} }
res.Value = new(big.Int).SetBytes(wtx.Amount) res.Value = new(big.Int).SetBytes(wtx.Amount)
res.User = common.BytesToAddress(wtx.User) res.User = common.BytesToAddress(wtx.User)
res.Coin = []byte(wtx.Coin) res.Coin = wtx.Coin
oo, err := e.OutputV0AtBlock(ctx, receipt.BlockHeight) oo, err := e.OutputV0AtBlock(ctx, receipt.BlockHeight)
if err != nil { if err != nil {
log.WithField("error", err).Error("failed to get output for withdrawal proof") e.Log.Error("failed to get output v0 at block", "block", receipt.BlockHeight, "error", err)
return nil, err return nil, err
} }
res.Output = *oo res.Output = *oo
//e.Log.Info("WithdrawalProof response", "res", res)
return res, nil return res, nil
} }
...@@ -119,7 +122,7 @@ func (e *ExChainAPI) OutputV0AtBlock(ctx context.Context, number uint64) (*eth.O ...@@ -119,7 +122,7 @@ func (e *ExChainAPI) OutputV0AtBlock(ctx context.Context, number uint64) (*eth.O
wdtroot, err := e.GetWDTRoot(ctx, number) wdtroot, err := e.GetWDTRoot(ctx, number)
if err != nil { if err != nil {
log.WithField("error", err).Error("failed to get wdt root") e.Log.Error("failed to get wdt root", "err", err)
return nil, err return nil, err
} }
storageRoot := eth.Bytes32(wdtroot[:]) storageRoot := eth.Bytes32(wdtroot[:])
...@@ -196,7 +199,6 @@ func (e *ExChainAPI) L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel ...@@ -196,7 +199,6 @@ func (e *ExChainAPI) L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel
return eth.L2BlockRef{}, err return eth.L2BlockRef{}, err
} }
ref, err := derive.PayloadToBlockRef(e.rollup, eth.NewExecutePayload(blk)) ref, err := derive.PayloadToBlockRef(e.rollup, eth.NewExecutePayload(blk))
log.WithField("label", label).WithField("ref", ref).Info("L2BlockRefByLabel")
return ref, err return ref, err
default: default:
return eth.L2BlockRef{}, errors.New("unsupported label") return eth.L2BlockRef{}, errors.New("unsupported label")
...@@ -236,12 +238,13 @@ var ( ...@@ -236,12 +238,13 @@ var (
_ driver.L2Chain = (*ExChainAPI)(nil) _ driver.L2Chain = (*ExChainAPI)(nil)
) )
func NewEngineAPI(cfg *rollup.Config, database chaindb.ChainDB, engine exchain.Engine) *ExChainAPI { func NewEngineAPI(cfg *rollup.Config, database chaindb.ChainDB, engine exchain.Engine, l log.Logger) *ExChainAPI {
cache, _ := lru.New(100) cache, _ := lru.New(100)
return &ExChainAPI{ return &ExChainAPI{
rollup: cfg, rollup: cfg,
chain: database, chain: database,
engine: engine, engine: engine,
cached: cache, cached: cache,
Log: l,
} }
} }
package engine
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/exchain/go-exchain/op-service/eth"
"testing"
)
func TestOutput(t *testing.T) {
storageRoot := "0xa643dc6f566a3d40490d9d973679230dd44a2f9314da325cecc83e10a183d273"
output := &eth.OutputV0{
StateRoot: eth.Bytes32{},
MessagePasserStorageRoot: eth.Bytes32{},
BlockHash: common.HexToHash("0xe48501598976f79351f9e2f2cc4474ca5646999aa0dfe6a469c5a13c3d02f7b4"),
}
if err := output.MessagePasserStorageRoot.UnmarshalText([]byte(storageRoot)); err != nil {
t.Fatalf("failed to unmarshal storage root: %v", err)
}
//t.Log("message passer root", output.MessagePasserStorageRoot.String())
marshaled := output.Marshal()
outputRoot := eth.Bytes32(crypto.Keccak256Hash(marshaled))
t.Logf("Storage root: %s", outputRoot.String())
}
...@@ -52,7 +52,7 @@ func (w *WDT) AddTx(tx *nebulav1.Transaction) error { ...@@ -52,7 +52,7 @@ func (w *WDT) AddTx(tx *nebulav1.Transaction) error {
// value is []byte("1") // value is []byte("1")
item := wrapper.NewTxWrapper(tx).WithdrawalHash() item := wrapper.NewTxWrapper(tx).WithdrawalHash()
addr := common.Address{} addr := common.Address{}
return w.st.UpdateStorage(addr, item.Bytes(), []byte("1")) return w.st.UpdateStorage(addr, item.Bytes(), []byte{0x1})
} }
func (w *WDT) Proof(key []byte) ([]string, error) { func (w *WDT) Proof(key []byte) ([]string, error) {
......
package wdt
import (
"github.com/ethereum/go-ethereum/common"
nebulav1 "github.com/exchain/go-exchain/exchain/protocol/gen/go/nebula/v1"
"github.com/exchain/go-exchain/exchain/wrapper"
"math/big"
"testing"
)
func TestProof(t *testing.T) {
wtx := nebulav1.WithdrawTransaction{
User: common.HexToAddress("0x9910048204119cCA216a2325A3e2fA05eD4977ef").Bytes(),
Coin: "ETH",
Amount: big.NewInt(5e18).Bytes(),
}
tx := &nebulav1.Transaction{
TxType: nebulav1.TxType_WithdrawTx,
Nonce: common.Hash{}.Bytes(),
Proxy: false,
Tx: &nebulav1.Transaction_WithdrawTx{
WithdrawTx: &wtx,
},
Signature: &nebulav1.Signature{
R: make([]byte, 32),
S: make([]byte, 32),
V: 0,
},
}
wraTx := wrapper.NewTxWrapper(tx)
te := NewWdt()
te.AddTx(tx)
item := wraTx.WithdrawalHash()
t.Logf("WithdrawalHash %s", item.Hex())
txHash := wraTx.Hash()
t.Logf("tx hash: %s", txHash.Hex())
root := te.Root()
t.Logf("Root: %s", root.Hex())
proof, err := te.Proof(item.Bytes())
if err != nil {
t.Errorf("Proof err: %v", err)
}
t.Logf("Proof: %v", proof)
}
...@@ -2,19 +2,18 @@ package wrapper ...@@ -2,19 +2,18 @@ package wrapper
import ( import (
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"math/big" "math/big"
"testing" "testing"
) )
func TestWhash(t *testing.T) { func TestWhash(t *testing.T) {
user := common.HexToAddress("0x000000000000000000000000000000000000dead") user := common.HexToAddress("0x9910048204119cCA216a2325A3e2fA05eD4977ef")
coin := "ETH" coin := "ETH"
value := big.NewInt(1e18) value := big.NewInt(5e18)
//ethers.keccak256(ethers.toUtf8Bytes("test transaction")); //ethers.keccak256(ethers.toUtf8Bytes("test transaction"));
hash := crypto.Keccak256Hash([]byte("test transaction")) hash := common.HexToHash("0xb2015d93f463a4d67145ab45f7498d426fc39879059311b863b3586240974305")
whash := Whash(user, coin, value, hash) whash := withdrawalHash(user, coin, value, hash)
expected := common.HexToHash("0xe7251ba12a5199190894e1c38c2bc80324901f054ccd2523640e47032630c560") expected := common.HexToHash("0x4939ac2eefe1c20d05fa0a319d8dd8fa891a333800a68c4644e7bdc203c18b3d")
if whash != expected { if whash != expected {
t.Errorf("expected %s, got %s", expected.Hex(), whash.Hex()) t.Errorf("expected %s, got %s", expected.Hex(), whash.Hex())
} else { } else {
......
...@@ -406,7 +406,7 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config) error { ...@@ -406,7 +406,7 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config) error {
chain := chaindb.NewChainDB(n.log, n.db) chain := chaindb.NewChainDB(n.log, n.db)
n.engineIns = processengine.NewEngine(n.cfg.NodeDataPath, n.log, chain) n.engineIns = processengine.NewEngine(n.cfg.NodeDataPath, n.log, chain)
n.engineIns = mockengine.NewEngine(n.cfg.NodeDataPath, n.log, chain) n.engineIns = mockengine.NewEngine(n.cfg.NodeDataPath, n.log, chain)
n.l2Source = engine.NewEngineAPI(&n.cfg.Rollup, chain, n.engineIns) n.l2Source = engine.NewEngineAPI(&n.cfg.Rollup, chain, n.engineIns, n.log)
if n.engineIns == nil { if n.engineIns == nil {
return errors.New("failed to create L2 engine") return errors.New("failed to create L2 engine")
} }
......
...@@ -2,6 +2,7 @@ package proposer ...@@ -2,6 +2,7 @@ package proposer
import ( import (
"context" "context"
"encoding/hex"
"errors" "errors"
"fmt" "fmt"
"math/big" "math/big"
...@@ -410,7 +411,6 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out ...@@ -410,7 +411,6 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out
return err return err
} }
l.Log.Info("Proposing output root", "output", output.OutputRoot, "block", output.BlockRef)
var receipt *types.Receipt var receipt *types.Receipt
if l.Cfg.DisputeGameFactoryAddr != nil { if l.Cfg.DisputeGameFactoryAddr != nil {
candidate, err := l.ProposeL2OutputDGFTxCandidate(ctx, output) candidate, err := l.ProposeL2OutputDGFTxCandidate(ctx, output)
...@@ -426,6 +426,7 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out ...@@ -426,6 +426,7 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out
if err != nil { if err != nil {
return err return err
} }
l.Log.Info("L2OutputSubmitter transaction", "data", hex.EncodeToString(data))
receipt, err = l.Txmgr.Send(ctx, txmgr.TxCandidate{ receipt, err = l.Txmgr.Send(ctx, txmgr.TxCandidate{
TxData: data, TxData: data,
To: l.Cfg.L2OutputOracleAddr, To: l.Cfg.L2OutputOracleAddr,
...@@ -512,6 +513,7 @@ func (l *L2OutputSubmitter) waitNodeSync() error { ...@@ -512,6 +513,7 @@ func (l *L2OutputSubmitter) waitNodeSync() error {
func (l *L2OutputSubmitter) proposeOutput(ctx context.Context, output *eth.OutputResponse) { func (l *L2OutputSubmitter) proposeOutput(ctx context.Context, output *eth.OutputResponse) {
cCtx, cancel := context.WithTimeout(ctx, 10*time.Minute) cCtx, cancel := context.WithTimeout(ctx, 10*time.Minute)
defer cancel() defer cancel()
l.Log.Info("Proposing output", "output", output.OutputRoot, "block", output.BlockRef)
if err := l.sendTransaction(cCtx, output); err != nil { if err := l.sendTransaction(cCtx, output); err != nil {
l.Log.Error("Failed to send proposal transaction", l.Log.Error("Failed to send proposal transaction",
......
...@@ -270,25 +270,38 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -270,25 +270,38 @@ func (l *Operator) DoOperator(ctx context.Context) {
proof, err := rollupClient.WithdrawalProof(ctx, common.HexToHash(tx.TxHash)) proof, err := rollupClient.WithdrawalProof(ctx, common.HexToHash(tx.TxHash))
if err != nil { if err != nil {
l.Log.Error("failed to get withdrawal proof", "err", err) l.Log.Error("failed to get withdrawal proof", "err", err)
break return
} else { } else {
//l.Log.Info("withdrawal proof", "tx", tx.TxHash, "proof", proof)
withdrawalProof := make([][]byte, len(proof.Proof))
for i, p := range proof.Proof {
withdrawalProof[i] = common.FromHex(p)
}
// call contract to do withdrawal. // call contract to do withdrawal.
params := bindings.TypesBatchExChainWithdrawalParam{ params := bindings.TypesBatchExChainWithdrawalParam{
WithdrawalProof: make([][]byte, len(proof.Proof)), WithdrawalProof: withdrawalProof,
Value: proof.Value, Value: proof.Value,
User: proof.User, User: proof.User,
Coin: proof.Coin, Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash), TxHash: common.HexToHash(tx.TxHash),
} }
for i, p := range proof.Proof { paramOne := bindings.TypesExChainWithdrawalParam{
params.WithdrawalProof[i] = common.HexToHash(p).Bytes() Value: proof.Value,
User: proof.User,
Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash),
} }
ooProof := bindings.TypesOutputRootProof{ ooProof := bindings.TypesOutputRootProof{
StateRoot: proof.Output.StateRoot, StateRoot: proof.Output.StateRoot,
MessagePasserStorageRoot: proof.Output.MessagePasserStorageRoot, MessagePasserStorageRoot: proof.Output.MessagePasserStorageRoot,
LatestBlockhash: proof.Output.BlockHash, LatestBlockhash: proof.Output.BlockHash,
} }
err = l.doWithdrawal(ctx, []bindings.TypesBatchExChainWithdrawalParam{params}, ooIndex, ooProof) err = l.doWithdrawalOne(ctx, paramOne, ooIndex, ooProof, withdrawalProof)
_ = params
//err = l.doWithdrawalBatch(ctx, []bindings.TypesBatchExChainWithdrawalParam{params}, ooIndex, ooProof)
if err != nil { if err != nil {
l.Log.Error("failed to do withdrawal", "err", err) l.Log.Error("failed to do withdrawal", "err", err)
return return
...@@ -361,23 +374,34 @@ func (l *Operator) DoOperator(ctx context.Context) { ...@@ -361,23 +374,34 @@ func (l *Operator) DoOperator(ctx context.Context) {
l.Log.Error("failed to get withdrawal proof", "err", err) l.Log.Error("failed to get withdrawal proof", "err", err)
break break
} else { } else {
withdrawalProof := make([][]byte, len(proof.Proof))
for i, p := range proof.Proof {
withdrawalProof[i] = common.FromHex(p)
}
// call contract to do withdrawal. // call contract to do withdrawal.
params := bindings.TypesBatchExChainWithdrawalParam{ params := bindings.TypesBatchExChainWithdrawalParam{
WithdrawalProof: make([][]byte, len(proof.Proof)), WithdrawalProof: withdrawalProof,
Value: proof.Value, Value: proof.Value,
User: proof.User, User: proof.User,
Coin: proof.Coin, Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash), TxHash: common.HexToHash(tx.TxHash),
} }
for i, p := range proof.Proof { paramOne := bindings.TypesExChainWithdrawalParam{
params.WithdrawalProof[i] = common.HexToHash(p).Bytes() Value: proof.Value,
User: proof.User,
Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash),
} }
ooProof := bindings.TypesOutputRootProof{ ooProof := bindings.TypesOutputRootProof{
StateRoot: proof.Output.StateRoot, StateRoot: proof.Output.StateRoot,
MessagePasserStorageRoot: proof.Output.MessagePasserStorageRoot, MessagePasserStorageRoot: proof.Output.MessagePasserStorageRoot,
LatestBlockhash: proof.Output.BlockHash, LatestBlockhash: proof.Output.BlockHash,
} }
err = l.doWithdrawal(ctx, []bindings.TypesBatchExChainWithdrawalParam{params}, ooIndex, ooProof) err = l.doWithdrawalOne(ctx, paramOne, ooIndex, ooProof, withdrawalProof)
_ = params
//err = l.doWithdrawalBatch(ctx, []bindings.TypesBatchExChainWithdrawalParam{params}, ooIndex, ooProof)
if err != nil { if err != nil {
l.Log.Error("failed to do withdrawal", "err", err) l.Log.Error("failed to do withdrawal", "err", err)
return return
...@@ -399,6 +423,10 @@ func (l *Operator) BatchExChainWithdrawalTxData(params []bindings.TypesBatchExCh ...@@ -399,6 +423,10 @@ func (l *Operator) BatchExChainWithdrawalTxData(params []bindings.TypesBatchExCh
return l.portalABI.Pack("batchExChainWithdrawal", params, l2OutputIndex, outputRootProof) return l.portalABI.Pack("batchExChainWithdrawal", params, l2OutputIndex, outputRootProof)
} }
func (l *Operator) ExChainWithdrawalTxData(param bindings.TypesExChainWithdrawalParam, l2OutputIndex *big.Int, outputRoot bindings.TypesOutputRootProof, proof [][]byte) ([]byte, error) {
return l.portalABI.Pack("exChainWithdrawal", param, l2OutputIndex, outputRoot, proof)
}
// sendTransaction creates & sends transactions through the underlying transaction manager. // sendTransaction creates & sends transactions through the underlying transaction manager.
func (l *Operator) sendTransaction(ctx context.Context, params []bindings.TypesBatchExChainWithdrawalParam, l2OutputIndex *big.Int, outputRootProof bindings.TypesOutputRootProof) error { func (l *Operator) sendTransaction(ctx context.Context, params []bindings.TypesBatchExChainWithdrawalParam, l2OutputIndex *big.Int, outputRootProof bindings.TypesOutputRootProof) error {
l.Log.Info("DoWithdrawal", "l2OutputIndex", l2OutputIndex) l.Log.Info("DoWithdrawal", "l2OutputIndex", l2OutputIndex)
...@@ -408,10 +436,40 @@ func (l *Operator) sendTransaction(ctx context.Context, params []bindings.TypesB ...@@ -408,10 +436,40 @@ func (l *Operator) sendTransaction(ctx context.Context, params []bindings.TypesB
if err != nil { if err != nil {
return err return err
} }
//l.Log.Info("BatchExChainWithdrawalTxData", "data", hex.EncodeToString(data))
receipt, err = l.Txmgr.Send(ctx, txmgr.TxCandidate{ receipt, err = l.Txmgr.Send(ctx, txmgr.TxCandidate{
TxData: data, TxData: data,
To: l.Cfg.PortalAddr, To: l.Cfg.PortalAddr,
GasLimit: 0, GasLimit: 10000000,
})
if err != nil {
return err
}
}
if receipt.Status == types.ReceiptStatusFailed {
l.Log.Error("Proposer withdrawal tx successfully published but reverted", "tx_hash", receipt.TxHash)
} else {
l.Log.Info("Proposer withdrawal tx successfully published",
"tx_hash", receipt.TxHash)
}
return nil
}
// sendTransaction creates & sends transactions through the underlying transaction manager.
func (l *Operator) sendTransactionOne(ctx context.Context, param bindings.TypesExChainWithdrawalParam, l2OutputIndex *big.Int, outputRoot bindings.TypesOutputRootProof, proof [][]byte) error {
//l.Log.Info("DoWithdrawalOne", "l2OutputIndex", l2OutputIndex)
var receipt *types.Receipt
{
data, err := l.ExChainWithdrawalTxData(param, l2OutputIndex, outputRoot, proof)
if err != nil {
return err
}
//l.Log.Info("ExChainWithdrawalTxData", "data", hex.EncodeToString(data))
receipt, err = l.Txmgr.Send(ctx, txmgr.TxCandidate{
TxData: data,
To: l.Cfg.PortalAddr,
GasLimit: 10000000,
}) })
if err != nil { if err != nil {
return err return err
...@@ -470,7 +528,7 @@ func (l *Operator) waitNodeSync() error { ...@@ -470,7 +528,7 @@ func (l *Operator) waitNodeSync() error {
return dial.WaitRollupSync(l.ctx, l.Log, rollupClient, l1head, time.Second*12) return dial.WaitRollupSync(l.ctx, l.Log, rollupClient, l1head, time.Second*12)
} }
func (l *Operator) doWithdrawal(ctx context.Context, params []bindings.TypesBatchExChainWithdrawalParam, l2OutputIndex *big.Int, outputRootProof bindings.TypesOutputRootProof) error { func (l *Operator) doWithdrawalBatch(ctx context.Context, params []bindings.TypesBatchExChainWithdrawalParam, l2OutputIndex *big.Int, outputRootProof bindings.TypesOutputRootProof) error {
cCtx, cancel := context.WithTimeout(ctx, 10*time.Minute) cCtx, cancel := context.WithTimeout(ctx, 10*time.Minute)
defer cancel() defer cancel()
...@@ -481,3 +539,15 @@ func (l *Operator) doWithdrawal(ctx context.Context, params []bindings.TypesBatc ...@@ -481,3 +539,15 @@ func (l *Operator) doWithdrawal(ctx context.Context, params []bindings.TypesBatc
} }
return nil return nil
} }
func (l *Operator) doWithdrawalOne(ctx context.Context, param bindings.TypesExChainWithdrawalParam, l2OutputIndex *big.Int, outputRoot bindings.TypesOutputRootProof, proof [][]byte) error {
cCtx, cancel := context.WithTimeout(ctx, 10*time.Minute)
defer cancel()
if err := l.sendTransactionOne(cCtx, param, l2OutputIndex, outputRoot, proof); err != nil {
l.Log.Error("Failed to send proposal withdrawal transaction",
"err", err)
return err
}
return nil
}
...@@ -10,5 +10,5 @@ type WithdrawalProof struct { ...@@ -10,5 +10,5 @@ type WithdrawalProof struct {
Proof []string Proof []string
Value *big.Int Value *big.Int
User common.Address User common.Address
Coin []byte Coin string
} }
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