2016-10-31 04:46:40 -07:00
|
|
|
package core
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/big"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/ethereum/go-ethereum/core/state"
|
|
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb"
|
2017-10-31 15:24:11 -07:00
|
|
|
"github.com/ethereum/go-ethereum/params"
|
2016-10-31 04:46:40 -07:00
|
|
|
)
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
var dualStateTestHeader = types.Header{
|
|
|
|
Number: new(big.Int),
|
|
|
|
Time: new(big.Int).SetUint64(43),
|
|
|
|
Difficulty: new(big.Int).SetUint64(1000488),
|
2018-05-31 21:23:38 -07:00
|
|
|
GasLimit: 4700000,
|
2017-10-31 15:24:11 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//[1] PUSH1 0x01 (out size)
|
|
|
|
//[3] PUSH1 0x00 (out offset)
|
|
|
|
//[5] PUSH1 0x00 (in size)
|
|
|
|
//[7] PUSH1 0x00 (in offset)
|
|
|
|
//[9] PUSH1 0x00 (value)
|
|
|
|
//[30] PUSH20 0x0200000000000000000000000000000000000000 (to)
|
|
|
|
//[34] PUSH3 0x0186a0 (gas)
|
|
|
|
//[35] CALL
|
|
|
|
//[37] PUSH1 0x00
|
|
|
|
//[38] MLOAD
|
|
|
|
//[40] PUSH1 0x00
|
|
|
|
//[41] SSTORE
|
|
|
|
//[42] STOP
|
|
|
|
|
2016-10-31 04:46:40 -07:00
|
|
|
func TestDualStatePrivateToPublicCall(t *testing.T) {
|
|
|
|
callAddr := common.Address{1}
|
|
|
|
|
2018-05-31 21:23:38 -07:00
|
|
|
db := ethdb.NewMemDatabase()
|
2017-10-31 15:24:11 -07:00
|
|
|
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
2016-10-31 04:46:40 -07:00
|
|
|
publicState.SetCode(common.Address{2}, common.Hex2Bytes("600a6000526001601ff300"))
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
2016-10-31 04:46:40 -07:00
|
|
|
privateState.SetCode(callAddr, common.Hex2Bytes("60016000600060006000730200000000000000000000000000000000000000620186a0f160005160005500"))
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
author := common.Address{}
|
2016-10-31 04:46:40 -07:00
|
|
|
msg := callmsg{
|
2017-10-31 15:24:11 -07:00
|
|
|
addr: author,
|
2016-10-31 04:46:40 -07:00
|
|
|
to: &callAddr,
|
|
|
|
value: big.NewInt(1),
|
2018-05-31 21:23:38 -07:00
|
|
|
gas: 1000000,
|
2016-10-31 04:46:40 -07:00
|
|
|
gasPrice: new(big.Int),
|
|
|
|
data: nil,
|
|
|
|
}
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
ctx := NewEVMContext(msg, &dualStateTestHeader, nil, &author)
|
|
|
|
env := vm.NewEVM(ctx, publicState, privateState, ¶ms.ChainConfig{}, vm.Config{})
|
2018-05-31 21:23:38 -07:00
|
|
|
env.Call(vm.AccountRef(author), callAddr, msg.data, msg.gas, new(big.Int))
|
2016-10-31 04:46:40 -07:00
|
|
|
|
|
|
|
if value := privateState.GetState(callAddr, common.Hash{}); value != (common.Hash{10}) {
|
|
|
|
t.Errorf("expected 10 got %x", value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDualStatePublicToPrivateCall(t *testing.T) {
|
|
|
|
callAddr := common.Address{1}
|
|
|
|
|
2018-05-31 21:23:38 -07:00
|
|
|
db := ethdb.NewMemDatabase()
|
2017-10-31 15:24:11 -07:00
|
|
|
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
2016-10-31 04:46:40 -07:00
|
|
|
privateState.SetCode(common.Address{2}, common.Hex2Bytes("600a6000526001601ff300"))
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
2016-10-31 04:46:40 -07:00
|
|
|
publicState.SetCode(callAddr, common.Hex2Bytes("60016000600060006000730200000000000000000000000000000000000000620186a0f160005160005500"))
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
author := common.Address{}
|
2016-10-31 04:46:40 -07:00
|
|
|
msg := callmsg{
|
2017-10-31 15:24:11 -07:00
|
|
|
addr: author,
|
2016-10-31 04:46:40 -07:00
|
|
|
to: &callAddr,
|
|
|
|
value: big.NewInt(1),
|
2018-05-31 21:23:38 -07:00
|
|
|
gas: 1000000,
|
2016-10-31 04:46:40 -07:00
|
|
|
gasPrice: new(big.Int),
|
|
|
|
data: nil,
|
|
|
|
}
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
ctx := NewEVMContext(msg, &dualStateTestHeader, nil, &author)
|
|
|
|
env := vm.NewEVM(ctx, publicState, publicState, ¶ms.ChainConfig{}, vm.Config{})
|
2018-05-31 21:23:38 -07:00
|
|
|
env.Call(vm.AccountRef(author), callAddr, msg.data, msg.gas, new(big.Int))
|
2016-10-31 04:46:40 -07:00
|
|
|
|
|
|
|
if value := publicState.GetState(callAddr, common.Hash{}); value != (common.Hash{}) {
|
|
|
|
t.Errorf("expected 0 got %x", value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDualStateReadOnly(t *testing.T) {
|
|
|
|
callAddr := common.Address{1}
|
|
|
|
|
2018-05-31 21:23:38 -07:00
|
|
|
db := ethdb.NewMemDatabase()
|
2017-10-31 15:24:11 -07:00
|
|
|
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
2016-10-31 04:46:40 -07:00
|
|
|
publicState.SetCode(common.Address{2}, common.Hex2Bytes("600a60005500"))
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
2016-10-31 04:46:40 -07:00
|
|
|
privateState.SetCode(callAddr, common.Hex2Bytes("60016000600060006000730200000000000000000000000000000000000000620186a0f160005160005500"))
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
author := common.Address{}
|
2016-10-31 04:46:40 -07:00
|
|
|
msg := callmsg{
|
2017-10-31 15:24:11 -07:00
|
|
|
addr: author,
|
2016-10-31 04:46:40 -07:00
|
|
|
to: &callAddr,
|
|
|
|
value: big.NewInt(1),
|
2018-05-31 21:23:38 -07:00
|
|
|
gas: 1000000,
|
2016-10-31 04:46:40 -07:00
|
|
|
gasPrice: new(big.Int),
|
|
|
|
data: nil,
|
|
|
|
}
|
|
|
|
|
2017-10-31 15:24:11 -07:00
|
|
|
ctx := NewEVMContext(msg, &dualStateTestHeader, nil, &author)
|
|
|
|
env := vm.NewEVM(ctx, publicState, privateState, ¶ms.ChainConfig{}, vm.Config{})
|
2018-05-31 21:23:38 -07:00
|
|
|
env.Call(vm.AccountRef(author), callAddr, msg.data, msg.gas, new(big.Int))
|
2016-10-31 04:46:40 -07:00
|
|
|
|
|
|
|
if value := publicState.GetState(common.Address{2}, common.Hash{}); value != (common.Hash{0}) {
|
|
|
|
t.Errorf("expected 0 got %x", value)
|
|
|
|
}
|
|
|
|
}
|
2018-12-05 10:47:01 -08:00
|
|
|
|
|
|
|
var (
|
|
|
|
calleeAddress = common.Address{2}
|
|
|
|
calleeContractCode = "600a6000526001601ff300" // a function that returns 10
|
|
|
|
callerAddress = common.Address{1}
|
|
|
|
// a functionn that calls the callee's function at its address and return the same value
|
|
|
|
//000000: PUSH1 0x01
|
|
|
|
//000002: PUSH1 0x00
|
|
|
|
//000004: PUSH1 0x00
|
|
|
|
//000006: PUSH1 0x00
|
|
|
|
//000008: PUSH20 0x0200000000000000000000000000000000000000
|
|
|
|
//000029: PUSH3 0x0186a0
|
|
|
|
//000033: STATICCALL
|
|
|
|
//000034: PUSH1 0x01
|
|
|
|
//000036: PUSH1 0x00
|
|
|
|
//000038: RETURN
|
|
|
|
//000039: STOP
|
|
|
|
callerContractCode = "6001600060006000730200000000000000000000000000000000000000620186a0fa60016000f300"
|
|
|
|
)
|
|
|
|
|
|
|
|
func verifyStaticCall(t *testing.T, privateState *state.StateDB, publicState *state.StateDB, expectedHash common.Hash) {
|
|
|
|
author := common.Address{}
|
|
|
|
msg := callmsg{
|
|
|
|
addr: author,
|
|
|
|
to: &callerAddress,
|
|
|
|
value: big.NewInt(1),
|
|
|
|
gas: 1000000,
|
|
|
|
gasPrice: new(big.Int),
|
|
|
|
data: nil,
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := NewEVMContext(msg, &dualStateTestHeader, nil, &author)
|
|
|
|
env := vm.NewEVM(ctx, publicState, privateState, ¶ms.ChainConfig{
|
|
|
|
ByzantiumBlock: new(big.Int),
|
|
|
|
}, vm.Config{})
|
|
|
|
|
|
|
|
ret, _, err := env.Call(vm.AccountRef(author), callerAddress, msg.data, msg.gas, new(big.Int))
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatalf("Call error: %s", err)
|
|
|
|
}
|
|
|
|
value := common.Hash{ret[0]}
|
|
|
|
if value != expectedHash {
|
|
|
|
t.Errorf("expected %x got %x", expectedHash, value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStaticCall_whenPublicToPublic(t *testing.T) {
|
|
|
|
db := ethdb.NewMemDatabase()
|
|
|
|
|
|
|
|
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
|
|
|
publicState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
|
|
|
|
publicState.SetCode(calleeAddress, common.Hex2Bytes(calleeContractCode))
|
|
|
|
|
|
|
|
verifyStaticCall(t, publicState, publicState, common.Hash{10})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStaticCall_whenPublicToPrivateInTheParty(t *testing.T) {
|
|
|
|
db := ethdb.NewMemDatabase()
|
|
|
|
|
|
|
|
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
|
|
|
privateState.SetCode(calleeAddress, common.Hex2Bytes(calleeContractCode))
|
|
|
|
|
|
|
|
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
|
|
|
publicState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
|
|
|
|
|
|
|
|
verifyStaticCall(t, privateState, publicState, common.Hash{10})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStaticCall_whenPublicToPrivateNotInTheParty(t *testing.T) {
|
|
|
|
|
|
|
|
db := ethdb.NewMemDatabase()
|
|
|
|
|
|
|
|
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
|
|
|
|
|
|
|
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
|
|
|
publicState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
|
|
|
|
|
|
|
|
verifyStaticCall(t, privateState, publicState, common.Hash{0})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStaticCall_whenPrivateToPublic(t *testing.T) {
|
|
|
|
db := ethdb.NewMemDatabase()
|
|
|
|
|
|
|
|
privateState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
|
|
|
privateState.SetCode(callerAddress, common.Hex2Bytes(callerContractCode))
|
|
|
|
|
|
|
|
publicState, _ := state.New(common.Hash{}, state.NewDatabase(db))
|
|
|
|
publicState.SetCode(calleeAddress, common.Hex2Bytes(calleeContractCode))
|
|
|
|
|
|
|
|
verifyStaticCall(t, privateState, publicState, common.Hash{10})
|
|
|
|
}
|