adding support for creating bootnode
diff --git a/Makefile b/Makefile
index 3922d60..77f351d 100644
--- a/Makefile
+++ b/Makefile
@@ -16,6 +16,11 @@ geth:
@echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth."
+ bootnode:
+ build/env.sh go run build/ci.go install ./cmd/bootnode
+ @echo "Done building."
+ @echo "Run \"$(GOBIN)/bootnode\" to launch bootnode."
+
swarm:
build/env.sh go run build/ci.go install ./cmd/swarm
@echo "Done building."
accounts/abi/bind/backends/simulated.go
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index 2b5c5fc..5362c94 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -37,6 +37,7 @@ import (
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -286,7 +287,7 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxUint64)
-
+ log.Iolite("when simulated? callContract", "msg.Data", msg.Data())
return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
}
core/meta/base_meta_executor.go
MetaExecutor interface base implementation
IntrinsicGas() inherit Ethereum algorithm
diff --git a/core/meta/base_meta_executor.go b/core/meta/base_meta_executor.go
new file mode 100644
index 0000000..89eb636
--- /dev/null
+++ b/core/meta/base_meta_executor.go
@@ -0,0 +1,46 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import (
+ "math"
+
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/params"
+ )
+
+ type BaseMetaExecutor struct {
+ metadata []byte
+ }
+
+ // IntrinsicGas computes the 'intrinsic gas' for a message with the given metadata. iolite.TODO: need to rework algorithm
+ func (executor *BaseMetaExecutor) IntrinsicGas() (uint64, error) {
+ if len(executor.metadata) == 0 {
+ return 0, nil
+ }
+
+ // Set the starting gas for the raw transaction
+ var gas uint64
+ // Bump the required gas by the amount of transactional data
+ if len(executor.metadata) > 0 {
+ // Zero and non-zero bytes are priced differently
+ var nz uint64
+ for _, byt := range executor.metadata {
+ if byt != 0 {
+ nz++
+ }
+ }
+ // Make sure we don't exceed uint64 for all data combinations
+ if (math.MaxUint64-gas)/params.TxDataNonZeroGas < nz {
+ return 0, vm.ErrOutOfGas
+ }
+ gas += nz * params.TxDataNonZeroGas
+
+ z := uint64(len(executor.metadata)) - nz
+ if (math.MaxUint64-gas)/params.TxDataZeroGas < z {
+ return 0, vm.ErrOutOfGas
+ }
+ gas += z * params.TxDataZeroGas
+ }
+ return gas, nil
+ }
core/meta/base_meta_payer.go
MetaPayer interface base implementation
CanPay() sums up all recipients and compares it with the specified limit
the result of IntrinsicGas() is the product of the number of recipients by TxGas(21000)
diff --git a/core/meta/base_meta_payer.go b/core/meta/base_meta_payer.go
new file mode 100644
index 0000000..c927ba2
--- /dev/null
+++ b/core/meta/base_meta_payer.go
@@ -0,0 +1,52 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/params"
+ )
+
+ type BaseMetaPayer struct {
+ from *common.Address
+ metaLogs *types.MetaLogs
+ metaLimit *big.Int
+ }
+
+ func (payer *BaseMetaPayer) CanPay() (*big.Int, bool) {
+ sum := big.NewInt(0)
+
+ if payer.metaLogs == nil || len(payer.metaLogs.Logs()) == 0 {
+ return sum, true
+ }
+
+ for _, log := range payer.metaLogs.Logs() {
+ sum.Add(sum, log.Amount)
+ }
+
+ log.Iolite("CanPay", "sum", sum, "metaLimit", payer.metaLimit)
+ if sum.Cmp(payer.metaLimit) > 0 {
+ return sum, false
+ }
+
+ return sum, true
+ }
+
+ func (payer *BaseMetaPayer) IntrinsicGas() (uint64, error) {
+ count := uint64(len(payer.metaLogs.Logs()))
+ if payer.metaLogs == nil || count == 0 {
+ return 0, nil
+ }
+
+ gas := count * params.TxGas
+ if gas/count != params.TxGas {
+ return 0, vm.ErrOutOfGas
+ }
+
+ return gas, nil
+ }
core/meta/business_meta_executor.go
Business implementation of MetaExecutor interface
Executes the metadata code in the EVM without changing the state
Compiles a list of recipients and their values
diff --git a/core/meta/business_meta_executor.go b/core/meta/business_meta_executor.go
new file mode 100644
index 0000000..c68083a
--- /dev/null
+++ b/core/meta/business_meta_executor.go
@@ -0,0 +1,65 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import (
+ "errors"
+ "math"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/rlp"
+ )
+
+ type BusinessMetaExecutor struct {
+ BaseMetaExecutor
+
+ readEVM *vm.EVM
+ from common.Address
+ }
+
+ func (executor *BusinessMetaExecutor) Execute() (*types.MetaLogs, error) {
+ metadata := new(types.BusinessMetadata)
+ metalogs := new(types.MetaLogs)
+
+ if len(executor.metadata) == 0 {
+ return metalogs, nil
+ }
+
+ if executor.readEVM == nil {
+ return metalogs, errors.New("the runtime is not specified")
+ }
+
+ if err := rlp.DecodeBytes(executor.metadata, metadata); err != nil {
+ return metalogs, err
+ }
+
+ log.Iolite("Business Metadata", "metadata", metadata)
+
+ sender := vm.AccountRef(executor.from)
+
+ ret, _, vmerr := executor.readEVM.Call(sender, *metadata.Data().Buisness, metadata.Data().Input, math.MaxUint64/2, big.NewInt(0))
+ if vmerr != nil {
+ return metalogs, vmerr
+ }
+
+ log.Iolite("Executed Metadata", "ret", ret)
+
+ if len(ret) != 64 {
+ return metalogs, errors.New("the business call result does not match the format (address, uint256)")
+ }
+
+ metalogs.Push(common.BytesToAddress(ret[:32]), big.NewInt(0).SetBytes(ret[32:]))
+
+ for _, data := range metalogs.Logs() {
+ log.Iolite("Decoded Metalogs", "To", data.Recipient, "Value", data.Amount)
+ }
+ return metalogs, nil
+ }
+
+ func NewBusinessMetaExecutor(metadata []byte, readEVM *vm.EVM, from common.Address) *BusinessMetaExecutor {
+ return &BusinessMetaExecutor{BaseMetaExecutor{metadata}, readEVM, from}
+ }
core/meta/business_meta_payer.go
Business implementation of MetaPayer interface
Pay off with the recipients through the EVM function call
diff --git a/core/meta/business_meta_payer.go b/core/meta/business_meta_payer.go
new file mode 100644
index 0000000..b3d6f43
--- /dev/null
+++ b/core/meta/business_meta_payer.go
@@ -0,0 +1,60 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import (
+ "errors"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/log"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ )
+
+ type BusinessMetaPayer struct {
+ BaseMetaPayer
+
+ evm *vm.EVM
+ }
+
+ func tryPay(from *common.Address, metaLogs *types.MetaLogs, evm *vm.EVM, gas uint64) (uint64, error) {
+ if evm == nil {
+ return gas, errors.New("the runtime is not specified")
+ }
+
+ var vmerr error
+ gasLeft := gas
+ sender := vm.AccountRef(*from)
+ for _, metalog := range metaLogs.Logs() {
+ _, gasLeft, vmerr = evm.Call(sender, *metalog.Recipient, []byte{}, gasLeft, metalog.Amount) // iolite.TODO need the correct gas calculation
+ log.Iolite("tryPay", "gas", gas, "gasLeft", gasLeft, "gasUsed", gas-gasLeft)
+ if vmerr != nil {
+ return gasLeft, vmerr
+ }
+ }
+ return gasLeft, nil
+ }
+
+ func (payer *BusinessMetaPayer) Pay(gas uint64) (*big.Int, uint64, error) {
+ if len(payer.metaLogs.Logs()) > 1 {
+ return big.NewInt(0), gas, errors.New("only one recipient is allowed for business call")
+ }
+
+ sum, payable := payer.CanPay()
+ if !payable {
+ return big.NewInt(0), gas, vm.ErrInsufficientBalance
+ }
+
+ gasLeft, err := tryPay(payer.from, payer.metaLogs, payer.evm, gas)
+ if err != nil {
+ return big.NewInt(0), gasLeft, err
+ }
+
+ return sum, gasLeft, nil
+ }
+
+ func NewBusinessMetaPayer(from common.Address, metaLogs *types.MetaLogs, metaLimit *big.Int, evm *vm.EVM) *BusinessMetaPayer {
+ return &BusinessMetaPayer{BaseMetaPayer{&from, metaLogs, metaLimit}, evm}
+ }
core/meta/meta_executor.go
Interface for working with metadata
diff --git a/core/meta/meta_executor.go b/core/meta/meta_executor.go
new file mode 100644
index 0000000..c66b7c5
--- /dev/null
+++ b/core/meta/meta_executor.go
@@ -0,0 +1,11 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import "github.com/ethereum/go-ethereum/core/types"
+
+ type MetaExecutor interface {
+ Execute() (*types.MetaLogs, error)
+
+ IntrinsicGas() (uint64, error)
+ }
Interface for working with metadata
diff --git a/core/meta/meta_payer.go b/core/meta/meta_payer.go
new file mode 100644
index 0000000..17f9742
--- /dev/null
+++ b/core/meta/meta_payer.go
@@ -0,0 +1,13 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import "math/big"
+
+ type MetaPayer interface {
+ Pay(gas uint64) (*big.Int, uint64, error)
+
+ CanPay() (*big.Int, bool)
+
+ IntrinsicGas() (uint64, error)
+ }
core/meta/simple_meta_executor.go
(Depreciated) Simple implementation of MetaExecutor interface
diff --git a/core/meta/simple_meta_executor.go b/core/meta/simple_meta_executor.go
new file mode 100644
index 0000000..fa9f070
--- /dev/null
+++ b/core/meta/simple_meta_executor.go
@@ -0,0 +1,34 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import (
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/rlp"
+ )
+
+ type SimpleMetaExecutor struct {
+ BaseMetaExecutor
+ }
+
+ func (executor *SimpleMetaExecutor) Execute() (*types.MetaLogs, error) {
+ meta := new(types.MetaLogs)
+
+ if len(executor.metadata) == 0 {
+ return meta, nil
+ }
+
+ if err := rlp.DecodeBytes(executor.metadata, meta); err != nil {
+ return meta, err
+ }
+
+ for _, data := range meta.Logs() {
+ log.Iolite("Decoded Metadata", "To", data.Recipient, "Value", data.Amount)
+ }
+ return meta, nil
+ }
+
+ func NewSimpleMetaExecutor(metadata []byte) *SimpleMetaExecutor {
+ return &SimpleMetaExecutor{BaseMetaExecutor{metadata}}
+ }
core/meta/simple_meta_payer.go
(Depreciated) Simple implementation of MetaPayer interface
diff --git a/core/meta/simple_meta_payer.go b/core/meta/simple_meta_payer.go
new file mode 100644
index 0000000..1cdc717
--- /dev/null
+++ b/core/meta/simple_meta_payer.go
@@ -0,0 +1,36 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package meta
+
+ import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ )
+
+ type SimpleMetaPayer struct {
+ BaseMetaPayer
+
+ state vm.StateDB
+ }
+
+ func (payer *SimpleMetaPayer) Pay(gas uint64) (*big.Int, uint64, error) {
+ sum, payable := payer.CanPay()
+ if !payable {
+ return big.NewInt(0), 0, vm.ErrInsufficientBalance
+ }
+
+ for _, log := range payer.metaLogs.Logs() {
+ payer.state.AddBalance(*log.Recipient, log.Amount)
+ payer.state.SubBalance(*payer.from, log.Amount)
+ }
+
+ return sum, 0, nil
+ }
+
+ func NewSimpleMetaPayer(from common.Address, metaLogs *types.MetaLogs, metaLimit *big.Int, state vm.StateDB) *SimpleMetaPayer {
+ return &SimpleMetaPayer{BaseMetaPayer{&from, metaLogs, metaLimit}, state}
+ }
Contains additional functions for working with metadata
diff --git a/core/meta_util.go b/core/meta_util.go
new file mode 100644
index 0000000..3c493a0
--- /dev/null
+++ b/core/meta_util.go
@@ -0,0 +1,113 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package core
+
+ import (
+ "errors"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/meta"
+ "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/log"
+ )
+
+ var (
+ ErrMetaInsufficientFunds = errors.New("insufficient funds for metadata payment or payment are not allowed")
+
+ ErrMetaIntrinsicGas = errors.New("metadata intrinsic gas error")
+ )
+
+ // iolite.TODO do something with code duplication
+
+ func UnpackSimpleMetadata(from common.Address, metadata []byte, metaLimit *big.Int, state vm.StateDB) (payer meta.MetaPayer, metaLogs *types.MetaLogs, payment *big.Int, intrinsicGas uint64, err error) {
+ log.Iolite("UnpackSimpleMetadata", "metaLimit", metaLimit)
+
+ executor := meta.NewSimpleMetaExecutor(metadata)
+
+ executorGas, err := executor.IntrinsicGas()
+ if err != nil {
+ return nil, nil, nil, 0, err
+ }
+
+ metaLogs, err = executor.Execute()
+ if err != nil {
+ return nil, metaLogs, nil, 0, err
+ }
+
+ payer = meta.NewSimpleMetaPayer(from, metaLogs, metaLimit, state)
+
+ payerGas, err := payer.IntrinsicGas()
+ if err != nil {
+ return nil, nil, nil, 0, err
+ }
+
+ payment, payable := payer.CanPay()
+ if !payable {
+ return nil, nil, nil, 0, ErrMetaInsufficientFunds
+ }
+
+ intrinsicGas = executorGas + payerGas
+ // Make sure we don't exceed uint64
+ if intrinsicGas < executorGas {
+ return nil, nil, nil, 0, ErrMetaIntrinsicGas
+ }
+
+ return payer, metaLogs, payment, intrinsicGas, nil
+ }
+
+ func UnpackBusinessMetadata(from common.Address, metadata []byte, metaLimit *big.Int, writeEVM *vm.EVM, readEVM *vm.EVM) (payer meta.MetaPayer, metaLogs *types.MetaLogs, payment *big.Int, intrinsicGas uint64, err error) {
+ log.Iolite("UnpackBusinessMetadata", "metaLimit", metaLimit)
+
+ executor := meta.NewBusinessMetaExecutor(metadata, readEVM, from)
+
+ executorGas, err := executor.IntrinsicGas()
+ if err != nil {
+ return nil, nil, nil, 0, err
+ }
+
+ metaLogs, err = executor.Execute()
+ if err != nil {
+ return nil, metaLogs, nil, 0, err
+ }
+
+ payer = meta.NewBusinessMetaPayer(from, metaLogs, metaLimit, writeEVM)
+
+ payerGas, err := payer.IntrinsicGas()
+ if err != nil {
+ return nil, nil, nil, 0, err
+ }
+
+ payment, payable := payer.CanPay()
+ if !payable {
+ return nil, nil, nil, 0, ErrMetaInsufficientFunds
+ }
+
+ intrinsicGas = executorGas + payerGas
+ // Make sure we don't exceed uint64
+ if intrinsicGas < executorGas {
+ return nil, nil, nil, 0, ErrMetaIntrinsicGas
+ }
+
+ return payer, metaLogs, payment, intrinsicGas, nil
+ }
+
+ func CreateReadOnlyEVMCopy(evm *vm.EVM, from common.Address) *vm.EVM {
+ statedb, ok := evm.StateDB.(*state.StateDB)
+ statedbCpy := statedb.Copy()
+ statedbCpy.SetBalance(from, math.MaxBig256)
+ log.Iolite("CREATE_STATE", "ok", ok)
+
+ return vm.NewEVM(evm.Context, statedbCpy, evm.ChainConfig(), vm.Config{})
+ }
+
+ func CreateReadOnlyEVM(msg types.Message, chain *BlockChain, statedb *state.StateDB) *vm.EVM {
+ statedbCpy := statedb.Copy()
+ header := chain.CurrentBlock().Header()
+ context := NewEVMContext(msg, header, chain, nil)
+ statedbCpy.SetBalance(msg.From(), math.MaxBig256)
+ return vm.NewEVM(context, statedbCpy, chain.Config(), vm.Config{})
+ }
Support of extra metadata fields
additional logs
diff --git a/core/state_processor.go b/core/state_processor.go
index 4dc58b9..b5e1f83 100644
--- a/core/state_processor.go
+++ b/core/state_processor.go
@@ -18,12 +18,14 @@ package core
import (
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"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/crypto"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
)
@@ -96,7 +98,7 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(context, statedb, config, cfg)
// Apply the transaction to the current state (included in the env)
- _, gas, failed, err := ApplyMessage(vmenv, msg, gp)
+ meta, _, gas, metaGas, failed, err := ApplyMessage(vmenv, msg, gp)
if err != nil {
return nil, 0, err
}
@@ -114,13 +116,15 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common
receipt := types.NewReceipt(root, failed, *usedGas)
receipt.TxHash = tx.Hash()
receipt.GasUsed = gas
+ receipt.MetaGasUsed = metaGas
// if the transaction created a contract, store the creation address in the receipt.
if msg.To() == nil {
receipt.ContractAddress = crypto.CreateAddress(vmenv.Context.Origin, tx.Nonce())
}
// Set the receipt logs and create a bloom for filtering
receipt.Logs = statedb.GetLogs(tx.Hash())
+ receipt.MetaLogs = meta.Logs()
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
-
+ log.Iolite("ApplyTransaction", "metadata", hexutil.Encode(msg.Metadata()))
return receipt, gas, err
}
Support of extra metadata fields
Backward compatibility with Ethereum transactions
additional logs
diff --git a/core/state_transition.go b/core/state_transition.go
index 5654cd0..b268014 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -22,6 +22,9 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/core/meta"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
@@ -73,6 +76,8 @@ type Message interface {
Nonce() uint64
CheckNonce() bool
Data() []byte
+ Metadata() []byte
+ MetadataLimit() *big.Int
}
// IntrinsicGas computes the 'intrinsic gas' for a message with the given data.
@@ -128,7 +133,7 @@ func NewStateTransition(evm *vm.EVM, msg Message, gp *GasPool) *StateTransition
// the gas used (which includes gas refunds) and an error if it failed. An error always
// indicates a core error meaning that the message would always fail for that particular
// state and would never be accepted within a block.
- func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool, error) {
+ func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) (*types.MetaLogs, []byte, uint64, uint64, bool, error) {
return NewStateTransition(evm, msg, gp).TransitionDb()
}
@@ -180,7 +185,7 @@ func (st *StateTransition) preCheck() error {
// TransitionDb will transition the state by applying the current message and
// returning the result including the the used gas. It returns an error if it
// failed. An error indicates a consensus issue.
- func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bool, err error) {
+ func (st *StateTransition) TransitionDb() (metalogs *types.MetaLogs, ret []byte, usedGas uint64, metaGasUsed uint64, failed bool, err error) {
if err = st.preCheck(); err != nil {
return
}
@@ -188,14 +193,31 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
sender := vm.AccountRef(msg.From())
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
contractCreation := msg.To() == nil
+ log.Iolite("ApplyMessage", "metadata", hexutil.Encode(st.msg.Metadata()), "limit", st.msg.MetadataLimit())
+
+ readEVM := CreateReadOnlyEVMCopy(st.evm, msg.From())
+ payer, metalogs, _, metaGas, err := UnpackBusinessMetadata(msg.From(), msg.Metadata(), msg.MetadataLimit(), st.evm, readEVM)
+ // payer, metalogs, _, metaGas, err := UnpackSimpleMetadata(msg.From(), msg.Metadata(), msg.MetadataLimit(), st.state)
+ if err != nil {
+ return nil, nil, 0, 0, false, err
+ }
// Pay intrinsic gas
- gas, err := IntrinsicGas(st.data, contractCreation, homestead)
+ txGas, err := IntrinsicGas(st.data, contractCreation, homestead)
if err != nil {
- return nil, 0, false, err
+ return nil, nil, 0, 0, false, err
+ }
+
+ gas := txGas + metaGas
+ // Make sure we don't exceed uint64
+ if gas < txGas {
+ return nil, nil, 0, 0, false, vm.ErrOutOfGas
}
+
+ log.Iolite("ApplyMessage", "gas", txGas, "metaGas", metaGas, "fullGas", gas)
+
if err = st.useGas(gas); err != nil {
- return nil, 0, false, err
+ return nil, nil, 0, 0, false, err
}
var (
@@ -203,28 +225,51 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
// vm errors do not effect consensus and are therefor
// not assigned to err, except for insufficient balance
// error.
- vmerr error
+ vmerr error
+ vmerr2 error
+ beforeMetaGasUsed uint64
)
- if contractCreation {
- ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
+
+ // if the business contract call is not correct, then the transaction will be considered a failure,
+ // but the logic of the pure transaction will be executed
+ tryPayer := meta.NewBusinessMetaPayer(msg.From(), metalogs, msg.MetadataLimit(), readEVM)
+ _, _, vmerr2 = tryPayer.Pay(metaGas)
+
+ if vmerr2 == nil {
+ log.Iolite("evm.before", "gas", st.gas)
+ if contractCreation {
+ ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
+ } else {
+ // Increment the nonce for the next transaction
+ st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
+ ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
+ }
+ log.Iolite("evm.after", "err", vmerr, "gas", st.gas)
+ if vmerr != nil {
+ log.Debug("VM returned with error", "err", vmerr)
+ // The only possible consensus-error would be if there wasn't
+ // sufficient balance to make the transfer happen. The first
+ // balance transfer may never fail.
+ if vmerr == vm.ErrInsufficientBalance {
+ return nil, nil, 0, 0, false, vmerr
+ }
+ }
+
+ beforeMetaGasUsed = st.gasUsed()
+ log.Iolite("payer.Pay.before", "gas", st.gas)
+ _, st.gas, vmerr2 = payer.Pay(st.gas)
+ log.Iolite("payer.Pay.after", "err", vmerr2, "gas", st.gas)
+ // iolite.TODO check vmerr == vm.ErrInsufficientBalance ?
} else {
- // Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
- ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
- }
- if vmerr != nil {
- log.Debug("VM returned with error", "err", vmerr)
- // The only possible consensus-error would be if there wasn't
- // sufficient balance to make the transfer happen. The first
- // balance transfer may never fail.
- if vmerr == vm.ErrInsufficientBalance {
- return nil, 0, false, vmerr
- }
+ log.Iolite("check before exec", "err", vmerr2)
}
st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
- return ret, st.gasUsed(), vmerr != nil, err
+ metaGasUsed = metaGas + st.gasUsed() - beforeMetaGasUsed
+ log.Iolite("metags???", "gasUsed diff", metaGasUsed)
+ return metalogs, ret, st.gasUsed(), metaGasUsed, vmerr != nil || vmerr2 != nil, err
}
func (st *StateTransition) refundGas() {
Support of extra metadata fields
additional logs
diff --git a/core/tx_pool.go b/core/tx_pool.go
index a554f66..1da68f1 100644
--- a/core/tx_pool.go
+++ b/core/tx_pool.go
@@ -581,16 +581,40 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
if pool.currentState.GetNonce(from) > tx.Nonce() {
return ErrNonceTooLow
}
+
+ msg, err := tx.AsMessage(pool.signer)
+ if err != nil {
+ return ErrInvalidSender
+ }
+
+ readEVM := CreateReadOnlyEVM(msg, pool.chain.(*BlockChain), pool.currentState)
+ _, _, payment, metaGas, err := UnpackBusinessMetadata(from, tx.Metadata(), tx.MetadataLimit(), nil, readEVM)
+ // _, _, payment, metaGas, err := UnpackSimpleMetadata(from, tx.Metadata(), tx.MetadataLimit(), nil)
+ if err != nil {
+ return err
+ }
// Transactor should have enough funds to cover the costs
// cost == V + GP * GL
- if pool.currentState.GetBalance(from).Cmp(tx.Cost()) < 0 {
+ txCost := big.NewInt(0)
+ txCost.Add(txCost, tx.Cost())
+ txCost.Add(txCost, payment)
+
+ if pool.currentState.GetBalance(from).Cmp(txCost) < 0 {
return ErrInsufficientFunds
}
+
intrGas, err := IntrinsicGas(tx.Data(), tx.To() == nil, pool.homestead)
if err != nil {
return err
}
- if tx.Gas() < intrGas {
+
+ gas := intrGas + metaGas
+ // Make sure we don't exceed uint64
+ if gas < intrGas {
+ return ErrIntrinsicGas
+ }
+
+ if tx.Gas() < gas {
return ErrIntrinsicGas
}
return nil
@@ -608,12 +632,12 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
// If the transaction is already known, discard it
hash := tx.Hash()
if pool.all[hash] != nil {
- log.Trace("Discarding already known transaction", "hash", hash)
+ log.Warn("Discarding already known transaction", "hash", hash)
return false, fmt.Errorf("known transaction: %x", hash)
}
// If the transaction fails basic validation, discard it
if err := pool.validateTx(tx, local); err != nil {
- log.Trace("Discarding invalid transaction", "hash", hash, "err", err)
+ log.Warn("Discarding invalid transaction", "hash", hash, "err", err)
invalidTxCounter.Inc(1)
return false, err
}
@@ -621,14 +645,14 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
if uint64(len(pool.all)) >= pool.config.GlobalSlots+pool.config.GlobalQueue {
// If the new transaction is underpriced, don't accept it
if pool.priced.Underpriced(tx, pool.locals) {
- log.Trace("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice())
+ log.Warn("Discarding underpriced transaction", "hash", hash, "price", tx.GasPrice())
underpricedTxCounter.Inc(1)
return false, ErrUnderpriced
}
// New transaction is better than our worse ones, make room for it
drop := pool.priced.Discard(len(pool.all)-int(pool.config.GlobalSlots+pool.config.GlobalQueue-1), pool.locals)
for _, tx := range drop {
- log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "price", tx.GasPrice())
+ log.Warn("Discarding freshly underpriced transaction", "hash", tx.Hash(), "price", tx.GasPrice())
underpricedTxCounter.Inc(1)
pool.removeTx(tx.Hash(), false)
}
@@ -652,7 +676,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
pool.priced.Put(tx)
pool.journalTx(from, tx)
- log.Trace("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To())
+ log.Warn("Pooled new executable transaction", "hash", hash, "from", from, "to", tx.To())
// We've directly injected a replacement transaction, notify subsystems
go pool.txFeed.Send(TxPreEvent{tx})
@@ -670,7 +694,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
}
pool.journalTx(from, tx)
- log.Trace("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To())
+ log.Warn("Pooled new future transaction", "hash", hash, "from", from, "to", tx.To())
return replace, nil
}
@@ -784,9 +808,9 @@ func (pool *TxPool) AddRemotes(txs []*types.Transaction) []error {
func (pool *TxPool) addTx(tx *types.Transaction, local bool) error {
pool.mu.Lock()
defer pool.mu.Unlock()
-
// Try to inject the transaction and update any state
replace, err := pool.add(tx, local)
+ log.Iolite("TxPool", "addTx.err", err)
if err != nil {
return err
}
/core/types/business_metadata.go
Type describing the Businnes metadata structure
diff --git a/core/types/business_metadata.go b/core/types/business_metadata.go
new file mode 100644
index 0000000..0913d13
--- /dev/null
+++ b/core/types/business_metadata.go
@@ -0,0 +1,39 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package types
+
+ import (
+ "io"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/rlp"
+ )
+
+ //go:generate gencodec -type metadata -field-override metadataMarshaling -out gen_metadata_json.go
+
+ // Metadata
+ type BusinessMetadata struct {
+ data metadata
+ }
+
+ type metadata struct {
+ Buisness *common.Address `json:"to" gencodec:"required"`
+ Input []byte `json:"input" gencodec:"required"`
+ }
+
+ type metadataMarshaling struct {
+ Input hexutil.Bytes
+ }
+
+ // EncodeRLP implements rlp.Encoder
+ func (meta *BusinessMetadata) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, &meta.data)
+ }
+
+ // DecodeRLP implements rlp.Decoder
+ func (meta *BusinessMetadata) DecodeRLP(s *rlp.Stream) error {
+ return s.Decode(&meta.data)
+ }
+
+ func (meta *BusinessMetadata) Data() *metadata { return &meta.data }
core/types/gen_header_json.go
diff --git a/core/types/gen_header_json.go b/core/types/gen_header_json.go
index 1b92cd9..1e832f2 100644
--- a/core/types/gen_header_json.go
+++ b/core/types/gen_header_json.go
@@ -13,6 +13,7 @@ import (
var _ = (*headerMarshaling)(nil)
+ // MarshalJSON marshals as JSON.
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
@@ -52,6 +53,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
return json.Marshal(&enc)
}
+ // UnmarshalJSON unmarshals from JSON.
func (h *Header) UnmarshalJSON(input []byte) error {
type Header struct {
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
diff --git a/core/types/gen_log_json.go b/core/types/gen_log_json.go
index 1b5ae3c..6e94339 100644
--- a/core/types/gen_log_json.go
+++ b/core/types/gen_log_json.go
@@ -12,6 +12,7 @@ import (
var _ = (*logMarshaling)(nil)
+ // MarshalJSON marshals as JSON.
func (l Log) MarshalJSON() ([]byte, error) {
type Log struct {
Address common.Address `json:"address" gencodec:"required"`
@@ -37,6 +38,7 @@ func (l Log) MarshalJSON() ([]byte, error) {
return json.Marshal(&enc)
}
+ // UnmarshalJSON unmarshals from JSON.
func (l *Log) UnmarshalJSON(input []byte) error {
type Log struct {
Address *common.Address `json:"address" gencodec:"required"`
core/types/gen_metadata_json.go
diff --git a/core/types/gen_metadata_json.go b/core/types/gen_metadata_json.go
new file mode 100644
index 0000000..b88be61
--- /dev/null
+++ b/core/types/gen_metadata_json.go
@@ -0,0 +1,46 @@
+ // Code generated by github.com/fjl/gencodec. DO NOT EDIT.
+
+ package types
+
+ import (
+ "encoding/json"
+ "errors"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ )
+
+ var _ = (*metadataMarshaling)(nil)
+
+ // MarshalJSON marshals as JSON.
+ func (m metadata) MarshalJSON() ([]byte, error) {
+ type metadata struct {
+ Buisness *common.Address `json:"to" gencodec:"required"`
+ Input hexutil.Bytes `json:"input" gencodec:"required"`
+ }
+ var enc metadata
+ enc.Buisness = m.Buisness
+ enc.Input = m.Input
+ return json.Marshal(&enc)
+ }
+
+ // UnmarshalJSON unmarshals from JSON.
+ func (m *metadata) UnmarshalJSON(input []byte) error {
+ type metadata struct {
+ Buisness *common.Address `json:"to" gencodec:"required"`
+ Input *hexutil.Bytes `json:"input" gencodec:"required"`
+ }
+ var dec metadata
+ if err := json.Unmarshal(input, &dec); err != nil {
+ return err
+ }
+ if dec.Buisness == nil {
+ return errors.New("missing required field 'to' for metadata")
+ }
+ m.Buisness = dec.Buisness
+ if dec.Input == nil {
+ return errors.New("missing required field 'input' for metadata")
+ }
+ m.Input = *dec.Input
+ return nil
+ }
core/types/gen_metalog_json.go
diff --git a/core/types/gen_metalog_json.go b/core/types/gen_metalog_json.go
new file mode 100644
index 0000000..be79f88
--- /dev/null
+++ b/core/types/gen_metalog_json.go
@@ -0,0 +1,47 @@
+ // Code generated by github.com/fjl/gencodec. DO NOT EDIT.
+
+ package types
+
+ import (
+ "encoding/json"
+ "errors"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ )
+
+ var _ = (*metalogMarshaling)(nil)
+
+ // MarshalJSON marshals as JSON.
+ func (m MetaLog) MarshalJSON() ([]byte, error) {
+ type MetaLog struct {
+ Recipient *common.Address `json:"to" gencodec:"required"`
+ Amount *hexutil.Big `json:"value" gencodec:"required"`
+ }
+ var enc MetaLog
+ enc.Recipient = m.Recipient
+ enc.Amount = (*hexutil.Big)(m.Amount)
+ return json.Marshal(&enc)
+ }
+
+ // UnmarshalJSON unmarshals from JSON.
+ func (m *MetaLog) UnmarshalJSON(input []byte) error {
+ type MetaLog struct {
+ Recipient *common.Address `json:"to" gencodec:"required"`
+ Amount *hexutil.Big `json:"value" gencodec:"required"`
+ }
+ var dec MetaLog
+ if err := json.Unmarshal(input, &dec); err != nil {
+ return err
+ }
+ if dec.Recipient == nil {
+ return errors.New("missing required field 'to' for MetaLog")
+ }
+ m.Recipient = dec.Recipient
+ if dec.Amount == nil {
+ return errors.New("missing required field 'value' for MetaLog")
+ }
+ m.Amount = (*big.Int)(dec.Amount)
+ return nil
+ }
core/types/gen_receipt_json.go
diff --git a/core/types/gen_receipt_json.go b/core/types/gen_receipt_json.go
index c297ade..9018eaa 100644
--- a/core/types/gen_receipt_json.go
+++ b/core/types/gen_receipt_json.go
@@ -12,6 +12,7 @@ import (
var _ = (*receiptMarshaling)(nil)
+ // MarshalJSON marshals as JSON.
func (r Receipt) MarshalJSON() ([]byte, error) {
type Receipt struct {
PostState hexutil.Bytes `json:"root"`
@@ -19,9 +20,11 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
CumulativeGasUsed hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"`
+ MetaLogs []*MetaLog `json:"metaLogs" gencodec:"required"`
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"`
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
+ MetaGasUsed hexutil.Uint64 `json:"metaGasUsed" gencodec:"required"`
}
var enc Receipt
enc.PostState = r.PostState
@@ -29,12 +32,15 @@ func (r Receipt) MarshalJSON() ([]byte, error) {
enc.CumulativeGasUsed = hexutil.Uint64(r.CumulativeGasUsed)
enc.Bloom = r.Bloom
enc.Logs = r.Logs
+ enc.MetaLogs = r.MetaLogs
enc.TxHash = r.TxHash
enc.ContractAddress = r.ContractAddress
enc.GasUsed = hexutil.Uint64(r.GasUsed)
+ enc.MetaGasUsed = hexutil.Uint64(r.MetaGasUsed)
return json.Marshal(&enc)
}
+ // UnmarshalJSON unmarshals from JSON.
func (r *Receipt) UnmarshalJSON(input []byte) error {
type Receipt struct {
PostState *hexutil.Bytes `json:"root"`
@@ -42,9 +48,11 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
CumulativeGasUsed *hexutil.Uint64 `json:"cumulativeGasUsed" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Logs []*Log `json:"logs" gencodec:"required"`
+ MetaLogs []*MetaLog `json:"metaLogs" gencodec:"required"`
TxHash *common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress *common.Address `json:"contractAddress"`
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
+ MetaGasUsed *hexutil.Uint64 `json:"metaGasUsed" gencodec:"required"`
}
var dec Receipt
if err := json.Unmarshal(input, &dec); err != nil {
@@ -68,6 +76,10 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'logs' for Receipt")
}
r.Logs = dec.Logs
+ if dec.MetaLogs == nil {
+ return errors.New("missing required field 'metaLogs' for Receipt")
+ }
+ r.MetaLogs = dec.MetaLogs
if dec.TxHash == nil {
return errors.New("missing required field 'transactionHash' for Receipt")
}
@@ -79,5 +91,9 @@ func (r *Receipt) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'gasUsed' for Receipt")
}
r.GasUsed = uint64(*dec.GasUsed)
+ if dec.MetaGasUsed == nil {
+ return errors.New("missing required field 'metaGasUsed' for Receipt")
+ }
+ r.MetaGasUsed = uint64(*dec.MetaGasUsed)
return nil
}
core/types/gen_tx_json.go
diff --git a/core/types/gen_tx_json.go b/core/types/gen_tx_json.go
index c27da67..ef6ac7f 100644
--- a/core/types/gen_tx_json.go
+++ b/core/types/gen_tx_json.go
@@ -13,18 +13,22 @@ import (
var _ = (*txdataMarshaling)(nil)
+ // MarshalJSON marshals as JSON.
func (t txdata) MarshalJSON() ([]byte, error) {
type txdata struct {
- AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
- Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
- GasLimit hexutil.Uint64 `json:"gas" gencodec:"required"`
- Recipient *common.Address `json:"to" rlp:"nil"`
- Amount *hexutil.Big `json:"value" gencodec:"required"`
- Payload hexutil.Bytes `json:"input" gencodec:"required"`
- V *hexutil.Big `json:"v" gencodec:"required"`
- R *hexutil.Big `json:"r" gencodec:"required"`
- S *hexutil.Big `json:"s" gencodec:"required"`
- Hash *common.Hash `json:"hash" rlp:"-"`
+ AccountNonce hexutil.Uint64 `json:"nonce" gencodec:"required"`
+ Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
+ GasLimit hexutil.Uint64 `json:"gas" gencodec:"required"`
+ Recipient *common.Address `json:"to" rlp:"nil"`
+ Amount *hexutil.Big `json:"value" gencodec:"required"`
+ Payload hexutil.Bytes `json:"input" gencodec:"required"`
+ Metadata hexutil.Bytes `json:"metadata" gencodec:"required"`
+ MetadataLimit *hexutil.Big `json:"metadataLimit" gencodec:"required"`
+ IsOld hexutil.Uint `json:"isOld" gencodec:"required"`
+ V *hexutil.Big `json:"v" gencodec:"required"`
+ R *hexutil.Big `json:"r" gencodec:"required"`
+ S *hexutil.Big `json:"s" gencodec:"required"`
+ Hash *common.Hash `json:"hash" rlp:"-"`
}
var enc txdata
enc.AccountNonce = hexutil.Uint64(t.AccountNonce)
@@ -33,6 +37,9 @@ func (t txdata) MarshalJSON() ([]byte, error) {
enc.Recipient = t.Recipient
enc.Amount = (*hexutil.Big)(t.Amount)
enc.Payload = t.Payload
+ enc.Metadata = t.Metadata
+ enc.MetadataLimit = (*hexutil.Big)(t.MetadataLimit)
+ enc.IsOld = hexutil.Uint(t.IsOld)
enc.V = (*hexutil.Big)(t.V)
enc.R = (*hexutil.Big)(t.R)
enc.S = (*hexutil.Big)(t.S)
@@ -40,18 +47,22 @@ func (t txdata) MarshalJSON() ([]byte, error) {
return json.Marshal(&enc)
}
+ // UnmarshalJSON unmarshals from JSON.
func (t *txdata) UnmarshalJSON(input []byte) error {
type txdata struct {
- AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
- Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
- GasLimit *hexutil.Uint64 `json:"gas" gencodec:"required"`
- Recipient *common.Address `json:"to" rlp:"nil"`
- Amount *hexutil.Big `json:"value" gencodec:"required"`
- Payload *hexutil.Bytes `json:"input" gencodec:"required"`
- V *hexutil.Big `json:"v" gencodec:"required"`
- R *hexutil.Big `json:"r" gencodec:"required"`
- S *hexutil.Big `json:"s" gencodec:"required"`
- Hash *common.Hash `json:"hash" rlp:"-"`
+ AccountNonce *hexutil.Uint64 `json:"nonce" gencodec:"required"`
+ Price *hexutil.Big `json:"gasPrice" gencodec:"required"`
+ GasLimit *hexutil.Uint64 `json:"gas" gencodec:"required"`
+ Recipient *common.Address `json:"to" rlp:"nil"`
+ Amount *hexutil.Big `json:"value" gencodec:"required"`
+ Payload *hexutil.Bytes `json:"input" gencodec:"required"`
+ Metadata *hexutil.Bytes `json:"metadata" gencodec:"required"`
+ MetadataLimit *hexutil.Big `json:"metadataLimit" gencodec:"required"`
+ IsOld *hexutil.Uint `json:"isOld" gencodec:"required"`
+ V *hexutil.Big `json:"v" gencodec:"required"`
+ R *hexutil.Big `json:"r" gencodec:"required"`
+ S *hexutil.Big `json:"s" gencodec:"required"`
+ Hash *common.Hash `json:"hash" rlp:"-"`
}
var dec txdata
if err := json.Unmarshal(input, &dec); err != nil {
@@ -80,6 +91,18 @@ func (t *txdata) UnmarshalJSON(input []byte) error {
return errors.New("missing required field 'input' for txdata")
}
t.Payload = *dec.Payload
+ if dec.Metadata == nil {
+ return errors.New("missing required field 'metadata' for txdata")
+ }
+ t.Metadata = *dec.Metadata
+ if dec.MetadataLimit == nil {
+ return errors.New("missing required field 'metadataLimit' for txdata")
+ }
+ t.MetadataLimit = (*big.Int)(dec.MetadataLimit)
+ if dec.IsOld == nil {
+ return errors.New("missing required field 'isOld' for txdata")
+ }
+ t.IsOld = uint(*dec.IsOld)
if dec.V == nil {
return errors.New("missing required field 'v' for txdata")
}
Type describing the structure of unpacked metadata
diff --git a/core/types/metalogs.go b/core/types/metalogs.go
new file mode 100644
index 0000000..9796382
--- /dev/null
+++ b/core/types/metalogs.go
@@ -0,0 +1,44 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package types
+
+ import (
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/rlp"
+ )
+
+ //go:generate gencodec -type MetaLog -field-override metalogMarshaling -out gen_metalog_json.go
+
+ // Metadata
+ type MetaLogs struct {
+ logs []*MetaLog
+ }
+
+ type MetaLog struct {
+ Recipient *common.Address `json:"to" gencodec:"required"`
+ Amount *big.Int `json:"value" gencodec:"required"`
+ }
+
+ type metalogMarshaling struct {
+ Amount *hexutil.Big
+ }
+
+ // EncodeRLP implements rlp.Encoder
+ func (meta *MetaLogs) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, &meta.logs)
+ }
+
+ // DecodeRLP implements rlp.Decoder
+ func (meta *MetaLogs) DecodeRLP(s *rlp.Stream) error {
+ return s.Decode(&meta.logs)
+ }
+
+ func (meta *MetaLogs) Logs() []*MetaLog { return meta.logs }
+
+ func (meta *MetaLogs) Push(recipient common.Address, amount *big.Int) {
+ meta.logs = append(meta.logs, &MetaLog{&recipient, amount})
+ }
core/types/new_iolite_transaction.go
Intermediate type containing metadata fields specific for the Iolite
diff --git a/core/types/new_iolite_transaction.go b/core/types/new_iolite_transaction.go
new file mode 100644
index 0000000..7d3ff36
--- /dev/null
+++ b/core/types/new_iolite_transaction.go
@@ -0,0 +1,97 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package types
+
+ import (
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
+ )
+
+ // IoliteTransaction is an extra type, necessary for maintaining iolite transactions.
+ type NewIoliteTransaction struct {
+ data newtxdata
+ }
+
+ type newtxdata struct {
+ AccountNonce uint64 `json:"nonce" gencodec:"required"`
+ Price *big.Int `json:"gasPrice" gencodec:"required"`
+ GasLimit uint64 `json:"gas" gencodec:"required"`
+ Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
+ Amount *big.Int `json:"value" gencodec:"required"`
+ Payload []byte `json:"input" gencodec:"required"`
+ Metadata []byte `json:"metadata" gencodec:"required"`
+ MetadataLimit *big.Int `json:"metadataLimit" gencodec:"required"`
+
+ // Signature values
+ V *big.Int `json:"v" gencodec:"required"`
+ R *big.Int `json:"r" gencodec:"required"`
+ S *big.Int `json:"s" gencodec:"required"`
+ }
+
+ // EncodeRLP implements rlp.Encoder
+ func (tx *NewIoliteTransaction) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, &tx.data)
+ }
+
+ // DecodeRLP implements rlp.Decoder
+ func (tx *NewIoliteTransaction) DecodeRLP(s *rlp.Stream) error {
+ return s.Decode(&tx.data)
+ }
+
+ // AsTransaction returns the OldTransaction as a Transaction.
+ func (tx *NewIoliteTransaction) AsTransaction() *Transaction {
+ d := txdata{
+ AccountNonce: tx.data.AccountNonce,
+ Recipient: tx.data.Recipient,
+ Payload: tx.data.Payload,
+ Amount: tx.data.Amount,
+ GasLimit: tx.data.GasLimit,
+ Price: tx.data.Price,
+ Metadata: tx.data.Metadata,
+ MetadataLimit: tx.data.MetadataLimit,
+ IsOld: 0,
+ V: tx.data.V,
+ R: tx.data.R,
+ S: tx.data.S,
+ }
+
+ return &Transaction{data: d}
+ }
+
+ func CreateNewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *NewIoliteTransaction {
+ return createNewTransaction(nonce, &to, amount, gasLimit, gasPrice, data)
+ }
+
+ func CreateNewContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *NewIoliteTransaction {
+ return createNewTransaction(nonce, nil, amount, gasLimit, gasPrice, data)
+ }
+
+ func createNewTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *NewIoliteTransaction {
+ if len(data) > 0 {
+ data = common.CopyBytes(data)
+ }
+ d := newtxdata{
+ AccountNonce: nonce,
+ Recipient: to,
+ Payload: data,
+ Amount: new(big.Int),
+ GasLimit: gasLimit,
+ Price: new(big.Int),
+ Metadata: nil,
+ MetadataLimit: new(big.Int),
+ V: new(big.Int),
+ R: new(big.Int),
+ S: new(big.Int),
+ }
+ if amount != nil {
+ d.Amount.Set(amount)
+ }
+ if gasPrice != nil {
+ d.Price.Set(gasPrice)
+ }
+
+ return &NewIoliteTransaction{data: d}
+ }
core/types/old_transaction.go
Saved structure of the Ethereum transaction
Intermediate type that is used for backward compatibility
diff --git a/core/types/old_transaction.go b/core/types/old_transaction.go
new file mode 100644
index 0000000..b85206f
--- /dev/null
+++ b/core/types/old_transaction.go
@@ -0,0 +1,93 @@
+ // Copyright 2018 ... iolite.TODO
+
+ package types
+
+ import (
+ "io"
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
+ )
+
+ // OldTransaction is an extra type, necessary for maintaining pure ethereum transactions.
+ type OldTransaction struct {
+ data oldtxdata
+ }
+
+ type oldtxdata struct {
+ AccountNonce uint64 `json:"nonce" gencodec:"required"`
+ Price *big.Int `json:"gasPrice" gencodec:"required"`
+ GasLimit uint64 `json:"gas" gencodec:"required"`
+ Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
+ Amount *big.Int `json:"value" gencodec:"required"`
+ Payload []byte `json:"input" gencodec:"required"`
+
+ // Signature values
+ V *big.Int `json:"v" gencodec:"required"`
+ R *big.Int `json:"r" gencodec:"required"`
+ S *big.Int `json:"s" gencodec:"required"`
+ }
+
+ // EncodeRLP implements rlp.Encoder
+ func (tx *OldTransaction) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, &tx.data)
+ }
+
+ // DecodeRLP implements rlp.Decoder
+ func (tx *OldTransaction) DecodeRLP(s *rlp.Stream) error {
+ return s.Decode(&tx.data)
+ }
+
+ // AsTransaction returns the OldTransaction as a Transaction.
+ func (tx *OldTransaction) AsTransaction() *Transaction {
+ d := txdata{
+ AccountNonce: tx.data.AccountNonce,
+ Recipient: tx.data.Recipient,
+ Payload: tx.data.Payload,
+ Amount: tx.data.Amount,
+ GasLimit: tx.data.GasLimit,
+ Price: tx.data.Price,
+ Metadata: nil,
+ MetadataLimit: new(big.Int),
+ IsOld: 1,
+ V: tx.data.V,
+ R: tx.data.R,
+ S: tx.data.S,
+ }
+
+ return &Transaction{data: d}
+ }
+
+ func CreateOldTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *OldTransaction {
+ return createOldTransaction(nonce, &to, amount, gasLimit, gasPrice, data)
+ }
+
+ func CreateOldContractCreation(nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *OldTransaction {
+ return createOldTransaction(nonce, nil, amount, gasLimit, gasPrice, data)
+ }
+
+ func createOldTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *OldTransaction {
+ if len(data) > 0 {
+ data = common.CopyBytes(data)
+ }
+ d := oldtxdata{
+ AccountNonce: nonce,
+ Recipient: to,
+ Payload: data,
+ Amount: new(big.Int),
+ GasLimit: gasLimit,
+ Price: new(big.Int),
+ V: new(big.Int),
+ R: new(big.Int),
+ S: new(big.Int),
+ }
+ if amount != nil {
+ d.Amount.Set(amount)
+ }
+ if gasPrice != nil {
+ d.Price.Set(gasPrice)
+ }
+
+ return &OldTransaction{data: d}
+ }
core/types/old_transaction_test.go
diff --git a/core/types/old_transaction_test.go b/core/types/old_transaction_test.go
new file mode 100644
index 0000000..61edc8b
--- /dev/null
+++ b/core/types/old_transaction_test.go
@@ -0,0 +1,43 @@
+ // Copyright 2018 ... iolite.TODO
+ package types
+
+ import (
+ "bytes"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/rlp"
+ )
+
+ func TestNewTransaction(t *testing.T) {
+ var tx Transaction
+ err := rlp.Decode(bytes.NewReader(common.Hex2Bytes("f8a08183850430e23400833d090094c01bab898cc6aa51273a7a31bae1a32e5cbc517b8502540be40080b3f2d894c01bab898cc6aa51273a7a31bae1a32e5cbc517b822b67d894f0476fab07ee687f7f1feeb41703b7da737802628256ce801ca00e9f4ee0174f50425613f3707b9d7e5c439b295323a0d1da614e4ede558463d1a0258dfe621c94691f7fff3d0db08ba7eeef84bfb3e407cf53da40e44a4e72bfe4")), &tx)
+ if err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
+
+ metadata := hexutil.Bytes(tx.Metadata()).String()
+ should := "0xf2d894c01bab898cc6aa51273a7a31bae1a32e5cbc517b822b67d894f0476fab07ee687f7f1feeb41703b7da737802628256ce"
+ if metadata != should {
+ t.Errorf("Metadata mismatch, got %s, should %s", metadata, should)
+ t.FailNow()
+ }
+ }
+
+ func TestOldTransaction(t *testing.T) {
+ var tx OldTransaction
+ err := rlp.Decode(bytes.NewReader(common.Hex2Bytes("f909833a84ee6b2800833d09008080b9092e606060405260408051908101604052600281527f4c310000000000000000000000000000000000000000000000000000000000006020820152600690805161004b92916020019061011c565b50341561005757600080fd5b633b9aca006000818155600160a060020a03301681526001602052604090819020919091558051908101604052600a81527f4c69676874546f6b656e00000000000000000000000000000000000000000000602082015260039080516100c192916020019061011c565b506004805460ff1916600317905560408051908101604052600281527f4c540000000000000000000000000000000000000000000000000000000000006020820152600590805161011692916020019061011c565b506101b7565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061015d57805160ff191683800117855561018a565b8280016001018555821561018a579182015b8281111561018a57825182559160200191906001019061016f565b5061019692915061019a565b5090565b6101b491905b8082111561019657600081556001016101a0565b90565b610768806101c66000396000f3006060604052600436106100ae5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166306fdde0381146100b3578063095ea7b31461013d57806318160ddd1461017357806323b872dd14610198578063313ce567146101c05780634e71d92d146101e957806354fd4d50146101fc57806370a082311461020f57806395d89b411461022e578063a9059cbb14610241578063dd62ed3e14610263575b600080fd5b34156100be57600080fd5b6100c6610288565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156101025780820151838201526020016100ea565b50505050905090810190601f16801561012f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014857600080fd5b61015f600160a060020a0360043516602435610326565b604051901515815260200160405180910390f35b341561017e57600080fd5b610186610392565b60405190815260200160405180910390f35b34156101a357600080fd5b61015f600160a060020a0360043581169060243516604435610398565b34156101cb57600080fd5b6101d36104a6565b60405160ff909116815260200160405180910390f35b34156101f457600080fd5b61015f6104af565b341561020757600080fd5b6100c6610565565b341561021a57600080fd5b610186600160a060020a03600435166105d0565b341561023957600080fd5b6100c66105eb565b341561024c57600080fd5b61015f600160a060020a0360043516602435610656565b341561026e57600080fd5b610186600160a060020a0360043581169060243516610711565b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561031e5780601f106102f35761010080835404028352916020019161031e565b820191906000526020600020905b81548152906001019060200180831161030157829003601f168201915b505050505081565b600160a060020a03338116600081815260026020908152604080832094871680845294909152808220859055909291907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259085905190815260200160405180910390a350600192915050565b60005481565b600160a060020a0383166000908152600160205260408120548290108015906103e85750600160a060020a0380851660009081526002602090815260408083203390941683529290522054829010155b801561040d5750600160a060020a038316600090815260016020526040902054828101115b151561041857600080fd5b600160a060020a03808416600081815260016020908152604080832080548801905588851680845281842080548990039055600283528184203390961684529490915290819020805486900390559091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a35060019392505050565b60045460ff1681565b600160a060020a0330811660009081526001602052604080822054339093168252812054909182916103e890910490106104e857600080fd5b50600160a060020a033081166000818152600160205260408082208054339095168084528284208054612710909704968701905592849052805485900390559091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9084905190815260200160405180910390a3600191505090565b60068054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561031e5780601f106102f35761010080835404028352916020019161031e565b600160a060020a031660009081526001602052604090205490565b60058054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561031e5780601f106102f35761010080835404028352916020019161031e565b600160a060020a0333166000908152600160205260408120548290108015906106985750600160a060020a038316600090815260016020526040902054828101115b15156106a357600080fd5b600160a060020a033381166000818152600160205260408082208054879003905592861680825290839020805486019055917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9085905190815260200160405180910390a350600192915050565b600160a060020a039182166000908152600260209081526040808320939094168252919091522054905600a165627a7a72305820703e40f0b83a73193a988a76f347cba2a882ca820b0b7af5fe7d12b3eae553ca00298325ab46a08fc1a0da7f8b748c1b563781d6f98c9a08dc59ef8b9db0a3d8d2c7adb6727c82a06170df4b6f8a6be1bf3c879f8082ade0c8bd640cbcced677a4be1153253dac35")), &tx)
+ if err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
+
+ metadata := hexutil.Bytes(tx.AsTransaction().Metadata()).String()
+ should := "0x"
+ if metadata != should {
+ t.Errorf("Metadata mismatch, got %s, should %s", metadata, should)
+ t.FailNow()
+ }
+ }
metaLogs field added
metaGasUsed field added
diff --git a/core/types/receipt.go b/core/types/receipt.go
index 613f03d..5a625b0 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -20,10 +20,12 @@ import (
"bytes"
"fmt"
"io"
+ "math/big"
"unsafe"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -45,16 +47,18 @@ const (
// Receipt represents the results of a transaction.
type Receipt struct {
// Consensus fields
- PostState []byte `json:"root"`
- Status uint `json:"status"`
- CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"`
- Bloom Bloom `json:"logsBloom" gencodec:"required"`
- Logs []*Log `json:"logs" gencodec:"required"`
+ PostState []byte `json:"root"`
+ Status uint `json:"status"`
+ CumulativeGasUsed uint64 `json:"cumulativeGasUsed" gencodec:"required"`
+ Bloom Bloom `json:"logsBloom" gencodec:"required"`
+ Logs []*Log `json:"logs" gencodec:"required"`
+ MetaLogs []*MetaLog `json:"metaLogs" gencodec:"required"`
// Implementation fields (don't reorder!)
TxHash common.Hash `json:"transactionHash" gencodec:"required"`
ContractAddress common.Address `json:"contractAddress"`
GasUsed uint64 `json:"gasUsed" gencodec:"required"`
+ MetaGasUsed uint64 `json:"metaGasUsed" gencodec:"required"`
}
type receiptMarshaling struct {
@@ -62,6 +66,7 @@ type receiptMarshaling struct {
Status hexutil.Uint
CumulativeGasUsed hexutil.Uint64
GasUsed hexutil.Uint64
+ MetaGasUsed hexutil.Uint64
}
// receiptRLP is the consensus encoding of a receipt.
@@ -70,6 +75,7 @@ type receiptRLP struct {
CumulativeGasUsed uint64
Bloom Bloom
Logs []*Log
+ MetaLogs []*MetaLog
}
type receiptStorageRLP struct {
@@ -79,7 +85,9 @@ type receiptStorageRLP struct {
TxHash common.Hash
ContractAddress common.Address
Logs []*LogForStorage
+ MetaLogs []*MetaLog
GasUsed uint64
+ MetaGasUsed uint64
}
// NewReceipt creates a barebone transaction receipt, copying the init fields.
@@ -96,7 +104,7 @@ func NewReceipt(root []byte, failed bool, cumulativeGasUsed uint64) *Receipt {
// EncodeRLP implements rlp.Encoder, and flattens the consensus fields of a receipt
// into an RLP stream. If no post state is present, byzantium fork is assumed.
func (r *Receipt) EncodeRLP(w io.Writer) error {
- return rlp.Encode(w, &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs})
+ return rlp.Encode(w, &receiptRLP{r.statusEncoding(), r.CumulativeGasUsed, r.Bloom, r.Logs, r.MetaLogs})
}
// DecodeRLP implements rlp.Decoder, and loads the consensus fields of a receipt
@@ -110,6 +118,7 @@ func (r *Receipt) DecodeRLP(s *rlp.Stream) error {
return err
}
r.CumulativeGasUsed, r.Bloom, r.Logs = dec.CumulativeGasUsed, dec.Bloom, dec.Logs
+ r.MetaLogs = dec.MetaLogs
return nil
}
@@ -146,6 +155,15 @@ func (r *Receipt) Size() common.StorageSize {
for _, log := range r.Logs {
size += common.StorageSize(len(log.Topics)*common.HashLength + len(log.Data))
}
+
+ size += common.StorageSize(len(r.MetaLogs)) * common.StorageSize(unsafe.Sizeof(MetaLog{}))
+ for _, metalog := range r.MetaLogs {
+ size += common.StorageSize(common.AddressLength)
+ size += common.StorageSize(len(metalog.Amount.Bits())) * common.StorageSize(unsafe.Sizeof(big.Word(0)))
+ }
+
+ //iolite.TODO: Test during synchronization of the blockchain
+ log.Iolite("Receipt", "Size", size)
return size
}
@@ -163,7 +181,9 @@ func (r *ReceiptForStorage) EncodeRLP(w io.Writer) error {
TxHash: r.TxHash,
ContractAddress: r.ContractAddress,
Logs: make([]*LogForStorage, len(r.Logs)),
+ MetaLogs: r.MetaLogs,
GasUsed: r.GasUsed,
+ MetaGasUsed: r.MetaGasUsed,
}
for i, log := range r.Logs {
enc.Logs[i] = (*LogForStorage)(log)
@@ -187,6 +207,8 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
for i, log := range dec.Logs {
r.Logs[i] = (*Log)(log)
}
+ r.MetaLogs = dec.MetaLogs
+ r.MetaGasUsed = dec.MetaGasUsed
// Assign the implementation fields
r.TxHash, r.ContractAddress, r.GasUsed = dec.TxHash, dec.ContractAddress, dec.GasUsed
return nil
diff --git a/core/types/transaction.go b/core/types/transaction.go
index 70d757c..5340be7 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -54,12 +54,16 @@ type Transaction struct {
}
type txdata struct {
- AccountNonce uint64 `json:"nonce" gencodec:"required"`
- Price *big.Int `json:"gasPrice" gencodec:"required"`
- GasLimit uint64 `json:"gas" gencodec:"required"`
- Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
- Amount *big.Int `json:"value" gencodec:"required"`
- Payload []byte `json:"input" gencodec:"required"`
+ AccountNonce uint64 `json:"nonce" gencodec:"required"`
+ Price *big.Int `json:"gasPrice" gencodec:"required"`
+ GasLimit uint64 `json:"gas" gencodec:"required"`
+ Recipient *common.Address `json:"to" rlp:"nil"` // nil means contract creation
+ Amount *big.Int `json:"value" gencodec:"required"`
+ Payload []byte `json:"input" gencodec:"required"`
+ Metadata []byte `json:"metadata" gencodec:"required"`
+ MetadataLimit *big.Int `json:"metadataLimit" gencodec:"required"`
+
+ IsOld uint `json:"isOld" gencodec:"required"`
// Signature values
V *big.Int `json:"v" gencodec:"required"`
@@ -71,14 +75,17 @@ type txdata struct {
}
type txdataMarshaling struct {
- AccountNonce hexutil.Uint64
- Price *hexutil.Big
- GasLimit hexutil.Uint64
- Amount *hexutil.Big
- Payload hexutil.Bytes
- V *hexutil.Big
- R *hexutil.Big
- S *hexutil.Big
+ AccountNonce hexutil.Uint64
+ Price *hexutil.Big
+ GasLimit hexutil.Uint64
+ Amount *hexutil.Big
+ Payload hexutil.Bytes
+ Metadata hexutil.Bytes
+ MetadataLimit *hexutil.Big
+ IsOld hexutil.Uint
+ V *hexutil.Big
+ R *hexutil.Big
+ S *hexutil.Big
}
func NewTransaction(nonce uint64, to common.Address, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte) *Transaction {
@@ -94,15 +101,18 @@ func newTransaction(nonce uint64, to *common.Address, amount *big.Int, gasLimit
data = common.CopyBytes(data)
}
d := txdata{
- AccountNonce: nonce,
- Recipient: to,
- Payload: data,
- Amount: new(big.Int),
- GasLimit: gasLimit,
- Price: new(big.Int),
- V: new(big.Int),
- R: new(big.Int),
- S: new(big.Int),
+ AccountNonce: nonce,
+ Recipient: to,
+ Payload: data,
+ Amount: new(big.Int),
+ GasLimit: gasLimit,
+ Price: new(big.Int),
+ Metadata: nil,
+ MetadataLimit: new(big.Int),
+ IsOld: 0,
+ V: new(big.Int),
+ R: new(big.Int),
+ S: new(big.Int),
}
if amount != nil {
d.Amount.Set(amount)
@@ -177,12 +187,15 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error {
return nil
}
- func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
- func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
- func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) }
- func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
- func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
- func (tx *Transaction) CheckNonce() bool { return true }
+ func (tx *Transaction) Data() []byte { return common.CopyBytes(tx.data.Payload) }
+ func (tx *Transaction) Metadata() []byte { return common.CopyBytes(tx.data.Metadata) }
+ func (tx *Transaction) MetadataLimit() *big.Int { return new(big.Int).Set(tx.data.MetadataLimit) }
+ func (tx *Transaction) Gas() uint64 { return tx.data.GasLimit }
+ func (tx *Transaction) GasPrice() *big.Int { return new(big.Int).Set(tx.data.Price) }
+ func (tx *Transaction) Value() *big.Int { return new(big.Int).Set(tx.data.Amount) }
+ func (tx *Transaction) Nonce() uint64 { return tx.data.AccountNonce }
+ func (tx *Transaction) CheckNonce() bool { return true }
+ func (tx *Transaction) IsOld() bool { return tx.data.IsOld != 0 }
// To returns the recipient address of the transaction.
// It returns nil if the transaction is a contract creation.
@@ -200,7 +213,12 @@ func (tx *Transaction) Hash() common.Hash {
if hash := tx.hash.Load(); hash != nil {
return hash.(common.Hash)
}
- v := rlpHash(tx)
+ var v common.Hash
+ if tx.IsOld() {
+ v = rlpHash(tx.AsOldTransaction())
+ } else {
+ v = rlpHash(tx.AsNewIoliteTransaction())
+ }
tx.hash.Store(v)
return v
}
@@ -224,13 +242,15 @@ func (tx *Transaction) Size() common.StorageSize {
// XXX Rename message to something less arbitrary?
func (tx *Transaction) AsMessage(s Signer) (Message, error) {
msg := Message{
- nonce: tx.data.AccountNonce,
- gasLimit: tx.data.GasLimit,
- gasPrice: new(big.Int).Set(tx.data.Price),
- to: tx.data.Recipient,
- amount: tx.data.Amount,
- data: tx.data.Payload,
- checkNonce: true,
+ nonce: tx.data.AccountNonce,
+ gasLimit: tx.data.GasLimit,
+ gasPrice: new(big.Int).Set(tx.data.Price),
+ to: tx.data.Recipient,
+ amount: tx.data.Amount,
+ data: tx.data.Payload,
+ metadata: tx.data.Metadata,
+ metadataLimit: tx.data.MetadataLimit,
+ checkNonce: true,
}
var err error
@@ -238,6 +258,40 @@ func (tx *Transaction) AsMessage(s Signer) (Message, error) {
return msg, err
}
+ func (tx *Transaction) AsOldTransaction() *OldTransaction {
+ d := oldtxdata{
+ AccountNonce: tx.data.AccountNonce,
+ Recipient: tx.data.Recipient,
+ Payload: tx.data.Payload,
+ Amount: tx.data.Amount,
+ GasLimit: tx.data.GasLimit,
+ Price: tx.data.Price,
+ V: tx.data.V,
+ R: tx.data.R,
+ S: tx.data.S,
+ }
+
+ return &OldTransaction{data: d}
+ }
+
+ func (tx *Transaction) AsNewIoliteTransaction() *NewIoliteTransaction {
+ d := newtxdata{
+ AccountNonce: tx.data.AccountNonce,
+ Recipient: tx.data.Recipient,
+ Payload: tx.data.Payload,
+ Amount: tx.data.Amount,
+ GasLimit: tx.data.GasLimit,
+ Price: tx.data.Price,
+ Metadata: tx.data.Metadata,
+ MetadataLimit: tx.data.MetadataLimit,
+ V: tx.data.V,
+ R: tx.data.R,
+ S: tx.data.S,
+ }
+
+ return &NewIoliteTransaction{data: d}
+ }
+
// WithSignature returns a new transaction with the given signature.
// This signature needs to be formatted as described in the yellow paper (v+27).
func (tx *Transaction) WithSignature(signer Signer, sig []byte) (*Transaction, error) {
@@ -386,34 +440,44 @@ func (t *TransactionsByPriceAndNonce) Pop() {
//
// NOTE: In a future PR this will be removed.
type Message struct {
- to *common.Address
- from common.Address
- nonce uint64
- amount *big.Int
- gasLimit uint64
- gasPrice *big.Int
- data []byte
- checkNonce bool
- }
-
- func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message {
+ to *common.Address
+ from common.Address
+ nonce uint64
+ amount *big.Int
+ gasLimit uint64
+ gasPrice *big.Int
+ data []byte
+ metadata []byte
+ metadataLimit *big.Int
+ checkNonce bool
+ }
+
+ func CreateNewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data, metadata []byte, metadataLimit *big.Int, checkNonce bool) Message {
return Message{
- from: from,
- to: to,
- nonce: nonce,
- amount: amount,
- gasLimit: gasLimit,
- gasPrice: gasPrice,
- data: data,
- checkNonce: checkNonce,
+ from: from,
+ to: to,
+ nonce: nonce,
+ amount: amount,
+ gasLimit: gasLimit,
+ gasPrice: gasPrice,
+ data: data,
+ metadata: metadata,
+ metadataLimit: metadataLimit,
+ checkNonce: checkNonce,
}
}
- func (m Message) From() common.Address { return m.from }
- func (m Message) To() *common.Address { return m.to }
- func (m Message) GasPrice() *big.Int { return m.gasPrice }
- func (m Message) Value() *big.Int { return m.amount }
- func (m Message) Gas() uint64 { return m.gasLimit }
- func (m Message) Nonce() uint64 { return m.nonce }
- func (m Message) Data() []byte { return m.data }
- func (m Message) CheckNonce() bool { return m.checkNonce }
+ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice *big.Int, data []byte, checkNonce bool) Message {
+ return CreateNewMessage(from, to, nonce, amount, gasLimit, gasPrice, data, []byte{}, big.NewInt(0), checkNonce)
+ }
+
+ func (m Message) From() common.Address { return m.from }
+ func (m Message) To() *common.Address { return m.to }
+ func (m Message) GasPrice() *big.Int { return m.gasPrice }
+ func (m Message) Value() *big.Int { return m.amount }
+ func (m Message) Gas() uint64 { return m.gasLimit }
+ func (m Message) Nonce() uint64 { return m.nonce }
+ func (m Message) Data() []byte { return m.data }
+ func (m Message) Metadata() []byte { return m.metadata }
+ func (m Message) MetadataLimit() *big.Int { return m.metadataLimit }
+ func (m Message) CheckNonce() bool { return m.checkNonce }
core/types/transaction_signing.go
Support for new transactions(Iolite ) and old(Ethereum ) ones
diff --git a/core/types/transaction_signing.go b/core/types/transaction_signing.go
index dfc84fd..9053222 100644
--- a/core/types/transaction_signing.go
+++ b/core/types/transaction_signing.go
@@ -153,6 +153,17 @@ func (s EIP155Signer) SignatureValues(tx *Transaction, sig []byte) (R, S, V *big
// Hash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
+ if tx.IsOld() {
+ return rlpHash([]interface{}{
+ tx.data.AccountNonce,
+ tx.data.Price,
+ tx.data.GasLimit,
+ tx.data.Recipient,
+ tx.data.Amount,
+ tx.data.Payload,
+ s.chainId, uint(0), uint(0),
+ })
+ }
return rlpHash([]interface{}{
tx.data.AccountNonce,
tx.data.Price,
@@ -160,6 +171,8 @@ func (s EIP155Signer) Hash(tx *Transaction) common.Hash {
tx.data.Recipient,
tx.data.Amount,
tx.data.Payload,
+ tx.data.Metadata,
+ tx.data.MetadataLimit,
s.chainId, uint(0), uint(0),
})
}
@@ -205,6 +218,16 @@ func (fs FrontierSigner) SignatureValues(tx *Transaction, sig []byte) (r, s, v *
// Hash returns the hash to be signed by the sender.
// It does not uniquely identify the transaction.
func (fs FrontierSigner) Hash(tx *Transaction) common.Hash {
+ if tx.IsOld() {
+ return rlpHash([]interface{}{
+ tx.data.AccountNonce,
+ tx.data.Price,
+ tx.data.GasLimit,
+ tx.data.Recipient,
+ tx.data.Amount,
+ tx.data.Payload,
+ })
+ }
return rlpHash([]interface{}{
tx.data.AccountNonce,
tx.data.Price,
@@ -212,6 +235,8 @@ func (fs FrontierSigner) Hash(tx *Transaction) common.Hash {
tx.data.Recipient,
tx.data.Amount,
tx.data.Payload,
+ tx.data.Metadata,
+ tx.data.MetadataLimit,
})
}
transaction_signing_test.go
diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go
index 689fc38..2e1b492 100644
--- a/core/types/transaction_signing_test.go
+++ b/core/types/transaction_signing_test.go
@@ -94,12 +94,13 @@ func TestEIP155SigningVitalik(t *testing.T) {
} {
signer := NewEIP155Signer(big.NewInt(1))
- var tx *Transaction
- err := rlp.DecodeBytes(common.Hex2Bytes(test.txRlp), &tx)
+ var oldtx *OldTransaction
+ err := rlp.DecodeBytes(common.Hex2Bytes(test.txRlp), &oldtx)
if err != nil {
t.Errorf("%d: %v", i, err)
continue
}
+ tx := oldtx.AsTransaction()
from, err := Sender(signer, tx)
if err != nil {
diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go
index d1861b1..caa7e00 100644
--- a/core/types/transaction_test.go
+++ b/core/types/transaction_test.go
@@ -31,21 +31,21 @@ import (
// The values in those tests are from the Transaction Tests
// at github.com/ethereum/tests.
var (
- emptyTx = NewTransaction(
+ emptyTx = CreateOldTransaction(
0,
common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
big.NewInt(0), 0, big.NewInt(0),
nil,
- )
+ ).AsTransaction()
- rightvrsTx, _ = NewTransaction(
+ rightvrsTx, _ = CreateOldTransaction(
3,
common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b"),
big.NewInt(10),
2000,
big.NewInt(1),
common.FromHex("5544"),
- ).WithSignature(
+ ).AsTransaction().WithSignature(
HomesteadSigner{},
common.Hex2Bytes("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a301"),
)
Support for the modified method signature
diff --git a/eth/api_tracer.go b/eth/api_tracer.go
index 07c4457..78e6f92 100644
--- a/eth/api_tracer.go
+++ b/eth/api_tracer.go
@@ -446,7 +446,7 @@ func (api *PrivateDebugAPI) traceBlock(ctx context.Context, block *types.Block,
vmctx := core.NewEVMContext(msg, block.Header(), api.eth.blockchain, nil)
vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{})
- if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
+ if _, _, _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(msg.Gas())); err != nil {
failed = err
break
}
@@ -588,7 +588,7 @@ func (api *PrivateDebugAPI) traceTx(ctx context.Context, message core.Message, v
// Run the transaction with tracing enabled.
vmenv := vm.NewEVM(vmctx, statedb, api.config, vm.Config{Debug: true, Tracer: tracer})
- ret, gas, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
+ _, ret, gas, _, failed, err := core.ApplyMessage(vmenv, message, new(core.GasPool).AddGas(message.Gas()))
if err != nil {
return nil, fmt.Errorf("tracing failed: %v", err)
}
@@ -637,7 +637,7 @@ func (api *PrivateDebugAPI) computeTxEnv(blockHash common.Hash, txIndex int, ree
}
// Not yet the searched for transaction, execute on top of the current state
vmenv := vm.NewEVM(context, statedb, api.config, vm.Config{})
- if _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
+ if _, _, _, _, _, err := core.ApplyMessage(vmenv, msg, new(core.GasPool).AddGas(tx.Gas())); err != nil {
return nil, vm.Context{}, nil, fmt.Errorf("tx %x failed: %v", tx.Hash(), err)
}
statedb.DeleteSuicides()
Support for the modified method signature
additional logs
Support metadata fields
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index e2bfbaf..bfa6b31 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -604,12 +604,14 @@ func (s *PublicBlockChainAPI) GetStorageAt(ctx context.Context, address common.A
// CallArgs represents the arguments for a call.
type CallArgs struct {
- From common.Address `json:"from"`
- To *common.Address `json:"to"`
- Gas hexutil.Uint64 `json:"gas"`
- GasPrice hexutil.Big `json:"gasPrice"`
- Value hexutil.Big `json:"value"`
- Data hexutil.Bytes `json:"data"`
+ From common.Address `json:"from"`
+ To *common.Address `json:"to"`
+ Gas hexutil.Uint64 `json:"gas"`
+ GasPrice hexutil.Big `json:"gasPrice"`
+ Value hexutil.Big `json:"value"`
+ Data hexutil.Bytes `json:"data"`
+ Metadata hexutil.Bytes `json:"metadata"`
+ MetadataLimit hexutil.Big `json:"metadataLimit"`
}
func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr rpc.BlockNumber, vmCfg vm.Config, timeout time.Duration) ([]byte, uint64, bool, error) {
@@ -638,7 +640,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
}
// Create new call message
- msg := types.NewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, false)
+ msg := types.CreateNewMessage(addr, args.To, 0, args.Value.ToInt(), gas, gasPrice, args.Data, args.Metadata, args.MetadataLimit.ToInt(), false)
// Setup context so it may be cancelled the call has completed
// or, in case of unmetered gas, setup a context with a timeout.
@@ -667,7 +669,7 @@ func (s *PublicBlockChainAPI) doCall(ctx context.Context, args CallArgs, blockNr
// Setup the gas pool (also for unmetered requests)
// and apply the message.
gp := new(core.GasPool).AddGas(math.MaxUint64)
- res, gas, failed, err := core.ApplyMessage(evm, msg, gp)
+ _, res, gas, _, failed, err := core.ApplyMessage(evm, msg, gp)
if err := vmError(); err != nil {
return nil, 0, false, err
}
@@ -724,6 +726,7 @@ func (s *PublicBlockChainAPI) EstimateGas(ctx context.Context, args CallArgs) (h
// Reject the transaction as invalid if it still fails at the highest allowance
if hi == cap {
if !executable(hi) {
+ log.Iolite("EstimateGas", "gas required exceeds allowance or always failing transaction", args.Data)
return 0, fmt.Errorf("gas required exceeds allowance or always failing transaction")
}
}
@@ -858,6 +861,9 @@ type RPCTransaction struct {
GasPrice *hexutil.Big `json:"gasPrice"`
Hash common.Hash `json:"hash"`
Input hexutil.Bytes `json:"input"`
+ Metadata hexutil.Bytes `json:"metadata"`
+ MetadataLimit *hexutil.Big `json:"metadataLimit"`
+ IsOld hexutil.Uint `json:"isOld"`
Nonce hexutil.Uint64 `json:"nonce"`
To *common.Address `json:"to"`
TransactionIndex hexutil.Uint `json:"transactionIndex"`
@@ -877,18 +883,26 @@ func newRPCTransaction(tx *types.Transaction, blockHash common.Hash, blockNumber
from, _ := types.Sender(signer, tx)
v, r, s := tx.RawSignatureValues()
+ isOld := 0
+ if tx.IsOld() {
+ isOld = 1
+ }
+
result := &RPCTransaction{
- From: from,
- Gas: hexutil.Uint64(tx.Gas()),
- GasPrice: (*hexutil.Big)(tx.GasPrice()),
- Hash: tx.Hash(),
- Input: hexutil.Bytes(tx.Data()),
- Nonce: hexutil.Uint64(tx.Nonce()),
- To: tx.To(),
- Value: (*hexutil.Big)(tx.Value()),
- V: (*hexutil.Big)(v),
- R: (*hexutil.Big)(r),
- S: (*hexutil.Big)(s),
+ From: from,
+ Gas: hexutil.Uint64(tx.Gas()),
+ GasPrice: (*hexutil.Big)(tx.GasPrice()),
+ Hash: tx.Hash(),
+ Input: hexutil.Bytes(tx.Data()),
+ Metadata: hexutil.Bytes(tx.Metadata()),
+ MetadataLimit: (*hexutil.Big)(tx.MetadataLimit()),
+ IsOld: hexutil.Uint(isOld),
+ Nonce: hexutil.Uint64(tx.Nonce()),
+ To: tx.To(),
+ Value: (*hexutil.Big)(tx.Value()),
+ V: (*hexutil.Big)(v),
+ R: (*hexutil.Big)(r),
+ S: (*hexutil.Big)(s),
}
if blockHash != (common.Hash{}) {
result.BlockHash = blockHash
@@ -1018,6 +1032,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionByHash(ctx context.Context, has
}
// GetRawTransactionByHash returns the bytes of the transaction for the given hash.
+ // iolite.TODO fix for OldTransaction and NewIoliteTransaction
func (s *PublicTransactionPoolAPI) GetRawTransactionByHash(ctx context.Context, hash common.Hash) (hexutil.Bytes, error) {
var tx *types.Transaction
@@ -1038,6 +1053,7 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
if tx == nil {
return nil, nil
}
+
receipts, err := s.b.GetReceipts(ctx, blockHash)
if err != nil {
return nil, err
@@ -1065,6 +1081,8 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
"contractAddress": nil,
"logs": receipt.Logs,
"logsBloom": receipt.Bloom,
+ "metaLogs": receipt.MetaLogs,
+ "metaGasUsed": receipt.MetaGasUsed,
}
// Assign receipt status or post state.
@@ -1076,6 +1094,9 @@ func (s *PublicTransactionPoolAPI) GetTransactionReceipt(ctx context.Context, ha
if receipt.Logs == nil {
fields["logs"] = [][]*types.Log{}
}
+
+ // iolite.TODO: allow metaLogs to be nil?
+
// If the ContractAddress is 20 0x0 bytes, assume it is not a contract creation
if receipt.ContractAddress != (common.Address{}) {
fields["contractAddress"] = receipt.ContractAddress
@@ -1112,6 +1133,7 @@ type SendTxArgs struct {
// newer name and should be preferred by clients.
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input"`
+ // iolite.TODO add metadata support
}
// setDefaults is a helper function that fills in default values for unspecified tx fields.
@@ -1170,6 +1192,7 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
// submitTransaction is a helper function that submits tx to txPool and logs a message.
func submitTransaction(ctx context.Context, b Backend, tx *types.Transaction) (common.Hash, error) {
+ log.Iolite("submitTransaction", "hash", tx.Hash().Hex())
if err := b.SendTx(ctx, tx); err != nil {
return common.Hash{}, err
}
@@ -1228,9 +1251,19 @@ func (s *PublicTransactionPoolAPI) SendTransaction(ctx context.Context, args Sen
// The sender is responsible for signing the transaction and using the correct nonce.
func (s *PublicTransactionPoolAPI) SendRawTransaction(ctx context.Context, encodedTx hexutil.Bytes) (common.Hash, error) {
tx := new(types.Transaction)
- if err := rlp.DecodeBytes(encodedTx, tx); err != nil {
- return common.Hash{}, err
+ oldtx := new(types.OldTransaction)
+ newtx := new(types.NewIoliteTransaction)
+
+ if err := rlp.DecodeBytes(encodedTx, oldtx); err != nil {
+ if err := rlp.DecodeBytes(encodedTx, newtx); err != nil {
+ return common.Hash{}, err
+ } else {
+ tx = newtx.AsTransaction()
+ }
+ } else {
+ tx = oldtx.AsTransaction()
}
+ log.Iolite("SendRawTransaction", "fullhash", tx.Hash().Hex(), "metadata", hexutil.Encode(tx.Metadata()))
return submitTransaction(ctx, s.b, tx)
}
Support for the modified method signature
diff --git a/les/odr_test.go b/les/odr_test.go
index 88e121c..fbe411c 100644
--- a/les/odr_test.go
+++ b/les/odr_test.go
@@ -135,7 +135,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
//vmenv := core.NewEnv(statedb, config, bc, msg, header, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
- ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
+ _, ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...)
}
} else {
@@ -146,7 +146,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
context := core.NewEVMContext(msg, header, lc, nil)
vmenv := vm.NewEVM(context, state, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
- ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
+ _, ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
if state.Error() == nil {
res = append(res, ret...)
}
Support for the modified method signature
diff --git a/light/odr_test.go b/light/odr_test.go
index d3f9374..7db343e 100644
--- a/light/odr_test.go
+++ b/light/odr_test.go
@@ -180,7 +180,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
context := core.NewEVMContext(msg, header, chain, nil)
vmenv := vm.NewEVM(context, st, config, vm.Config{})
gp := new(core.GasPool).AddGas(math.MaxUint64)
- ret, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
+ _, ret, _, _, _, _ := core.ApplyMessage(vmenv, msg, gp)
res = append(res, ret...)
if st.Error() != nil {
return res, st.Error()
diff --git a/light/txpool.go b/light/txpool.go
index ca41490..baab5ec 100644
--- a/light/txpool.go
+++ b/light/txpool.go
@@ -23,6 +23,7 @@ import (
"time"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
@@ -437,6 +438,7 @@ func (self *TxPool) Add(ctx context.Context, tx *types.Transaction) error {
//fmt.Println("Send", tx.Hash())
self.relay.Send(types.Transactions{tx})
+ log.Iolite("Light: Add to txpool", "data", hexutil.Encode(data))
self.chainDb.Put(tx.Hash().Bytes(), data)
return nil
}
diff --git a/log/format.go b/log/format.go
index 0b07abb..bd3676f 100644
--- a/log/format.go
+++ b/log/format.go
@@ -96,6 +96,8 @@ func TerminalFormat(usecolor bool) Format {
color = 33
case LvlInfo:
color = 32
+ case LvlIolite:
+ color = 95
case LvlDebug:
color = 36
case LvlTrace:
diff --git a/log/logger.go b/log/logger.go
index 15c83a9..1657a67 100644
--- a/log/logger.go
+++ b/log/logger.go
@@ -20,6 +20,7 @@ const (
LvlError
LvlWarn
LvlInfo
+ LvlIolite
LvlDebug
LvlTrace
)
@@ -31,6 +32,8 @@ func (l Lvl) AlignedString() string {
return "TRACE"
case LvlDebug:
return "DEBUG"
+ case LvlIolite:
+ return "ILT "
case LvlInfo:
return "INFO "
case LvlWarn:
@@ -51,6 +54,8 @@ func (l Lvl) String() string {
return "trce"
case LvlDebug:
return "dbug"
+ case LvlIolite:
+ return "ilt"
case LvlInfo:
return "info"
case LvlWarn:
@@ -72,6 +77,8 @@ func LvlFromString(lvlString string) (Lvl, error) {
return LvlTrace, nil
case "debug", "dbug":
return LvlDebug, nil
+ case "iolite", "ilt":
+ return LvlIolite, nil
case "info":
return LvlInfo, nil
case "warn":
@@ -115,6 +122,7 @@ type Logger interface {
// Log a message at the given level with context key/value pairs
Trace(msg string, ctx ...interface{})
Debug(msg string, ctx ...interface{})
+ Iolite(msg string, ctx ...interface{})
Info(msg string, ctx ...interface{})
Warn(msg string, ctx ...interface{})
Error(msg string, ctx ...interface{})
@@ -163,6 +171,10 @@ func (l *logger) Debug(msg string, ctx ...interface{}) {
l.write(msg, LvlDebug, ctx)
}
+ func (l *logger) Iolite(msg string, ctx ...interface{}) {
+ l.write(msg, LvlIolite, ctx)
+ }
+
func (l *logger) Info(msg string, ctx ...interface{}) {
l.write(msg, LvlInfo, ctx)
}
diff --git a/log/root.go b/log/root.go
index 71b8cef..1c62287 100644
--- a/log/root.go
+++ b/log/root.go
@@ -39,6 +39,11 @@ func Debug(msg string, ctx ...interface{}) {
root.write(msg, LvlDebug, ctx)
}
+ // Iolite is a convenient alias for Root().Iolite
+ func Iolite(msg string, ctx ...interface{}) {
+ root.write(msg, LvlIolite, ctx)
+ }
+
// Info is a convenient alias for Root().Info
func Info(msg string, ctx ...interface{}) {
root.write(msg, LvlInfo, ctx)
diff --git a/log/syslog.go b/log/syslog.go
index 71a17b3..62e67c7 100644
--- a/log/syslog.go
+++ b/log/syslog.go
@@ -36,6 +36,8 @@ func sharedSyslog(fmtr Format, sysWr *syslog.Writer, err error) (Handler, error)
syslogFn = sysWr.Warning
case LvlInfo:
syslogFn = sysWr.Info
+ case LvlIolite:
+ syslogFn = sysWr.Info
case LvlDebug:
syslogFn = sysWr.Debug
case LvlTrace:
diff --git a/node/node.go b/node/node.go
index b02aecf..5b1fa1f 100644
--- a/node/node.go
+++ b/node/node.go
@@ -287,7 +287,7 @@ func (n *Node) startInProc(apis []rpc.API) error {
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
return err
}
- n.log.Debug("InProc registered", "service", api.Service, "namespace", api.Namespace)
+ n.log.Info("InProc registered", "service", api.Service, "namespace", api.Namespace)
}
n.inprocHandler = handler
return nil
Support for the modified method signature
diff --git a/tests/state_test_util.go b/tests/state_test_util.go
index 3b761bd..faf62a8 100644
--- a/tests/state_test_util.go
+++ b/tests/state_test_util.go
@@ -141,7 +141,7 @@ func (t *StateTest) Run(subtest StateSubtest, vmconfig vm.Config) (*state.StateD
gaspool := new(core.GasPool)
gaspool.AddGas(block.GasLimit())
snapshot := statedb.Snapshot()
- if _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil {
+ if _, _, _, _, _, err := core.ApplyMessage(evm, msg, gaspool); err != nil {
statedb.RevertToSnapshot(snapshot)
}
if logs := rlpHash(statedb.Logs()); logs != common.Hash(post.Logs) {