Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Remix debugging of EVM call #1496

Closed
wants to merge 54 commits into from
Closed
Show file tree
Hide file tree
Changes from 53 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
9bdb94b
wip move middleware to seperate package
Sriep Sep 23, 2019
414db24
implement
Sriep Sep 24, 2019
2b94ec3
wip implement
Sriep Sep 24, 2019
00743d8
implement
Sriep Sep 24, 2019
239fb4b
use ethapi go-ethereum branch
Sriep Sep 25, 2019
04dd303
use config transfer gateway branch
Sriep Sep 25, 2019
79536ea
touch
Sriep Sep 25, 2019
6002221
touch
Sriep Sep 25, 2019
c7af3a8
add version reader
Sriep Sep 25, 2019
343e039
wip use correct chain id
Sriep Sep 27, 2019
af517e5
Merge remote-tracking branch 'remotes/origin/appstate' into debug-evm
Sriep Sep 27, 2019
3d71a4f
move nocetxhandler into loom.go
Sriep Sep 27, 2019
7665fdf
evm debug
Sriep Sep 30, 2019
96b74f6
move tx_handler
Sriep Sep 30, 2019
0e3986c
Merge remote-tracking branch 'remotes/origin/appstate' into debug-evm
Sriep Oct 10, 2019
63368c5
merge master changes
Sriep Oct 10, 2019
91f266f
newMultiWriterVersionReader, unit test
Sriep Oct 14, 2019
9bda227
Merge remote-tracking branch 'remotes/origin/appstate' into debug-evm
Sriep Oct 18, 2019
1c59869
merge-wip
Sriep Oct 21, 2019
fbcfa43
merge-wip
Sriep Oct 21, 2019
7489a31
merge-wip
Sriep Oct 21, 2019
cf0ced2
Add version paramter to GetSnapshot
Sriep Oct 21, 2019
048040c
Modify stores
Sriep Oct 22, 2019
f7682fe
wip
Sriep Oct 22, 2019
d9664f1
merge iAVLVersionReader into iavlStoreSnapshot
Sriep Oct 23, 2019
0053ff4
versionedCachingStore
Sriep Oct 23, 2019
23746d5
PruningIAVLStore
Sriep Oct 23, 2019
c3c0ee4
PruningIAVLStore
Sriep Oct 25, 2019
e7d01f8
PruningIAVLStore
Sriep Oct 30, 2019
cff6ba6
reiview issues store changes
Sriep Oct 30, 2019
f2323ae
use loomchain.Application
Sriep Oct 30, 2019
3f0d006
loomchain.Application
Sriep Oct 30, 2019
39d948d
Add valiadtor functions, fix range
Sriep Oct 31, 2019
5de9514
fx deploy fixes
Sriep Oct 31, 2019
de3313f
fix version number
Sriep Oct 31, 2019
9c3daa1
copy factory, truffle test
Sriep Oct 31, 2019
ba19cf4
revert
Sriep Oct 31, 2019
323fa14
unit test fixes
Sriep Oct 31, 2019
8f3a7ad
unit test fixes
Sriep Nov 1, 2019
ce35dd1
test jenkins
Sriep Nov 1, 2019
5e10bd1
test jenkins
Sriep Nov 1, 2019
882ee71
Merge remote-tracking branch 'remotes/origin/appstate' into debug-evm
Sriep Nov 4, 2019
37838df
merge in master changes
Sriep Nov 4, 2019
66aaf08
makefile
Sriep Nov 4, 2019
48e3738
touch
Sriep Nov 4, 2019
fdfcb2f
Merge remote-tracking branch 'remotes/origin/appstate' into debug-evm
Sriep Nov 4, 2019
4203aaf
touch
Sriep Nov 4, 2019
fff1634
touch
Sriep Nov 4, 2019
3b8d97e
touch
Sriep Nov 4, 2019
9d2b808
touch
Sriep Nov 4, 2019
6d95f13
lint fix
Sriep Nov 4, 2019
6cf49dd
lint fixes
Sriep Nov 4, 2019
4b609de
touch
Sriep Nov 6, 2019
a1d93af
range fix
Sriep Nov 7, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ BINANCE_TGORACLE_DIR=$(GOPATH)/src/$(PKG_BINANCE_TGORACLE)
# specific commit.
GO_LOOM_GIT_REV = HEAD
# Specifies the loomnetwork/transfer-gateway branch/revision to use.
TG_GIT_REV = HEAD
TG_GIT_REV = config
# loomnetwork/go-ethereum loomchain branch
ETHEREUM_GIT_REV = 1fb6138d017a4309105d91f187c126cf979c93f9
ETHEREUM_GIT_REV = ethapi
# use go-plugin we get 'timeout waiting for connection info' error
HASHICORP_GIT_REV = f4c3476bd38585f9ec669d10ed1686abd52b9961
LEVIGO_GIT_REV = c42d9e0ca023e2198120196f842701bb4c55d7b9
Expand Down
165 changes: 107 additions & 58 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,44 +7,29 @@ import (
"fmt"
"time"

"github.com/loomnetwork/loomchain/eth/utils"
"github.com/loomnetwork/loomchain/features"
"github.com/loomnetwork/loomchain/registry"

"github.com/ethereum/go-ethereum/core/vm"
"github.com/go-kit/kit/metrics"
kitprometheus "github.com/go-kit/kit/metrics/prometheus"
cctypes "github.com/loomnetwork/go-loom/builtin/types/chainconfig"
"github.com/pkg/errors"

// "github.com/pkg/errors"
stdprometheus "github.com/prometheus/client_golang/prometheus"
abci "github.com/tendermint/tendermint/abci/types"
"github.com/tendermint/tendermint/libs/common"
ttypes "github.com/tendermint/tendermint/types"

"github.com/loomnetwork/loomchain/eth/utils"
"github.com/loomnetwork/loomchain/features"
"github.com/loomnetwork/loomchain/registry"
"github.com/loomnetwork/loomchain/txhandler"

"github.com/loomnetwork/loomchain/log"
appstate "github.com/loomnetwork/loomchain/state"
"github.com/loomnetwork/loomchain/store"
blockindex "github.com/loomnetwork/loomchain/store/block_index"
evmaux "github.com/loomnetwork/loomchain/store/evm_aux"
)

