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

Commit

Permalink
6.0.8-stable backports (#37)
Browse files Browse the repository at this point in the history
* Replace repository reference for accounts/abi/bind (#29)

* docs: update badges (#34)

* docs: add gitter badge

* docs: add circle-ci badge

* Update README.md

* Update README.md

* Update README.md

* docs: update repository path

* Update README.md

* Tx Encoding and decoding fix (#33)

* Added test for decoding old encoding function

* Fixed decoding issue and improved tests to handle all cases including previous client

* Add compatibility with previous version

* Rename receipt storage variable

* Storage and edge case fixes (#28)

* Applied storage fixes and updates

* Minor execution refactor
  • Loading branch information
soc1c authored Aug 13, 2019
1 parent b898609 commit 72c72b6
Show file tree
Hide file tree
Showing 12 changed files with 214 additions and 107 deletions.
21 changes: 10 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
# Geth Classic

[![GitHub release](https://img.shields.io/github/release-pre/eth-classic/go-ethereum.svg)](https://github.com/eth-classic/go-ethereum/releases/latest)
![GitHub All Releases](https://img.shields.io/github/downloads/eth-classic/go-ethereum/total.svg)
![LICENSE](https://img.shields.io/github/license/eth-classic/go-ethereum.svg)
[![GitHub release](https://img.shields.io/github/release-pre/etclabscore/go-ethereum.svg)](https://github.com/etclabscore/go-ethereum/releases/latest)
![GitHub All Releases](https://img.shields.io/github/downloads/etclabscore/go-ethereum/total.svg)
![LICENSE](https://img.shields.io/github/license/etclabscore/go-ethereum.svg)


[![CircleCI](https://img.shields.io/circleci/build/gh/eth-classic/go-ethereum/development.svg)](https://circleci.com/gh/eth-classic/go-ethereum/tree/development)
![GitHub last commit](https://img.shields.io/github/last-commit/eth-classic/go-ethereum.svg)
[![Join the chat at https://gitter.im/eth-classic/go-ethereum](https://badges.gitter.im/eth-classic/go-ethereum.svg)](https://gitter.im/eth-classic/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![CircleCI](https://img.shields.io/circleci/build/gh/etclabscore/go-ethereum/development.svg)](https://circleci.com/gh/etclabscore/go-ethereum/tree/development)
![GitHub last commit](https://img.shields.io/github/last-commit/etclabscore/go-ethereum.svg)
[![Join the chat at https://gitter.im/etclabscore/go-ethereum](https://badges.gitter.im/etclabscore/go-ethereum.svg)](https://gitter.im/etclabscore/go-ethereum?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

Official Go-language implementation of the Ethereum Classic protocol. Ethereum Classic (ETC) offers a censorship-resistant and powerful application platform for developers in parallel to the Ethereum Foundation network (ETH), while differentially rejecting the DAO transition.

## Install Geth Classic

### :gift: Official Releases
Regular releases will be published on the [release page](https://github.com/eth-classic/go-ethereum/releases). Binaries will be provided for all releases that are considered fairly stable.
Regular releases will be published on the [release page](https://github.com/etclabscore/go-ethereum/releases). Binaries will be provided for all releases that are considered fairly stable.

### :hammer: Building the source
If your heart is set on the bleeding edge, install from source. However, please be advised that you may encounter some strange things, and we can't prioritize support beyond the release versions. Recommended for developers only.
Expand All @@ -28,7 +27,7 @@ With [Go modules](https://github.com/golang/go/wiki/Modules), dependencies will
Clone the repository:

```
git clone https://github.com/eth-classic/go-ethereum.git getc && cd getc
git clone https://github.com/etclabscore/go-ethereum.git getc && cd getc
```

Build all executables:
Expand Down Expand Up @@ -79,7 +78,7 @@ This repository includes several wrappers/executables found in the `cmd` directo
| `bootnode` | Stripped down version of our Ethereum client implementation that only takes part in the network node discovery protocol, but does not run any of the higher level application protocols. It can be used as a lightweight bootstrap node to aid in finding peers in private networks. |
| `disasm` | Bytecode disassembler to convert EVM (Ethereum Virtual Machine) bytecode into more user friendly assembly-like opcodes (e.g. `echo "6001" | disasm`). For details on the individual opcodes, please see pages 22-30 of the [Ethereum Yellow Paper](http://gavwood.com/paper.pdf). |
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow insolated, fine graned debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug`). |
| `gethrpctest` | Developer utility tool to support our [ethereum/rpc-test](https://github.com/eth-classic/rpc-tests) test suite which validates baseline conformity to the [Ethereum JSON RPC](https://github.com/ethereumproject/wiki/wiki/JSON-RPC) specs. Please see the [test suite's readme](https://github.com/eth-classic/rpc-tests/blob/master/README.md) for details. |
| `gethrpctest` | Developer utility tool to support our [ethereum/rpc-test](https://github.com/etclabscore/rpc-tests) test suite which validates baseline conformity to the [Ethereum JSON RPC](https://github.com/ethereumproject/wiki/wiki/JSON-RPC) specs. Please see the [test suite's readme](https://github.com/etclabscore/rpc-tests/blob/master/README.md) for details. |
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://github.com/ethereumproject/wiki/wiki/RLP)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |

## :green_book: Getting started with Geth Classic
Expand Down Expand Up @@ -207,7 +206,7 @@ You'll need to use your own programming environments' capabilities (libraries, t
> Note: Please understand the security implications of opening up an HTTP/WS based transport before doing so! Hackers on the internet are actively trying to subvert Ethereum nodes with exposed APIs! Further, all browser tabs can access locally running webservers, so malicious webpages could try to subvert locally available APIs!*
### Operating a private/custom network
As of [Geth 3.4](https://github.com/eth-classic/go-ethereum/releases) you are now able to configure a private chain by specifying an __external chain configuration__ JSON file, which includes necessary genesis block data as well as feature configurations for protocol forks, bootnodes, and chainID.
As of [Geth 3.4](https://github.com/etclabscore/go-ethereum/releases) you are now able to configure a private chain by specifying an __external chain configuration__ JSON file, which includes necessary genesis block data as well as feature configurations for protocol forks, bootnodes, and chainID.

Please find full [example external configuration files representing the Mainnet and Morden Testnet specs in the /config subdirectory of this repo](). You can use either of these files as a starting point for your own customizations.

Expand Down
106 changes: 106 additions & 0 deletions core/database_util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,112 @@ func TestReceiptStorage(t *testing.T) {
}
}

func TestReceiptStorageEncoding(t *testing.T) {
var w bytes.Buffer
r := &types.ReceiptForStorage{
PostState: []byte{0x01, 0x02},
Status: types.TxSuccess,
CumulativeGasUsed: big.NewInt(1),
Logs: vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte{0x11})},
&vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})},
},
TxHash: common.BytesToHash([]byte{0x12, 0x11}),
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
GasUsed: big.NewInt(111111),
}

r.EncodeRLP(&w)

var encodedReceipt types.ReceiptForStorage
stream := rlp.NewStream(bytes.NewReader(w.Bytes()), 0)
encodedReceipt.DecodeRLP(stream)

if bytes.Compare(encodedReceipt.PostState, r.PostState) != 0 {
t.Errorf("Old storage receipt PostState: have (%v) want (%v)", encodedReceipt.PostState, r.PostState)
}
if encodedReceipt.Status != r.Status {
t.Errorf("Old storage receipt status: have (%v) want (%v)", encodedReceipt.Status, r.Status)
}
if encodedReceipt.CumulativeGasUsed.Cmp(r.CumulativeGasUsed) != 0 {
t.Errorf("Old storage receipt CumulativeGasUsed: have (%v) want (%v)", encodedReceipt.CumulativeGasUsed, r.CumulativeGasUsed)
}
if encodedReceipt.TxHash != r.TxHash {
t.Errorf("Old storage receipt TxHash: have (%v) want (%v)", encodedReceipt.TxHash, r.TxHash)
}
if encodedReceipt.ContractAddress != r.ContractAddress {
t.Errorf("Old storage receipt ContractAddress: have (%v) want (%v)", encodedReceipt.ContractAddress, r.ContractAddress)
}
if encodedReceipt.GasUsed.Cmp(r.GasUsed) != 0 {
t.Errorf("Old storage receipt GasUsed: have (%v) want (%v)", encodedReceipt.GasUsed, r.GasUsed)
}
for i, log := range r.Logs {
if bytes.Compare(r.Logs[i].Data, log.Data) != 0 {
t.Errorf("Old storage receipt Log: have (%v) want (%v)", log.Data, r.Logs[i].Data)
}
}
}

func TestOldReceiptStorageTransition(t *testing.T) {
var w bytes.Buffer
r := &types.Receipt{
PostState: []byte{0x24, 0x12},
Status: types.TxSuccess,
CumulativeGasUsed: big.NewInt(1),
Logs: vm.Logs{
&vm.Log{Address: common.BytesToAddress([]byte{0x11})},
&vm.Log{Address: common.BytesToAddress([]byte{0x01, 0x11})},
},
TxHash: common.BytesToHash([]byte{0x11, 0x11}),
ContractAddress: common.BytesToAddress([]byte{0x01, 0x11, 0x11}),
GasUsed: big.NewInt(111111),
}

logs := make([]*vm.LogForStorage, len(r.Logs))
for i, log := range r.Logs {
logs[i] = (*vm.LogForStorage)(log)
}

rlp.Encode(&w, []interface{}{
r.PostState,
r.CumulativeGasUsed,
r.Bloom,
r.TxHash,
r.ContractAddress,
logs,
r.GasUsed,
r.Status,
})

var encodedReceipt types.ReceiptForStorage
stream := rlp.NewStream(bytes.NewReader(w.Bytes()), 0)
encodedReceipt.DecodeRLP(stream)

if bytes.Compare(encodedReceipt.PostState, r.PostState) != 0 {
t.Errorf("Old storage receipt PostState: have (%v) want (%v)", encodedReceipt.PostState, r.PostState)
}
if encodedReceipt.Status != r.Status {
t.Errorf("Old storage receipt status: have (%v) want (%v)", encodedReceipt.Status, r.Status)
}
if encodedReceipt.CumulativeGasUsed.Cmp(r.CumulativeGasUsed) != 0 {
t.Errorf("Old storage receipt CumulativeGasUsed: have (%v) want (%v)", encodedReceipt.CumulativeGasUsed, r.CumulativeGasUsed)
}
if encodedReceipt.TxHash != r.TxHash {
t.Errorf("Old storage receipt TxHash: have (%v) want (%v)", encodedReceipt.TxHash, r.TxHash)
}
if encodedReceipt.ContractAddress != r.ContractAddress {
t.Errorf("Old storage receipt ContractAddress: have (%v) want (%v)", encodedReceipt.ContractAddress, r.ContractAddress)
}
if encodedReceipt.GasUsed.Cmp(r.GasUsed) != 0 {
t.Errorf("Old storage receipt GasUsed: have (%v) want (%v)", encodedReceipt.GasUsed, r.GasUsed)
}
for i, log := range r.Logs {
if bytes.Compare(r.Logs[i].Data, log.Data) != 0 {
t.Errorf("Old storage receipt Log: have (%v) want (%v)", log.Data, r.Logs[i].Data)
}
}
}

// Tests that receipts associated with a single block can be stored and retrieved.
func TestBlockReceiptStorage(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
Expand Down
34 changes: 10 additions & 24 deletions core/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ var (
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)
Expand Down Expand Up @@ -86,7 +85,7 @@ func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input
defer contract.Finalise()

// Even if the account has no code, we need to continue because it might be a precompile
ret, err = evm.Run(contract, input, false)
ret, err = env.Vm().Run(contract, input, false)

// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
Expand All @@ -102,7 +101,6 @@ func Call(env vm.Environment, caller vm.ContractRef, addr common.Address, input

// CallCode executes the given address' code as the given contract address
func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice, value *big.Int) (ret []byte, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)
Expand All @@ -127,7 +125,7 @@ func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, in
defer contract.Finalise()

// Even if the account has no code, we need to continue because it might be a precompile
ret, err = evm.Run(contract, input, false)
ret, err = env.Vm().Run(contract, input, false)

if err != nil {
env.RevertToSnapshot(snapshot)
Expand All @@ -140,7 +138,6 @@ func CallCode(env vm.Environment, caller vm.ContractRef, addr common.Address, in

// DelegateCall is equivalent to CallCode except that sender and value propagates from parent scope to child scope
func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice *big.Int) (ret []byte, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)
Expand All @@ -165,7 +162,7 @@ func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address
defer contract.Finalise()

// Even if the account has no code, we need to continue because it might be a precompile
ret, err = evm.Run(contract, input, false)
ret, err = env.Vm().Run(contract, input, false)

// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
Expand All @@ -181,7 +178,6 @@ func DelegateCall(env vm.Environment, caller vm.ContractRef, addr common.Address

// StaticCall executes within the given contract and throws exception if state is attempted to be changed
func StaticCall(env vm.Environment, caller vm.ContractRef, addr common.Address, input []byte, gas, gasPrice *big.Int) (ret []byte, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)
Expand Down Expand Up @@ -211,7 +207,7 @@ func StaticCall(env vm.Environment, caller vm.ContractRef, addr common.Address,
env.Db().AddBalance(addr, big.NewInt(0))

// Even if the account has no code, we need to continue because it might be a precompile
ret, err = evm.Run(contract, input, true)
ret, err = env.Vm().Run(contract, input, true)

// When an error was returned by the EVM or when setting the creation code
// above we revert to the snapshot and consume any gas remaining. Additionally
Expand All @@ -227,20 +223,6 @@ func StaticCall(env vm.Environment, caller vm.ContractRef, addr common.Address,

// Create creates a new contract with the given code
func Create(env vm.Environment, caller vm.ContractRef, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
ret, address, err = create(env, caller, crypto.Keccak256Hash(code), code, gas, gasPrice, value)
// Here we get an error if we run into maximum stack depth,
// See: https://github.com/ethereum/yellowpaper/pull/131
// and YP definitions for CREATE

//if there's an error we return nothing
if err != nil && err != vm.ErrRevert {
return nil, address, err
}
return ret, address, err
}

func create(env vm.Environment, caller vm.ContractRef, codeHash common.Hash, code []byte, gas, gasPrice, value *big.Int) (ret []byte, address common.Address, err error) {
evm := env.Vm()
// Depth check execution. Fail if we're trying to execute above the limit.
if env.Depth() > callCreateDepthMax {
caller.ReturnGas(gas, gasPrice)
Expand Down Expand Up @@ -281,10 +263,10 @@ func create(env vm.Environment, caller vm.ContractRef, codeHash common.Hash, cod
// EVM. The contract is a scoped environment for this execution context
// only.
contract := vm.NewContract(caller, to, value, gas, gasPrice)
contract.SetCallCode(nil, codeHash, code)
contract.SetCallCode(nil, crypto.Keccak256Hash(code), code)
defer contract.Finalise()

ret, err = evm.Run(contract, nil, false)
ret, err = env.Vm().Run(contract, nil, false)

maxCodeSizeExceeded := len(ret) > maxCodeSize && env.RuleSet().IsAtlantis(env.BlockNumber())
// if the contract creation ran successfully and no errors were returned
Expand Down Expand Up @@ -317,6 +299,10 @@ func create(env vm.Environment, caller vm.ContractRef, codeHash common.Hash, cod
err = errMaxCodeSizeExceeded
}

//if there's an error we return nothing
if err != nil && err != vm.ErrRevert {
return nil, address, err
}
return ret, address, err
}

Expand Down
29 changes: 19 additions & 10 deletions core/state/state_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -386,18 +386,27 @@ func (self *StateObject) Value() *big.Int {
panic("Value on StateObject should never be called")
}

func (self *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) {
// When iterating over the storage check the cache first
for h, value := range self.cachedStorage {
cb(h, value)
}

it := trie.NewIterator(self.getTrie(self.db.db).NodeIterator(nil))
func (s *StateObject) ForEachStorage(cb func(key, value common.Hash) bool) error {
it := trie.NewIterator(s.getTrie(s.db.db).NodeIterator(nil))
for it.Next() {
// ignore cached values
key := common.BytesToHash(self.trie.GetKey(it.Key))
if _, ok := self.cachedStorage[key]; !ok {
cb(key, common.BytesToHash(it.Value))
key := common.BytesToHash(s.trie.GetKey(it.Key))
if value, dirty := s.dirtyStorage[key]; dirty {
if cb(key, value) {
return nil
}
continue
}

if len(it.Value) > 0 {
_, content, _, err := rlp.Split(it.Value)
if err != nil {
return err
}
if !cb(key, common.BytesToHash(content)) {
return nil
}
}
}
return nil
}
Loading

0 comments on commit 72c72b6

Please sign in to comment.