aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-05-22 23:35:26 +0800
committerobscuren <geffobscura@gmail.com>2014-05-22 23:35:26 +0800
commit230aafbf66ba747fb3796810adf3b1680f368e73 (patch)
tree66aff77b70bf083cc1a7ce32ab108d39d82ac95d /ethchain
parent14787ac148274a84478aa06fd985407b9241cd50 (diff)
downloadgo-tangerine-230aafbf66ba747fb3796810adf3b1680f368e73.tar
go-tangerine-230aafbf66ba747fb3796810adf3b1680f368e73.tar.gz
go-tangerine-230aafbf66ba747fb3796810adf3b1680f368e73.tar.bz2
go-tangerine-230aafbf66ba747fb3796810adf3b1680f368e73.tar.lz
go-tangerine-230aafbf66ba747fb3796810adf3b1680f368e73.tar.xz
go-tangerine-230aafbf66ba747fb3796810adf3b1680f368e73.tar.zst
go-tangerine-230aafbf66ba747fb3796810adf3b1680f368e73.zip
Working on interop
* Receipts after each transaction * Fee structure * Applying fees to miners
Diffstat (limited to 'ethchain')
-rw-r--r--ethchain/block.go74
-rw-r--r--ethchain/block_chain.go21
-rw-r--r--ethchain/genesis.go2
-rw-r--r--ethchain/state_manager.go42
-rw-r--r--ethchain/state_object.go2
-rw-r--r--ethchain/transaction.go108
-rw-r--r--ethchain/transaction_pool.go18
-rw-r--r--ethchain/vm.go1
8 files changed, 191 insertions, 77 deletions
diff --git a/ethchain/block.go b/ethchain/block.go
index 3401632b1..c846516f4 100644
--- a/ethchain/block.go
+++ b/ethchain/block.go
@@ -55,6 +55,7 @@ type Block struct {
Nonce []byte
// List of transactions and/or contracts
transactions []*Transaction
+ receipts []*Receipt
TxSha []byte
}
@@ -84,24 +85,20 @@ func CreateBlock(root interface{},
base []byte,
Difficulty *big.Int,
Nonce []byte,
- extra string,
- txes []*Transaction) *Block {
+ extra string) *Block {
block := &Block{
- // Slice of transactions to include in this block
- transactions: txes,
- PrevHash: prevHash,
- Coinbase: base,
- Difficulty: Difficulty,
- Nonce: Nonce,
- Time: time.Now().Unix(),
- Extra: extra,
- UncleSha: EmptyShaList,
- GasUsed: new(big.Int),
- MinGasPrice: new(big.Int),
- GasLimit: new(big.Int),
+ PrevHash: prevHash,
+ Coinbase: base,
+ Difficulty: Difficulty,
+ Nonce: Nonce,
+ Time: time.Now().Unix(),
+ Extra: extra,
+ UncleSha: EmptyShaList,
+ GasUsed: new(big.Int),
+ MinGasPrice: new(big.Int),
+ GasLimit: new(big.Int),
}
- block.SetTransactions(txes)
block.SetUncles([]*Block{})
block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, root))
@@ -115,7 +112,10 @@ func (block *Block) Hash() []byte {
}
func (block *Block) HashNoNonce() []byte {
- return ethutil.Sha3Bin(ethutil.Encode([]interface{}{block.PrevHash, block.UncleSha, block.Coinbase, block.state.trie.Root, block.TxSha, block.Difficulty, block.Time, block.Extra}))
+ return ethutil.Sha3Bin(ethutil.Encode([]interface{}{block.PrevHash,
+ block.UncleSha, block.Coinbase, block.state.trie.Root,
+ block.TxSha, block.Difficulty, block.Number, block.MinGasPrice,
+ block.GasLimit, block.GasUsed, block.Time, block.Extra}))
}
func (block *Block) State() *State {
@@ -172,15 +172,15 @@ func (block *Block) Undo() {
}
/////// Block Encoding
-func (block *Block) rlpTxs() interface{} {
+func (block *Block) rlpReceipts() interface{} {
// Marshal the transactions of this block
- encTx := make([]interface{}, len(block.transactions))
- for i, tx := range block.transactions {
+ encR := make([]interface{}, len(block.receipts))
+ for i, r := range block.receipts {
// Cast it to a string (safe)
- encTx[i] = tx.RlpData()
+ encR[i] = r.RlpData()
}
- return encTx
+ return encR
}
func (block *Block) rlpUncles() interface{} {
@@ -201,7 +201,12 @@ func (block *Block) SetUncles(uncles []*Block) {
block.UncleSha = ethutil.Sha3Bin(ethutil.Encode(block.rlpUncles()))
}
-func (block *Block) SetTransactions(txs []*Transaction) {
+func (self *Block) SetReceipts(receipts []*Receipt, txs []*Transaction) {
+ self.receipts = receipts
+ self.setTransactions(txs)
+}
+
+func (block *Block) setTransactions(txs []*Transaction) {
block.transactions = txs
trie := ethutil.NewTrie(ethutil.Config.Db, "")
@@ -221,7 +226,7 @@ func (block *Block) SetTransactions(txs []*Transaction) {
}
func (block *Block) Value() *ethutil.Value {
- return ethutil.NewValue([]interface{}{block.header(), block.rlpTxs(), block.rlpUncles()})
+ return ethutil.NewValue([]interface{}{block.header(), block.rlpReceipts(), block.rlpUncles()})
}
func (block *Block) RlpEncode() []byte {
@@ -245,6 +250,7 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
block.TxSha = header.Get(4).Bytes()
block.Difficulty = header.Get(5).BigInt()
block.Number = header.Get(6).BigInt()
+ //fmt.Printf("#%v : %x\n", block.Number, block.Coinbase)
block.MinGasPrice = header.Get(7).BigInt()
block.GasLimit = header.Get(8).BigInt()
block.GasUsed = header.Get(9).BigInt()
@@ -255,12 +261,13 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) {
// Tx list might be empty if this is an uncle. Uncles only have their
// header set.
if decoder.Get(1).IsNil() == false { // Yes explicitness
- txes := decoder.Get(1)
- block.transactions = make([]*Transaction, txes.Len())
- for i := 0; i < txes.Len(); i++ {
- tx := NewTransactionFromValue(txes.Get(i))
-
- block.transactions[i] = tx
+ receipts := decoder.Get(1)
+ block.transactions = make([]*Transaction, receipts.Len())
+ block.receipts = make([]*Receipt, receipts.Len())
+ for i := 0; i < receipts.Len(); i++ {
+ receipt := NewRecieptFromValue(receipts.Get(i))
+ block.transactions[i] = receipt.Tx
+ block.receipts[i] = receipt
}
}
@@ -299,6 +306,10 @@ func (block *Block) GetRoot() interface{} {
return block.state.trie.Root
}
+func (self *Block) Receipts() []*Receipt {
+ return self.receipts
+}
+
func (block *Block) header() []interface{} {
return []interface{}{
// Sha of the previous block
@@ -346,6 +357,7 @@ func (block *Block) String() string {
Time: %v
Extra: %v
Nonce: %x
+ NumTx: %v
`,
block.Hash(),
block.PrevHash,
@@ -360,5 +372,7 @@ func (block *Block) String() string {
block.GasUsed,
block.Time,
block.Extra,
- block.Nonce)
+ block.Nonce,
+ len(block.transactions),
+ )
}
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index b72c78cdb..b45d254b5 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -36,7 +36,7 @@ func (bc *BlockChain) Genesis() *Block {
return bc.genesisBlock
}
-func (bc *BlockChain) NewBlock(coinbase []byte, txs []*Transaction) *Block {
+func (bc *BlockChain) NewBlock(coinbase []byte) *Block {
var root interface{}
var lastBlockTime int64
hash := ZeroHash256
@@ -53,8 +53,7 @@ func (bc *BlockChain) NewBlock(coinbase []byte, txs []*Transaction) *Block {
coinbase,
ethutil.BigPow(2, 32),
nil,
- "",
- txs)
+ "")
if bc.CurrentBlock != nil {
var mul *big.Int
@@ -272,16 +271,18 @@ func (bc *BlockChain) GetChain(hash []byte, amount int) []*Block {
func AddTestNetFunds(block *Block) {
for _, addr := range []string{
- "8a40bfaa73256b60764c1bf40675a99083efb075", // Gavin
- "e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey
- "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit
- "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex
- "2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran
- "cd2a3d9f938e13cd947ec05abc7fe734df8dd826", // Roman
+ "8a40bfaa73256b60764c1bf40675a99083efb075",
+ "e4157b34ea9615cfbde6b4fda419828124b70c78",
+ "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df",
+ "6c386a4b26f73c802f34673f7248bb118f97424a",
+ "cd2a3d9f938e13cd947ec05abc7fe734df8dd826",
+ "2ef47100e0787b915105fd5e3f4ff6752079d5cb",
+ "e6716f9544a56c530d868e4bfbacb172315bdead",
+ "1a26338f0d905e295fccb71fa9ea849ffa12aaf4",
} {
codedAddr := ethutil.FromHex(addr)
account := block.state.GetAccount(codedAddr)
- account.Amount = ethutil.BigPow(2, 200)
+ account.Amount = ethutil.Big("1606938044258990275541962092341162602522202993782792835301376") //ethutil.BigPow(2, 200)
block.state.UpdateStateObject(account)
}
log.Printf("%x\n", block.RlpEncode())
diff --git a/ethchain/genesis.go b/ethchain/genesis.go
index b8f9f865a..359c47c26 100644
--- a/ethchain/genesis.go
+++ b/ethchain/genesis.go
@@ -23,7 +23,7 @@ var GenesisHeader = []interface{}{
// Root state
"",
// tx sha
- ZeroHash256,
+ "",
// Difficulty
ethutil.BigPow(2, 22),
// Number
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 8b56d65bb..3b67381ea 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -97,40 +97,56 @@ func (sm *StateManager) MakeContract(state *State, tx *Transaction) *StateObject
// Apply transactions uses the transaction passed to it and applies them onto
// the current processing state.
-func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Transaction) {
+func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Transaction) ([]*Receipt, []*Transaction) {
// Process each transaction/contract
+ var receipts []*Receipt
+ var validTxs []*Transaction
+ totalUsedGas := big.NewInt(0)
for _, tx := range txs {
- sm.ApplyTransaction(state, block, tx)
+ usedGas, err := sm.ApplyTransaction(state, block, tx)
+ if err != nil {
+ ethutil.Config.Log.Infoln(err)
+ continue
+ }
+
+ accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, usedGas))
+ receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative}
+
+ receipts = append(receipts, receipt)
+ validTxs = append(validTxs, tx)
}
+
+ return receipts, txs
}
-func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) error {
+func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transaction) (*big.Int, error) {
// If there's no recipient, it's a contract
// Check if this is a contract creation traction and if so
// create a contract of this tx.
+ totalGasUsed := big.NewInt(0)
if tx.IsContract() {
- err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
+ err := sm.Ethereum.TxPool().ProcessTransaction(tx, state, false)
if err == nil {
contract := sm.MakeContract(state, tx)
if contract != nil {
sm.EvalScript(state, contract.Init(), contract, tx, block)
} else {
- return fmt.Errorf("[STATE] Unable to create contract")
+ return nil, fmt.Errorf("[STATE] Unable to create contract")
}
} else {
- return fmt.Errorf("[STATE] contract create:", err)
+ return nil, fmt.Errorf("[STATE] contract create:", err)
}
} else {
- err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false)
+ err := sm.Ethereum.TxPool().ProcessTransaction(tx, state, false)
contract := state.GetStateObject(tx.Recipient)
if err == nil && contract != nil && len(contract.Script()) > 0 {
sm.EvalScript(state, contract.Script(), contract, tx, block)
} else if err != nil {
- return fmt.Errorf("[STATE] process:", err)
+ return nil, fmt.Errorf("[STATE] process:", err)
}
}
- return nil
+ return totalGasUsed, nil
}
func (sm *StateManager) Process(block *Block, dontReact bool) error {
@@ -276,6 +292,14 @@ func CalculateBlockReward(block *Block, uncleLength int) *big.Int {
for i := 0; i < uncleLength; i++ {
base.Add(base, UncleInclusionReward)
}
+
+ lastCumulGasUsed := big.NewInt(0)
+ for _, r := range block.Receipts() {
+ usedGas := new(big.Int).Sub(r.CumulativeGasUsed, lastCumulGasUsed)
+ usedGas.Add(usedGas, r.Tx.GasPrice)
+ base.Add(base, usedGas)
+ }
+
return base.Add(base, BlockReward)
}
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
index 8e059f334..4046054db 100644
--- a/ethchain/state_object.go
+++ b/ethchain/state_object.go
@@ -146,7 +146,7 @@ func (c *StateObject) RlpEncode() []byte {
if c.state != nil {
root = c.state.trie.Root
} else {
- root = ZeroHash256
+ root = ""
}
return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, ethutil.Sha3Bin(c.script)})
diff --git a/ethchain/transaction.go b/ethchain/transaction.go
index bd7a0e424..16ea312c0 100644
--- a/ethchain/transaction.go
+++ b/ethchain/transaction.go
@@ -1,6 +1,7 @@
package ethchain
import (
+ "fmt"
"github.com/ethereum/eth-go/ethutil"
"github.com/obscuren/secp256k1-go"
"math/big"
@@ -46,11 +47,13 @@ func NewTransactionFromValue(val *ethutil.Value) *Transaction {
}
func (tx *Transaction) Hash() []byte {
- data := []interface{}{tx.Nonce, tx.Value, tx.GasPrice, tx.Gas, tx.Recipient, tx.Data}
+ data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data}
- if tx.contractCreation {
- data = append(data, tx.Init)
- }
+ /*
+ if tx.contractCreation {
+ data = append(data, tx.Init)
+ }
+ */
return ethutil.Sha3Bin(ethutil.NewValue(data).Encode())
}
@@ -138,18 +141,87 @@ func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) {
tx.Recipient = decoder.Get(3).Bytes()
tx.Value = decoder.Get(4).BigInt()
tx.Data = decoder.Get(5).Bytes()
-
- // If the list is of length 10 it's a contract creation tx
- if decoder.Len() == 10 {
- tx.contractCreation = true
- tx.Init = decoder.Get(6).Bytes()
-
- tx.v = byte(decoder.Get(7).Uint())
- tx.r = decoder.Get(8).Bytes()
- tx.s = decoder.Get(9).Bytes()
- } else {
- tx.v = byte(decoder.Get(6).Uint())
- tx.r = decoder.Get(7).Bytes()
- tx.s = decoder.Get(8).Bytes()
- }
+ tx.v = byte(decoder.Get(6).Uint())
+ tx.r = decoder.Get(7).Bytes()
+ tx.s = decoder.Get(8).Bytes()
+
+ /*
+ // If the list is of length 10 it's a contract creation tx
+ if decoder.Len() == 10 {
+ tx.contractCreation = true
+ tx.Init = decoder.Get(6).Bytes()
+
+ tx.v = byte(decoder.Get(7).Uint())
+ tx.r = decoder.Get(8).Bytes()
+ tx.s = decoder.Get(9).Bytes()
+ } else {
+ tx.v = byte(decoder.Get(6).Uint())
+ tx.r = decoder.Get(7).Bytes()
+ tx.s = decoder.Get(8).Bytes()
+ }
+ */
+}
+
+func (tx *Transaction) String() string {
+ return fmt.Sprintf(`
+ TX(%x)
+ Contract: %v
+ From: %x
+ Nonce: %v
+ GasPrice: %v
+ Gas: %v
+ To: %x
+ Value: %v
+ Data: 0x%x
+ V: 0x%x
+ R: 0x%x
+ S: 0x%x
+ `,
+ tx.Hash(),
+ len(tx.Recipient) > 1,
+ tx.Sender(),
+ tx.Nonce,
+ tx.GasPrice,
+ tx.Gas,
+ tx.Recipient,
+ tx.Value,
+ tx.Data,
+ tx.v,
+ tx.r,
+ tx.s)
+}
+
+type Receipt struct {
+ Tx *Transaction
+ PostState []byte
+ CumulativeGasUsed *big.Int
+}
+
+func NewRecieptFromValue(val *ethutil.Value) *Receipt {
+ r := &Receipt{}
+ r.RlpValueDecode(val)
+
+ return r
+}
+
+func (self *Receipt) RlpValueDecode(decoder *ethutil.Value) {
+ self.Tx = NewTransactionFromValue(decoder.Get(0))
+ self.PostState = decoder.Get(1).Bytes()
+ self.CumulativeGasUsed = decoder.Get(2).BigInt()
+}
+
+func (self *Receipt) RlpData() interface{} {
+ return []interface{}{self.Tx.RlpData(), self.PostState, self.CumulativeGasUsed}
+}
+
+func (self *Receipt) String() string {
+ return fmt.Sprintf(`
+ R
+ Tx:[ %v]
+ PostState: 0x%x
+ CumulativeGasUsed: %v
+ `,
+ self.Tx,
+ self.PostState,
+ self.CumulativeGasUsed)
}
diff --git a/ethchain/transaction_pool.go b/ethchain/transaction_pool.go
index dcf0c4c31..ee026ffdd 100644
--- a/ethchain/transaction_pool.go
+++ b/ethchain/transaction_pool.go
@@ -91,15 +91,15 @@ func (pool *TxPool) addTransaction(tx *Transaction) {
// Process transaction validates the Tx and processes funds from the
// sender to the recipient.
-func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract bool) (err error) {
+func (pool *TxPool) ProcessTransaction(tx *Transaction, state *State, toContract bool) (err error) {
defer func() {
if r := recover(); r != nil {
- log.Println(r)
+ ethutil.Config.Log.Infoln(r)
err = fmt.Errorf("%v", r)
}
}()
// Get the sender
- sender := block.state.GetAccount(tx.Sender())
+ sender := state.GetAccount(tx.Sender())
if sender.Nonce != tx.Nonce {
return fmt.Errorf("[TXPL] Invalid account nonce, state nonce is %d transaction nonce is %d instead", sender.Nonce, tx.Nonce)
@@ -107,19 +107,21 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
// Make sure there's enough in the sender's account. Having insufficient
// funds won't invalidate this transaction but simple ignores it.
- totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
+ //totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
+ totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(tx.Gas, tx.GasPrice))
if sender.Amount.Cmp(totAmount) < 0 {
return fmt.Errorf("[TXPL] Insufficient amount in sender's (%x) account", tx.Sender())
}
+ //fmt.Println(tx)
// Get the receiver
- receiver := block.state.GetAccount(tx.Recipient)
+ receiver := state.GetAccount(tx.Recipient)
sender.Nonce += 1
// Send Tx to self
if bytes.Compare(tx.Recipient, tx.Sender()) == 0 {
// Subtract the fee
- sender.SubAmount(new(big.Int).Mul(TxFee, TxFeeRat))
+ sender.SubAmount(new(big.Int).Mul(GasTx, tx.GasPrice))
} else {
// Subtract the amount from the senders account
sender.SubAmount(totAmount)
@@ -127,10 +129,10 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract
// Add the amount to receivers account which should conclude this transaction
receiver.AddAmount(tx.Value)
- block.state.UpdateStateObject(receiver)
+ state.UpdateStateObject(receiver)
}
- block.state.UpdateStateObject(sender)
+ state.UpdateStateObject(sender)
ethutil.Config.Log.Infof("[TXPL] Processed Tx %x\n", tx.Hash())
diff --git a/ethchain/vm.go b/ethchain/vm.go
index d8254998e..e067a9c96 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -18,6 +18,7 @@ var (
GasCreate = big.NewInt(100)
GasCall = big.NewInt(20)
GasMemory = big.NewInt(1)
+ GasTx = big.NewInt(500)
)
func CalculateTxGas(initSize, scriptSize *big.Int) *big.Int {