type TxHandler interface {
ProcessTx(state appstate.State, txBytes []byte, isCheckTx bool) (TxHandlerResult, error)
}

type TxHandlerFunc func(state appstate.State, txBytes []byte, isCheckTx bool) (TxHandlerResult, error)

type TxHandlerResult struct {
Data []byte
ValidatorUpdates []abci.Validator
Info string
// Tags to associate with the tx that produced this result. Tags can be used to filter txs
// via the ABCI query interface (see https://godoc.org/github.com/tendermint/tendermint/libs/pubsub/query)
Tags []common.KVPair
}

func (f TxHandlerFunc) ProcessTx(state appstate.State, txBytes []byte, isCheckTx bool) (TxHandlerResult, error) {
return f(state, txBytes, isCheckTx)
}

type QueryHandler interface {
Handle(state appstate.ReadOnlyState, path string, data []byte) ([]byte, error)
}
Expand Down Expand Up @@ -73,10 +58,11 @@ type Application struct {
curBlockHash []byte
Store store.VersionedKVStore
Init func(appstate.State) error
TxHandler
txhandler.TxHandler
QueryHandler
EventHandler
ReceiptHandlerProvider
txhandler.TxHandlerFactory
EvmAuxStore *evmaux.EvmAuxStore
blockindex.BlockIndexStore
CreateValidatorManager ValidatorsManagerFactoryFunc
Expand All @@ -89,6 +75,7 @@ type Application struct {
config *cctypes.Config
childTxRefs []evmaux.ChildTxRef // links Tendermint txs to EVM txs
ReceiptsVersion int32
DebugTxHandler txhandler.TxHandler
}

var _ abci.Application = &Application{}
Expand Down Expand Up @@ -304,13 +291,16 @@ func (a *Application) EndBlock(req abci.RequestEndBlock) abci.ResponseEndBlock {

// TODO: receiptHandler.CommitBlock() should be moved to Application.Commit()
storeTx := store.WrapAtomic(a.Store).BeginTx()
receiptHandler := a.ReceiptHandlerProvider.Store()
if err := receiptHandler.CommitBlock(a.height()); err != nil {
storeTx.Rollback()
// TODO: maybe panic instead?
log.Error(fmt.Sprintf("aborted committing block receipts, %v", err.Error()))
} else {
storeTx.Commit()

Sriep marked this conversation as resolved.
Show resolved Hide resolved
if a.ReceiptHandlerProvider != nil {
receiptHandler := a.ReceiptHandlerProvider.Store()
if err := receiptHandler.CommitBlock(a.height()); err != nil {
storeTx.Rollback()
// TODO: maybe panic instead?
log.Error(fmt.Sprintf("aborted committing block receipts, %v", err.Error()))
} else {
storeTx.Commit()
}
}

storeTx = store.WrapAtomic(a.Store).BeginTx()
Expand Down Expand Up @@ -438,7 +428,7 @@ func (a *Application) deliverTx(storeTx store.KVStoreTx, txBytes []byte) abci.Re
return abci.ResponseDeliverTx{Code: abci.CodeTypeOK, Data: r.Data, Tags: r.Tags, Info: r.Info}
}

func (a *Application) processTx(storeTx store.KVStoreTx, txBytes []byte, isCheckTx bool) (TxHandlerResult, error) {
func (a *Application) processTx(storeTx store.KVStoreTx, txBytes []byte, isCheckTx bool) (txhandler.TxHandlerResult, error) {
state := appstate.NewStoreState(
context.Background(),
storeTx,
Expand Down Expand Up @@ -499,16 +489,17 @@ func (a *Application) deliverTx2(storeTx store.KVStoreTx, txBytes []byte) abci.R
a.curBlockHash,
a.GetValidatorSet,
).WithOnChainConfig(a.config)

receiptHandler := a.ReceiptHandlerProvider.Store()
defer receiptHandler.DiscardCurrentReceipt()
defer a.EventHandler.Rollback()
if a.ReceiptHandlerProvider != nil {
//receiptHandler := a.ReceiptHandlerProvider.Store()
defer a.ReceiptHandlerProvider.Store().DiscardCurrentReceipt()
defer a.EventHandler.Rollback()
}

r, txErr := a.TxHandler.ProcessTx(state, txBytes, false)

// Store the receipt even if the tx itself failed
var receiptTxHash []byte
if a.ReceiptHandlerProvider.Reader().GetCurrentReceipt() != nil {
if a.ReceiptHandlerProvider != nil && a.ReceiptHandlerProvider.Reader().GetCurrentReceipt() != nil {
receiptTxHash = a.ReceiptHandlerProvider.Reader().GetCurrentReceipt().TxHash
txHash := ttypes.Tx(txBytes).Hash()
// If a receipt was generated for an EVM tx add a link between the TM tx hash and the EVM tx hash
Expand All @@ -519,7 +510,7 @@ func (a *Application) deliverTx2(storeTx store.KVStoreTx, txBytes []byte) abci.R
ChildTxHash: receiptTxHash,
})
}
receiptHandler.CommitCurrentReceipt()
a.ReceiptHandlerProvider.Store().CommitCurrentReceipt()
}

if txErr != nil {
Expand All @@ -530,13 +521,15 @@ func (a *Application) deliverTx2(storeTx store.KVStoreTx, txBytes []byte) abci.R
return abci.ResponseDeliverTx{Code: 1, Data: r.Data, Log: txErr.Error()}
}

a.EventHandler.Commit(uint64(a.curBlockHeader.GetHeight()))
storeTx.Commit()

// FIXME: Really shouldn't be sending out events until the whole block is committed because
// the state changes from the tx won't be visible to queries until after Application.Commit()
if err := a.EventHandler.LegacyEthSubscriptionSet().EmitTxEvent(r.Data, r.Info); err != nil {
log.Error("Emit Tx Event error", "err", err)
if a.EventHandler != nil {
a.EventHandler.Commit(uint64(a.curBlockHeader.GetHeight()))
// FIXME: Really shouldn't be sending out events until the whole block is committed because
// the state changes from the tx won't be visible to queries until after Application.Commit()
if err := a.EventHandler.LegacyEthSubscriptionSet().EmitTxEvent(r.Data, r.Info); err != nil {
log.Error("Emit Tx Event error", "err", err)
}
}

if len(receiptTxHash) > 0 {
Expand All @@ -563,23 +556,28 @@ func (a *Application) Commit() abci.ResponseCommit {

height := a.curBlockHeader.GetHeight()

if err := a.EvmAuxStore.SaveChildTxRefs(a.childTxRefs); err != nil {
// TODO: consider panic instead
log.Error("Failed to save Tendermint -> EVM tx hash refs", "height", height, "err", err)
if a.EvmAuxStore != nil {
if err := a.EvmAuxStore.SaveChildTxRefs(a.childTxRefs); err != nil {
// TODO: consider panic instead
log.Error("Failed to save Tendermint -> EVM tx hash refs", "height", height, "err", err)
}
}
a.childTxRefs = nil

go func(height int64, blockHeader abci.Header) {
if err := a.EventHandler.EmitBlockTx(uint64(height), blockHeader.Time); err != nil {
log.Error("Emit Block Event error", "err", err)
}
if err := a.EventHandler.LegacyEthSubscriptionSet().EmitBlockEvent(blockHeader); err != nil {
log.Error("Emit Block Event error", "err", err)
}
if err := a.EventHandler.EthSubscriptionSet().EmitBlockEvent(blockHeader); err != nil {
log.Error("Emit Block Event error", "err", err)
}
}(height, a.curBlockHeader)
if a.EventHandler != nil {
go func(height int64, blockHeader abci.Header) {
if err := a.EventHandler.EmitBlockTx(uint64(height), blockHeader.Time); err != nil {
log.Error("Emit Block Event error", "err", err)
}
if err := a.EventHandler.LegacyEthSubscriptionSet().EmitBlockEvent(blockHeader); err != nil {
log.Error("Emit Block Event error", "err", err)
}
if err := a.EventHandler.EthSubscriptionSet().EmitBlockEvent(blockHeader); err != nil {
log.Error("Emit Block Event error", "err", err)
}
}(height, a.curBlockHeader)
}

a.lastBlockHeader = a.curBlockHeader

if err := a.Store.Prune(); err != nil {
Expand Down Expand Up @@ -611,6 +609,7 @@ func (a *Application) Query(req abci.RequestQuery) abci.ResponseQuery {
func (a *Application) height() int64 {
return a.Store.Version() + 1
}

func (a *Application) ReadOnlyState() appstate.State {
// TODO: the store snapshot should be created atomically, otherwise the block header might
// not match the state... need to figure out why this hasn't spectacularly failed already
Expand All @@ -622,3 +621,53 @@ func (a *Application) ReadOnlyState() appstate.State {
a.GetValidatorSet,
)
}

func (a *Application) ReplayApplication(blockNumber uint64, blockstore store.BlockStore) (*Application, int64, error) {
Sriep marked this conversation as resolved.
Show resolved Hide resolved
startVersion := int64(blockNumber) - 1
if startVersion < 0 {
return nil, 0, errors.Errorf("invalid block number %d", blockNumber)
}
var snapshot store.Snapshot
for err := error(nil); (snapshot == nil || err != nil) && startVersion > 0; startVersion-- {
snapshot, err = a.Store.GetSnapshotAt(startVersion)
}
if startVersion == 0 {
return nil, 0, errors.Errorf("no saved version for height %d", blockNumber)
}

splitStore := store.NewSplitStore(snapshot, store.NewMemStore(), startVersion-1)
factory := a.TxHandlerFactory.Copy(splitStore)
txHandle, err := factory.TxHandler(nil, false)
if err != nil {
return nil, 0, err
}
newApp := &Application{
Store: splitStore,
Init: func(state appstate.State) error {
panic("init should not be called")
},
TxHandler: txHandle,
TxHandlerFactory: factory,
BlockIndexStore: nil,
EventHandler: nil,
ReceiptHandlerProvider: nil,
CreateValidatorManager: a.CreateValidatorManager,
CreateChainConfigManager: a.CreateChainConfigManager,
CreateContractUpkeepHandler: a.CreateContractUpkeepHandler,
EventStore: nil,
GetValidatorSet: a.GetValidatorSet,
EvmAuxStore: nil,
ReceiptsVersion: a.ReceiptsVersion,
config: a.config,
}
return newApp, startVersion, nil
}

func (a *Application) SetTracer(tracer vm.Tracer, metrics bool) error {
newTxHandle, err := a.TxHandlerFactory.TxHandler(tracer, metrics)
if err != nil {
return errors.Wrap(err, "making transaction handle")
}
a.TxHandler = newTxHandle
return nil
}
Loading