Skip to content
This repository has been archived by the owner on Oct 7, 2020. It is now read-only.

Allow networkId as a parameter #324

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ dist/
scripts/kubernetes/ethermint.yaml
ethstats/
coverage.txt
tests/integration/truffle/build
ethstats/
coverage.txt
tests/tendermint_data/**/*.bak
tests/tendermint_data/**/*.toml

### Go ###
# Binaries for programs and plugins
Expand Down
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ os:

install: make get_vendor_deps

script: make test_coverage
script: make test_coverage # && make metalinter (enable when CI can handle the memory)

after_success:
- bash <(curl -s https://codecov.io/bash)
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@
* add readthedocs to the docs folder
* update to go-ethereum 1.6.7
* update dependencies
* add unsafe reset command to easily reset all the initialisation files
* run integration tests on CI
* add build targets for OSX
* add `--with-tendermint` flag to start tendermint in process
* tendermint needs to be installed as a binary
* tendermint core is not pulled in as a dependency
* rework the docs
* no networking is started by the ethereum node
* performance optimisation
* doc updates
* block state in calls for checkTx
* allows multiple transactions from the same account

## 0.4.0
### Breaking
Expand Down
4 changes: 4 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# CODEOWNERS: https://help.github.com/articles/about-codeowners/

# Everything goes through Adrian. For now.
* @adrianbrink
11 changes: 5 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
GOTOOLS = \
github.com/karalabe/xgo \
github.com/Masterminds/glide \
honnef.co/go/tools/cmd/megacheck \
github.com/alecthomas/gometalinter
PACKAGES=$(shell go list ./... | grep -v '/vendor/')
BUILD_TAGS?=ethermint
Expand Down Expand Up @@ -66,12 +65,12 @@ test_race:
@echo "--> Running go test --race"
@go test -race $(PACKAGES)

megacheck: ensure_tools
@for pkg in ${PACKAGES}; do megacheck "$$pkg"; done
test_integrations:
@bash ./tests/test.sh

metalinter: ensure_tools
metalinter: ensure_tools install
@gometalinter --install
gometalinter --vendor --deadline=600s --enable-all --disable=lll ./...
gometalinter --vendor --disable-all --enable=unused ./...

draw_deps:
# requires brew install graphviz or apt-get install graphviz
Expand Down Expand Up @@ -114,7 +113,7 @@ ethstats_stop:
@cd $(CURDIR)/ethstats && pm2 stop ./app.json

.PHONY: all install build build_race dist \
test test_race \
test test_racetest_integrations \
draw_deps list_deps get_deps get_vendor_deps tools ensure_tools \
docker_build docker_build_develop docker_push docker_push_develop \
ethstats_setup ethstats_run ethstats_stop
3 changes: 3 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# TODO

* Document performance numbers for Tendermint and Ethermint and write a blog post about it
87 changes: 59 additions & 28 deletions app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
ethTypes "github.com/ethereum/go-ethereum/core/types"
Expand All @@ -26,7 +25,9 @@ type EthermintApplication struct {
backend *ethereum.Backend // backend ethereum struct

// a closure to return the latest current state from the ethereum blockchain
currentState func() (*state.StateDB, error)
getCurrentState func() (*state.StateDB, error)

checkTxState *state.StateDB

// an ethereum rpc client we can forward queries to
rpcClient *rpc.Client
Expand All @@ -41,11 +42,18 @@ type EthermintApplication struct {
// #stable - 0.4.0
func NewEthermintApplication(backend *ethereum.Backend,
client *rpc.Client, strategy *emtTypes.Strategy) (*EthermintApplication, error) {

state, err := backend.Ethereum().BlockChain().State()
if err != nil {
return nil, err
}

app := &EthermintApplication{
backend: backend,
rpcClient: client,
currentState: backend.Ethereum().BlockChain().State,
strategy: strategy,
backend: backend,
rpcClient: client,
getCurrentState: backend.Ethereum().BlockChain().State,
checkTxState: state.Copy(),
strategy: strategy,
}

if err := app.backend.ResetWork(app.Receiver()); err != nil {
Expand All @@ -63,6 +71,9 @@ func (app *EthermintApplication) SetLogger(log tmLog.Logger) {

var bigZero = big.NewInt(0)

// maxTransactionSize is 32KB in order to prevent DOS attacks
const maxTransactionSize = 32768

// Info returns information about the last height and app_hash to the tendermint engine
// #stable - 0.4.0
func (app *EthermintApplication) Info() abciTypes.ResponseInfo {
Expand Down Expand Up @@ -109,11 +120,11 @@ func (app *EthermintApplication) InitChain(validators []*abciTypes.Validator) {
// #stable - 0.4.0
func (app *EthermintApplication) CheckTx(txBytes []byte) abciTypes.Result {
tx, err := decodeTx(txBytes)
app.logger.Debug("CheckTx: Received valid transaction", "tx", tx) // nolint: errcheck
if err != nil {
app.logger.Debug("CheckTx: Received invalid transaction", "tx", tx) // nolint: errcheck
return abciTypes.ErrEncodingError.AppendLog(err.Error())
}
app.logger.Debug("CheckTx: Received valid transaction", "tx", tx) // nolint: errcheck

return app.validateTx(tx)
}
Expand Down Expand Up @@ -164,6 +175,13 @@ func (app *EthermintApplication) Commit() abciTypes.Result {
app.logger.Error("Error getting latest ethereum state", "err", err) // nolint: errcheck
return abciTypes.ErrInternalError.AppendLog(err.Error())
}
state, err := app.getCurrentState()
if err != nil {
app.logger.Error("Error getting latest state", "err", err) // nolint: errcheck
return abciTypes.ErrInternalError.AppendLog(err.Error())
}

app.checkTxState = state.Copy()
return abciTypes.NewResultOK(blockHash[:], "")
}

Expand Down Expand Up @@ -191,48 +209,52 @@ func (app *EthermintApplication) Query(query abciTypes.RequestQuery) abciTypes.R
// validateTx checks the validity of a tx against the blockchain's current state.
// it duplicates the logic in ethereum's tx_pool
func (app *EthermintApplication) validateTx(tx *ethTypes.Transaction) abciTypes.Result {
currentState, err := app.currentState()
if err != nil {
return abciTypes.ErrInternalError.AppendLog(err.Error())

// Heuristic limit, reject transactions over 32KB to prevent DOS attacks
if tx.Size() > maxTransactionSize {
return abciTypes.ErrInternalError.
AppendLog(core.ErrOversizedData.Error())
}

var signer ethTypes.Signer = ethTypes.FrontierSigner{}
if tx.Protected() {
signer = ethTypes.NewEIP155Signer(tx.ChainId())
}

// Make sure the transaction is signed properly
from, err := ethTypes.Sender(signer, tx)
if err != nil {
return abciTypes.ErrBaseInvalidSignature.
AppendLog(core.ErrInvalidSender.Error())
}

// Make sure the account exist. Non existent accounts
// haven't got funds and well therefor never pass.
// Transactions can't be negative. This may never happen using RLP decoded
// transactions but may occur if you create a transaction using the RPC.
if tx.Value().Sign() < 0 {
return abciTypes.ErrBaseInvalidInput.
AppendLog(core.ErrNegativeValue.Error())
}

currentState := app.checkTxState

// Make sure the account exist - cant send from non-existing account.
if !currentState.Exist(from) {
return abciTypes.ErrBaseUnknownAddress.
AppendLog(core.ErrInvalidSender.Error())
}

// Check for nonce errors
currentNonce := currentState.GetNonce(from)
if currentNonce > tx.Nonce() {
return abciTypes.ErrBadNonce.
AppendLog(fmt.Sprintf("Got: %d, Current: %d", tx.Nonce(), currentNonce))
}

// Check the transaction doesn't exceed the current block limit gas.
gasLimit := app.backend.GasLimit()
if gasLimit.Cmp(tx.Gas()) < 0 {
return abciTypes.ErrInternalError.AppendLog(core.ErrGasLimitReached.Error())
return abciTypes.ErrInternalError.
AppendLog(core.ErrGasLimitReached.Error())
}

// Transactions can't be negative. This may never happen
// using RLP decoded transactions but may occur if you create
// a transaction using the RPC for example.
if tx.Value().Cmp(common.Big0) < 0 {
return abciTypes.ErrBaseInvalidInput.
SetLog(core.ErrNegativeValue.Error())
// Check if nonce is not strictly increasing
nonce := currentState.GetNonce(from)
if nonce != tx.Nonce() {
return abciTypes.ErrBadNonce.
AppendLog(fmt.Sprintf("Nonce is not strictly increasing. Expected: %d; Got: %d", nonce, tx.Nonce()))
}

// Transactor should have enough funds to cover the costs
Expand All @@ -241,14 +263,23 @@ func (app *EthermintApplication) validateTx(tx *ethTypes.Transaction) abciTypes.
if currentBalance.Cmp(tx.Cost()) < 0 {
return abciTypes.ErrInsufficientFunds.
AppendLog(fmt.Sprintf("Current balance: %s, tx cost: %s", currentBalance, tx.Cost()))

}

intrGas := core.IntrinsicGas(tx.Data(), tx.To() == nil, true) // homestead == true
if tx.Gas().Cmp(intrGas) < 0 {
return abciTypes.ErrBaseInsufficientFees.
SetLog(core.ErrIntrinsicGas.Error())
AppendLog(core.ErrIntrinsicGas.Error())
}

// Update ether balances
// amount + gasprice * gaslimit
currentState.SubBalance(from, tx.Cost())
// tx.To() returns a pointer to a common address. It returns nil
// if it is a contract creation transaction.
if to := tx.To(); to != nil {
currentState.AddBalance(*to, tx.Value())
}
currentState.SetNonce(from, tx.Nonce()+1)

return abciTypes.OK
}
Loading