diff --git a/block_manager.go b/block_manager.go index 9322d0d3a..87af9f293 100644 --- a/block_manager.go +++ b/block_manager.go @@ -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++ } diff --git a/block_manager_test.go b/block_manager_test.go index 3dcf572fd..5f200f3e7 100644 --- a/block_manager_test.go +++ b/block_manager_test.go @@ -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) } -*/ diff --git a/peer.go b/peer.go index 158541028..0f3422826 100644 --- a/peer.go +++ b/peer.go @@ -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 diff --git a/server.go b/server.go index 7a29d1bd9..3a35a43a2 100644 --- a/server.go +++ b/server.go @@ -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 }