Transaction processing. Implemented sending and receiving wei

This commit is contained in:
obscuren 2014-01-20 23:26:32 +01:00
parent b608a80ef1
commit 09df961abb
4 changed files with 96 additions and 66 deletions

@ -10,6 +10,7 @@ import (
"math" "math"
"math/big" "math/big"
"strconv" "strconv"
"time"
) )
type BlockChain struct { type BlockChain struct {
@ -44,6 +45,7 @@ func (bc *BlockChain) GenesisBlock() *ethutil.Block {
} }
type BlockManager struct { type BlockManager struct {
server *Server
// The block chain :) // The block chain :)
bc *BlockChain bc *BlockChain
@ -56,11 +58,12 @@ type BlockManager struct {
mem map[string]*big.Int mem map[string]*big.Int
} }
func NewBlockManager() *BlockManager { func NewBlockManager(s *Server) *BlockManager {
bm := &BlockManager{ bm := &BlockManager{
bc: NewBlockChain(), server: s,
stack: NewStack(), bc: NewBlockChain(),
mem: make(map[string]*big.Int), stack: NewStack(),
mem: make(map[string]*big.Int),
} }
// Set the last known block number based on the blockchains last // Set the last known block number based on the blockchains last
@ -161,13 +164,16 @@ func (bm *BlockManager) CalculateTD(block *ethutil.Block) bool {
// an uncle or anything that isn't on the current block chain. // an uncle or anything that isn't on the current block chain.
// Validation validates easy over difficult (dagger takes longer time = difficult) // Validation validates easy over difficult (dagger takes longer time = difficult)
func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error { func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error {
// Genesis block
if bm.bc.LastBlock == nil && block.PrevHash == "" {
return nil
}
// TODO // TODO
// 2. Check if the difficulty is correct // 2. Check if the difficulty is correct
// Check if we have the parent hash, if it isn't known we discard it // Check if we have the parent hash, if it isn't known we discard it
// Reasons might be catching up or simply an invalid block // Reasons might be catching up or simply an invalid block
if bm.bc.LastBlock != nil && block.PrevHash == "" && if !bm.bc.HasBlock(block.PrevHash) {
!bm.bc.HasBlock(block.PrevHash) {
return errors.New("Block's parent unknown") return errors.New("Block's parent unknown")
} }
@ -183,9 +189,18 @@ func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error {
} }
} }
diff := block.Time - bm.bc.LastBlock.Time
if diff < 0 {
return fmt.Errorf("Block timestamp less then prev block %v", diff)
}
// New blocks must be within the 15 minute range of the last block.
if diff > int64(15*time.Minute) {
return errors.New("Block is too far in the future of last block (> 15 minutes)")
}
// Verify the nonce of the block. Return an error if it's not valid // Verify the nonce of the block. Return an error if it's not valid
if bm.bc.LastBlock != nil && block.PrevHash == "" && if !DaggerVerify(ethutil.BigD(block.Hash()), block.Difficulty, block.Nonce) {
!DaggerVerify(ethutil.BigD(block.Hash()), block.Difficulty, block.Nonce) {
return errors.New("Block's nonce is invalid") return errors.New("Block's nonce is invalid")
} }
@ -429,7 +444,7 @@ out:
// x = floor(10^21 / floor(diff^0.5)) // x = floor(10^21 / floor(diff^0.5))
bm.stack.Push(x) bm.stack.Push(x)
case oSHA256, oRIPEMD160: case oSHA256, oSHA3, oRIPEMD160:
// This is probably save // This is probably save
// ceil(pop / 32) // ceil(pop / 32)
length := int(math.Ceil(float64(bm.stack.Pop().Uint64()) / 32.0)) length := int(math.Ceil(float64(bm.stack.Pop().Uint64()) / 32.0))
@ -443,6 +458,8 @@ out:
if op == oSHA256 { if op == oSHA256 {
bm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes()))) bm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes())))
} else if op == oSHA3 {
bm.stack.Push(base.SetBytes(ethutil.Sha3Bin(data.Bytes())))
} else { } else {
bm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes()))) bm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes())))
} }
@ -472,7 +489,6 @@ out:
case oECSIGN: case oECSIGN:
case oECRECOVER: case oECRECOVER:
case oECVALID: case oECVALID:
case oSHA3:
case oPUSH: case oPUSH:
pc++ pc++
bm.stack.Push(bm.mem[strconv.Itoa(pc)]) bm.stack.Push(bm.mem[strconv.Itoa(pc)])
@ -535,7 +551,21 @@ out:
ether := ethutil.NewEtherFromData([]byte(d)) ether := ethutil.NewEtherFromData([]byte(d))
bm.stack.Push(ether.Amount) bm.stack.Push(ether.Amount)
case oMKTX: case oMKTX:
value, addr := bm.stack.Popn()
from, length := bm.stack.Popn()
j := 0
dataItems := make([]string, int(length.Uint64()))
for i := from.Uint64(); i < length.Uint64(); i++ {
dataItems[j] = string(bm.mem[strconv.Itoa(int(i))].Bytes())
j++
}
// TODO sign it?
tx := ethutil.NewTransaction(string(addr.Bytes()), value, dataItems)
// Add the transaction to the tx pool
bm.server.txPool.QueueTransaction(tx)
case oSUICIDE: case oSUICIDE:
//addr := bm.stack.Pop()
} }
pc++ pc++
} }

