Commit 3870897b authored by vicotor's avatar vicotor

fix bug for withdrawal.

parent bafe92d3
......@@ -6,6 +6,7 @@ import (
"fmt"
"github.com/ethereum/go-ethereum/common"
"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/chaindb"
nebulav1 "github.com/exchain/go-exchain/exchain/protocol/gen/go/nebula/v1"
......@@ -18,7 +19,6 @@ import (
"github.com/exchain/go-exchain/op-service/eth"
lru "github.com/hashicorp/golang-lru"
"github.com/holiman/uint256"
log "github.com/sirupsen/logrus"
"math/big"
)
......@@ -28,6 +28,7 @@ type ExChainAPI struct {
chain chaindb.ChainDB
engine exchain.Engine
cached *lru.Cache
Log log.Logger
}
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) (*
}
res.Value = new(big.Int).SetBytes(wtx.Amount)
res.User = common.BytesToAddress(wtx.User)
res.Coin = []byte(wtx.Coin)
res.Coin = wtx.Coin
oo, err := e.OutputV0AtBlock(ctx, receipt.BlockHeight)
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
}
res.Output = *oo
//e.Log.Info("WithdrawalProof response", "res", res)
return res, nil
}
......@@ -119,7 +122,7 @@ func (e *ExChainAPI) OutputV0AtBlock(ctx context.Context, number uint64) (*eth.O
wdtroot, err := e.GetWDTRoot(ctx, number)
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
}
storageRoot := eth.Bytes32(wdtroot[:])
......@@ -196,7 +199,6 @@ func (e *ExChainAPI) L2BlockRefByLabel(ctx context.Context, label eth.BlockLabel
return eth.L2BlockRef{}, err
}
ref, err := derive.PayloadToBlockRef(e.rollup, eth.NewExecutePayload(blk))
log.WithField("label", label).WithField("ref", ref).Info("L2BlockRefByLabel")
return ref, err
default:
return eth.L2BlockRef{}, errors.New("unsupported label")
......@@ -236,12 +238,13 @@ var (
_ 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)
return &ExChainAPI{
rollup: cfg,
chain: database,
engine: engine,
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 {
// value is []byte("1")
item := wrapper.NewTxWrapper(tx).WithdrawalHash()
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) {
......
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
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"math/big"
"testing"
)
func TestWhash(t *testing.T) {
user := common.HexToAddress("0x000000000000000000000000000000000000dead")
user := common.HexToAddress("0x9910048204119cCA216a2325A3e2fA05eD4977ef")
coin := "ETH"
value := big.NewInt(1e18)
value := big.NewInt(5e18)
//ethers.keccak256(ethers.toUtf8Bytes("test transaction"));
hash := crypto.Keccak256Hash([]byte("test transaction"))
whash := Whash(user, coin, value, hash)
expected := common.HexToHash("0xe7251ba12a5199190894e1c38c2bc80324901f054ccd2523640e47032630c560")
hash := common.HexToHash("0xb2015d93f463a4d67145ab45f7498d426fc39879059311b863b3586240974305")
whash := withdrawalHash(user, coin, value, hash)
expected := common.HexToHash("0x4939ac2eefe1c20d05fa0a319d8dd8fa891a333800a68c4644e7bdc203c18b3d")
if whash != expected {
t.Errorf("expected %s, got %s", expected.Hex(), whash.Hex())
} else {
......
......@@ -406,7 +406,7 @@ func (n *OpNode) initL2(ctx context.Context, cfg *Config) error {
chain := chaindb.NewChainDB(n.log, n.db)
n.engineIns = processengine.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 {
return errors.New("failed to create L2 engine")
}
......
......@@ -2,6 +2,7 @@ package proposer
import (
"context"
"encoding/hex"
"errors"
"fmt"
"math/big"
......@@ -410,7 +411,6 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out
return err
}
l.Log.Info("Proposing output root", "output", output.OutputRoot, "block", output.BlockRef)
var receipt *types.Receipt
if l.Cfg.DisputeGameFactoryAddr != nil {
candidate, err := l.ProposeL2OutputDGFTxCandidate(ctx, output)
......@@ -426,6 +426,7 @@ func (l *L2OutputSubmitter) sendTransaction(ctx context.Context, output *eth.Out
if err != nil {
return err
}
l.Log.Info("L2OutputSubmitter transaction", "data", hex.EncodeToString(data))
receipt, err = l.Txmgr.Send(ctx, txmgr.TxCandidate{
TxData: data,
To: l.Cfg.L2OutputOracleAddr,
......@@ -512,6 +513,7 @@ func (l *L2OutputSubmitter) waitNodeSync() error {
func (l *L2OutputSubmitter) proposeOutput(ctx context.Context, output *eth.OutputResponse) {
cCtx, cancel := context.WithTimeout(ctx, 10*time.Minute)
defer cancel()
l.Log.Info("Proposing output", "output", output.OutputRoot, "block", output.BlockRef)
if err := l.sendTransaction(cCtx, output); err != nil {
l.Log.Error("Failed to send proposal transaction",
......
......@@ -270,25 +270,38 @@ func (l *Operator) DoOperator(ctx context.Context) {
proof, err := rollupClient.WithdrawalProof(ctx, common.HexToHash(tx.TxHash))
if err != nil {
l.Log.Error("failed to get withdrawal proof", "err", err)
break
return
} 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.
params := bindings.TypesBatchExChainWithdrawalParam{
WithdrawalProof: make([][]byte, len(proof.Proof)),
WithdrawalProof: withdrawalProof,
Value: proof.Value,
User: proof.User,
Coin: proof.Coin,
Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash),
}
for i, p := range proof.Proof {
params.WithdrawalProof[i] = common.HexToHash(p).Bytes()
paramOne := bindings.TypesExChainWithdrawalParam{
Value: proof.Value,
User: proof.User,
Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash),
}
ooProof := bindings.TypesOutputRootProof{
StateRoot: proof.Output.StateRoot,
MessagePasserStorageRoot: proof.Output.MessagePasserStorageRoot,
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 {
l.Log.Error("failed to do withdrawal", "err", err)
return
......@@ -361,23 +374,34 @@ func (l *Operator) DoOperator(ctx context.Context) {
l.Log.Error("failed to get withdrawal proof", "err", err)
break
} else {
withdrawalProof := make([][]byte, len(proof.Proof))
for i, p := range proof.Proof {
withdrawalProof[i] = common.FromHex(p)
}
// call contract to do withdrawal.
params := bindings.TypesBatchExChainWithdrawalParam{
WithdrawalProof: make([][]byte, len(proof.Proof)),
WithdrawalProof: withdrawalProof,
Value: proof.Value,
User: proof.User,
Coin: proof.Coin,
Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash),
}
for i, p := range proof.Proof {
params.WithdrawalProof[i] = common.HexToHash(p).Bytes()
paramOne := bindings.TypesExChainWithdrawalParam{
Value: proof.Value,
User: proof.User,
Coin: []byte(proof.Coin),
TxHash: common.HexToHash(tx.TxHash),
}
ooProof := bindings.TypesOutputRootProof{
StateRoot: proof.Output.StateRoot,
MessagePasserStorageRoot: proof.Output.MessagePasserStorageRoot,
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 {
l.Log.Error("failed to do withdrawal", "err", err)
return
......@@ -399,6 +423,10 @@ func (l *Operator) BatchExChainWithdrawalTxData(params []bindings.TypesBatchExCh
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.
func (l *Operator) sendTransaction(ctx context.Context, params []bindings.TypesBatchExChainWithdrawalParam, l2OutputIndex *big.Int, outputRootProof bindings.TypesOutputRootProof) error {
l.Log.Info("DoWithdrawal", "l2OutputIndex", l2OutputIndex)
......@@ -408,10 +436,40 @@ func (l *Operator) sendTransaction(ctx context.Context, params []bindings.TypesB
if err != nil {
return err
}
//l.Log.Info("BatchExChainWithdrawalTxData", "data", hex.EncodeToString(data))
receipt, err = l.Txmgr.Send(ctx, txmgr.TxCandidate{
TxData: data,
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 {
return err
......@@ -470,7 +528,7 @@ func (l *Operator) waitNodeSync() error {
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)
defer cancel()
......@@ -481,3 +539,15 @@ func (l *Operator) doWithdrawal(ctx context.Context, params []bindings.TypesBatc
}
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 {
Proof []string
Value *big.Int
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