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

View File

@ -10,6 +10,7 @@ import (
"math"
"math/big"
"strconv"
"time"
)
type BlockChain struct {
@ -44,6 +45,7 @@ func (bc *BlockChain) GenesisBlock() *ethutil.Block {
}
type BlockManager struct {
server *Server
// The block chain :)
bc *BlockChain
@ -56,11 +58,12 @@ type BlockManager struct {
mem map[string]*big.Int
}
func NewBlockManager() *BlockManager {
func NewBlockManager(s *Server) *BlockManager {
bm := &BlockManager{
bc: NewBlockChain(),
stack: NewStack(),
mem: make(map[string]*big.Int),
server: s,
bc: NewBlockChain(),
stack: NewStack(),
mem: make(map[string]*big.Int),
}
// 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.
// Validation validates easy over difficult (dagger takes longer time = difficult)
func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error {
// Genesis block
if bm.bc.LastBlock == nil && block.PrevHash == "" {
return nil
}
// TODO
// 2. Check if the difficulty is correct
// 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
if bm.bc.LastBlock != nil && block.PrevHash == "" &&
!bm.bc.HasBlock(block.PrevHash) {
if !bm.bc.HasBlock(block.PrevHash) {
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
if bm.bc.LastBlock != nil && block.PrevHash == "" &&
!DaggerVerify(ethutil.BigD(block.Hash()), block.Difficulty, block.Nonce) {
if !DaggerVerify(ethutil.BigD(block.Hash()), block.Difficulty, block.Nonce) {
return errors.New("Block's nonce is invalid")
}
@ -429,7 +444,7 @@ out:
// x = floor(10^21 / floor(diff^0.5))
bm.stack.Push(x)
case oSHA256, oRIPEMD160:
case oSHA256, oSHA3, oRIPEMD160:
// This is probably save
// ceil(pop / 32)
length := int(math.Ceil(float64(bm.stack.Pop().Uint64()) / 32.0))
@ -443,6 +458,8 @@ out:
if op == oSHA256 {
bm.stack.Push(base.SetBytes(ethutil.Sha256Bin(data.Bytes())))
} else if op == oSHA3 {
bm.stack.Push(base.SetBytes(ethutil.Sha3Bin(data.Bytes())))
} else {
bm.stack.Push(base.SetBytes(ethutil.Ripemd160(data.Bytes())))
}
@ -472,7 +489,6 @@ out:
case oECSIGN:
case oECRECOVER:
case oECVALID:
case oSHA3:
case oPUSH:
pc++
bm.stack.Push(bm.mem[strconv.Itoa(pc)])
@ -535,7 +551,21 @@ out:
ether := ethutil.NewEtherFromData([]byte(d))
bm.stack.Push(ether.Amount)
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:
//addr := bm.stack.Pop()
}
pc++
}

View File

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

View File

@ -174,7 +174,7 @@ out:
log.Println(err)
}
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.MsgGetPeersTy:
p.requestedPeerList = true

View File

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