@ -1,77 +1,73 @@
package main package main
/*
import ( import (
_"fmt" _ "fmt"
"testing" "testing"
) )
/*
func TestVm(t *testing.T) { func TestVm(t *testing.T) {
InitFees() InitFees()
db, _ := NewMemDatabase() db, _ := NewMemDatabase()
Db = db Db = db
ctrct := NewTransaction("", 200000000, []string{ ctrct := NewTransaction("", 200000000, []string{
"PUSH", "1a2f2e", "PUSH", "1a2f2e",
"PUSH", "hallo", "PUSH", "hallo",
"POP", // POP hallo "POP", // POP hallo
"PUSH", "3", "PUSH", "3",
"LOAD", // Load hallo back on the stack "LOAD", // Load hallo back on the stack
"PUSH", "1", "PUSH", "1",
"PUSH", "2", "PUSH", "2",
"ADD", "ADD",
"PUSH", "2", "PUSH", "2",
"PUSH", "1", "PUSH", "1",
"SUB", "SUB",
"PUSH", "100000000000000000000000", "PUSH", "100000000000000000000000",
"PUSH", "10000000000000", "PUSH", "10000000000000",
"SDIV", "SDIV",
"PUSH", "105", "PUSH", "105",
"PUSH", "200", "PUSH", "200",
"MOD", "MOD",
"PUSH", "100000000000000000000000", "PUSH", "100000000000000000000000",
"PUSH", "10000000000000", "PUSH", "10000000000000",
"SMOD", "SMOD",
"PUSH", "5", "PUSH", "5",
"PUSH", "10", "PUSH", "10",
"LT", "LT",
"PUSH", "5", "PUSH", "5",
"PUSH", "5", "PUSH", "5",
"LE", "LE",
"PUSH", "50", "PUSH", "50",
"PUSH", "5", "PUSH", "5",
"GT", "GT",
"PUSH", "5", "PUSH", "5",
"PUSH", "5", "PUSH", "5",
"GE", "GE",
"PUSH", "10", "PUSH", "10",
"PUSH", "10", "PUSH", "10",
"NOT", "NOT",
"MYADDRESS", "MYADDRESS",
"TXSENDER", "TXSENDER",
"STOP", "STOP",
}) })
tx := NewTransaction("1e8a42ea8cce13", 100, []string{}) tx := NewTransaction("1e8a42ea8cce13", 100, []string{})
block := CreateBlock("", 0, "", "c014ba53", 0, 0, "", []*Transaction{ctrct, tx}) block := CreateBlock("", 0, "", "c014ba53", 0, 0, "", []*Transaction{ctrct, tx})
db.Put(block.Hash(), block.RlpEncode()) db.Put(block.Hash(), block.RlpEncode())
bm := NewBlockManager() bm := NewBlockManager()
bm.ProcessBlock( block ) bm.ProcessBlock(block)
} }
*/

@ -174,7 +174,7 @@ out:
log.Println(err) log.Println(err)
} }
case ethwire.MsgTxTy: case ethwire.MsgTxTy:
//p.server.blockManager.AddToTransactionPool(ethutil.NewTransactionFromData(ethutil.Encode(msg.Data))) p.server.txPool.QueueTransaction(ethutil.NewTransactionFromData(ethutil.Encode(msg.Data)))
case ethwire.MsgInvTy: case ethwire.MsgInvTy:
case ethwire.MsgGetPeersTy: case ethwire.MsgGetPeersTy:
p.requestedPeerList = true p.requestedPeerList = true

@ -32,6 +32,9 @@ type Server struct {
db *ethdb.MemDatabase db *ethdb.MemDatabase
// Block manager for processing new blocks and managing the block chain // Block manager for processing new blocks and managing the block chain
blockManager *BlockManager blockManager *BlockManager
// The transaction pool. Transaction can be pushed on this pool
// for later including in the blocks
txPool *TxPool
// Peers (NYI) // Peers (NYI)
peers *list.List peers *list.List
// Nonce // Nonce
@ -50,11 +53,12 @@ func NewServer() (*Server, error) {
nonce, _ := ethutil.RandomUint64() nonce, _ := ethutil.RandomUint64()
server := &Server{ server := &Server{
shutdownChan: make(chan bool), shutdownChan: make(chan bool),
blockManager: NewBlockManager(),
db: db, db: db,
peers: list.New(), peers: list.New(),
Nonce: nonce, Nonce: nonce,
} }
server.txPool = NewTxPool(server)
server.blockManager = NewBlockManager(server)
return server, nil return server, nil
} }