good morning!!!!

Skip to content
Snippets Groups Projects
Commit 9df4c745 authored by Jeffrey Wilcke's avatar Jeffrey Wilcke
Browse files

WIP rewrite vm

parent 5b3d4fae
No related branches found
No related tags found
No related merge requests found
...@@ -15,6 +15,7 @@ type Block struct { ...@@ -15,6 +15,7 @@ type Block struct {
uncles []*Block uncles []*Block
coinbase string coinbase string
// state xxx // state xxx
state *Trie
difficulty uint32 difficulty uint32
// Creation time // Creation time
time int64 time int64
...@@ -34,7 +35,7 @@ func NewBlock(raw []byte) *Block { ...@@ -34,7 +35,7 @@ func NewBlock(raw []byte) *Block {
} }
// Creates a new block. This is currently for testing // Creates a new block. This is currently for testing
func CreateBlock(/* TODO use raw data */transactions []*Transaction) *Block { func CreateTestBlock(/* TODO use raw data */transactions []*Transaction) *Block {
block := &Block{ block := &Block{
// Slice of transactions to include in this block // Slice of transactions to include in this block
transactions: transactions, transactions: transactions,
...@@ -49,12 +50,32 @@ func CreateBlock(/* TODO use raw data */transactions []*Transaction) *Block { ...@@ -49,12 +50,32 @@ func CreateBlock(/* TODO use raw data */transactions []*Transaction) *Block {
return block return block
} }
func CreateBlock(root string, num int, prevHash string, base string, difficulty int, nonce int, extra string, txes []*Transaction) *Block {
block := &Block{
// Slice of transactions to include in this block
transactions: txes,
number: uint32(num),
prevHash: prevHash,
coinbase: base,
difficulty: uint32(difficulty),
nonce: uint32(nonce),
time: time.Now().Unix(),
extra: extra,
}
block.state = NewTrie(Db, root)
for _, tx := range txes {
block.state.Update(tx.recipient, string(tx.MarshalRlp()))
}
return block
}
func (block *Block) Update() { func (block *Block) Update() {
} }
// Returns a hash of the block // Returns a hash of the block
func (block *Block) Hash() string { func (block *Block) Hash() []byte {
return Sha256Hex(block.MarshalRlp()) return Sha256Bin(block.MarshalRlp())
} }
func (block *Block) MarshalRlp() []byte { func (block *Block) MarshalRlp() []byte {
...@@ -73,7 +94,7 @@ func (block *Block) MarshalRlp() []byte { ...@@ -73,7 +94,7 @@ func (block *Block) MarshalRlp() []byte {
"", "",
block.coinbase, block.coinbase,
// root state // root state
"", block.state.root,
// Sha of tx // Sha of tx
string(Sha256Bin([]byte(Encode(encTx)))), string(Sha256Bin([]byte(Encode(encTx)))),
block.difficulty, block.difficulty,
...@@ -99,7 +120,7 @@ func (block *Block) UnmarshalRlp(data []byte) { ...@@ -99,7 +120,7 @@ func (block *Block) UnmarshalRlp(data []byte) {
block.number = uint32(number) block.number = uint32(number)
} }
if prevHash, ok := header[1].([]byte); ok { if prevHash, ok := header[1].([]uint8); ok {
block.prevHash = string(prevHash) block.prevHash = string(prevHash)
} }
...@@ -109,7 +130,12 @@ func (block *Block) UnmarshalRlp(data []byte) { ...@@ -109,7 +130,12 @@ func (block *Block) UnmarshalRlp(data []byte) {
block.coinbase = string(coinbase) block.coinbase = string(coinbase)
} }
// state is header[header[4] if state, ok := header[4].([]uint8); ok {
// XXX The database is currently a global variable defined in testing.go
// This will eventually go away and the database will grabbed from the public server
// interface
block.state = NewTrie(Db, string(state))
}
// sha is header[5] // sha is header[5]
......
...@@ -33,7 +33,7 @@ func (bm *BlockManager) ProcessBlock(block *Block) error { ...@@ -33,7 +33,7 @@ func (bm *BlockManager) ProcessBlock(block *Block) error {
// Process each transaction/contract // Process each transaction/contract
for _, tx := range block.transactions { for _, tx := range block.transactions {
go bm.ProcessTransaction(tx, lockChan) go bm.ProcessTransaction(tx, block, lockChan)
} }
// Wait for all Tx to finish processing // Wait for all Tx to finish processing
...@@ -44,9 +44,9 @@ func (bm *BlockManager) ProcessBlock(block *Block) error { ...@@ -44,9 +44,9 @@ func (bm *BlockManager) ProcessBlock(block *Block) error {
return nil return nil
} }
func (bm *BlockManager) ProcessTransaction(tx *Transaction, lockChan chan bool) { func (bm *BlockManager) ProcessTransaction(tx *Transaction, block *Block, lockChan chan bool) {
if tx.recipient == "\x00" { if tx.recipient == "\x00" {
bm.vm.RunTransaction(tx, func(opType OpType) bool { bm.vm.RunTransaction(tx, block, func(opType OpType) bool {
// TODO calculate fees // TODO calculate fees
return true // Continue return true // Continue
......
...@@ -11,6 +11,8 @@ import ( ...@@ -11,6 +11,8 @@ import (
// Op codes // Op codes
var OpCodes = map[string]string{ var OpCodes = map[string]string{
"STOP": "0", "STOP": "0",
"PSH": "30", // 0x30
/*
"ADD": "16", // 0x10 "ADD": "16", // 0x10
"SUB": "17", // 0x11 "SUB": "17", // 0x11
"MUL": "18", // 0x12 "MUL": "18", // 0x12
...@@ -48,6 +50,7 @@ var OpCodes = map[string]string{ ...@@ -48,6 +50,7 @@ var OpCodes = map[string]string{
"BLKHASH": "145", // 0x91 "BLKHASH": "145", // 0x91
"COINBASE": "146", // 0x92 "COINBASE": "146", // 0x92
"SUICIDE": "255", // 0xff "SUICIDE": "255", // 0xff
*/
} }
......
...@@ -19,22 +19,13 @@ func TestCompile(t *testing.T) { ...@@ -19,22 +19,13 @@ func TestCompile(t *testing.T) {
} }
func TestValidInstr(t *testing.T) { func TestValidInstr(t *testing.T) {
/*
op, args, err := Instr("68163") op, args, err := Instr("68163")
if err != nil { if err != nil {
t.Error("Error decoding instruction") t.Error("Error decoding instruction")
} }
*/
if op != oSET {
t.Error("Expected op to be 43, got:", op)
}
if args[0] != "10" {
t.Error("Expect args[0] to be 10, got:", args[0])
}
if args[1] != "1" {
t.Error("Expected args[1] to be 1, got:", args[1])
}
} }
func TestInvalidInstr(t *testing.T) { func TestInvalidInstr(t *testing.T) {
......
...@@ -4,22 +4,17 @@ import ( ...@@ -4,22 +4,17 @@ import (
"fmt" "fmt"
) )
// This will eventually go away
var Db *MemDatabase
func Testing() { func Testing() {
db, _ := NewMemDatabase()
Db = db
bm := NewBlockManager() bm := NewBlockManager()
tx := NewTransaction("\x00", 20, []string{ tx := NewTransaction("\x00", 20, []string{
"SET 10 6", "PSH 10",
"LD 10 10",
"LT 10 1 20",
"SET 255 7",
"JMPI 20 255",
"STOP",
"SET 30 200",
"LD 30 31",
"SET 255 22",
"JMPI 31 255",
"SET 255 15",
"JMP 255",
}) })
txData := tx.MarshalRlp() txData := tx.MarshalRlp()
...@@ -28,9 +23,9 @@ func Testing() { ...@@ -28,9 +23,9 @@ func Testing() {
tx2 := NewTransaction("\x00", 20, []string{"SET 10 6", "LD 10 10"}) tx2 := NewTransaction("\x00", 20, []string{"SET 10 6", "LD 10 10"})
blck := CreateBlock([]*Transaction{tx2, tx}) blck := CreateTestBlock([]*Transaction{tx2, tx})
bm.ProcessBlock( blck ) bm.ProcessBlock( blck )
fmt.Println("GenesisBlock:", GenisisBlock, "hashed", GenisisBlock.Hash()) fmt.Println("GenesisBlock:", GenisisBlock, "hash", string(GenisisBlock.Hash()))
} }
...@@ -3,6 +3,7 @@ package main ...@@ -3,6 +3,7 @@ package main
import ( import (
"testing" "testing"
"encoding/hex" "encoding/hex"
_"fmt"
) )
func TestTriePut(t *testing.T) { func TestTriePut(t *testing.T) {
...@@ -41,6 +42,13 @@ func TestTrieUpdate(t *testing.T) { ...@@ -41,6 +42,13 @@ func TestTrieUpdate(t *testing.T) {
trie.Update("doe", "reindeer") trie.Update("doe", "reindeer")
trie.Update("dog", "puppy") trie.Update("dog", "puppy")
/*
data, _ := db.Get([]byte(trie.root))
data, _ = db.Get([]byte(DecodeNode(data)[1]))
data, _ = db.Get([]byte(DecodeNode(data)[7]))
PrintSlice(DecodeNode(data))
*/
trie.Update("dogglesworth", "cat") trie.Update("dogglesworth", "cat")
root := hex.EncodeToString([]byte(trie.root)) root := hex.EncodeToString([]byte(trie.root))
req := "e378927bfc1bd4f01a2e8d9f59bd18db8a208bb493ac0b00f93ce51d4d2af76c" req := "e378927bfc1bd4f01a2e8d9f59bd18db8a208bb493ac0b00f93ce51d4d2af76c"
......
package main package main
import ( import (
"math" _"math"
"math/big" "math/big"
"fmt" "fmt"
"strconv" _"strconv"
_ "encoding/hex" _ "encoding/hex"
) )
// Op codes // Op codes
const ( const (
oSTOP int = 0x00 oSTOP int = 0x00
oPSH int = 0x30
/*
oADD int = 0x10 oADD int = 0x10
oSUB int = 0x11 oSUB int = 0x11
oMUL int = 0x12 oMUL int = 0x12
...@@ -46,6 +48,7 @@ const ( ...@@ -46,6 +48,7 @@ const (
oDATAN int = 0x81 oDATAN int = 0x81
oMYADDRESS int = 0x90 oMYADDRESS int = 0x90
oSUICIDE int = 0xff oSUICIDE int = 0xff
*/
) )
type OpType int type OpType int
...@@ -57,6 +60,66 @@ const ( ...@@ -57,6 +60,66 @@ const (
) )
type TxCallback func(opType OpType) bool type TxCallback func(opType OpType) bool
// Simple push/pop stack mechanism
type Stack struct {
data []string
}
func NewStack() *Stack {
return &Stack{}
}
func (st *Stack) Pop() string {
s := len(st.data)
str := st.data[s]
st.data = st.data[:s-1]
return str
}
func (st *Stack) Push(d string) {
st.data = append(st.data, d)
}
type Vm struct {
// Stack
stack *Stack
}
func NewVm() *Vm {
return &Vm{
stack: NewStack(),
}
}
func (vm *Vm) RunTransaction(tx *Transaction, block *Block, cb TxCallback) {
// Instruction pointer
iptr := 0
// Index pointer for the memory
memIndex := 0
fmt.Printf("# op arg\n")
for iptr < len(tx.data) {
memIndex++
// The base big int for all calculations. Use this for any results.
base := new(big.Int)
base.SetString("0",0) // so it doesn't whine about it
// XXX Should Instr return big int slice instead of string slice?
op, args, _ := Instr(tx.data[iptr])
if Debug {
fmt.Printf("%-3d %-4d %v\n", iptr, op, args)
}
switch op {
case oPSH:
}
// Increment instruction pointer
iptr++
}
}
/*
type Vm struct { type Vm struct {
// Memory stack // Memory stack
stack map[string]string stack map[string]string
...@@ -183,3 +246,4 @@ out: ...@@ -183,3 +246,4 @@ out:
} }
} }
} }
*/
package main
import (
"fmt"
"testing"
_"encoding/hex"
)
func TestVm(t *testing.T) {
db, _ := NewMemDatabase()
Db = db
tx := NewTransaction("\x00", 20, []string{
"PSH 10",
})
block := CreateBlock("", 0, "", "", 0, 0, "", []*Transaction{tx})
db.Put(block.Hash(), block.MarshalRlp())
bm := NewBlockManager()
bm.ProcessBlock( block )
tx1 := &Transaction{}
tx1.UnmarshalRlp([]byte(block.state.Get(tx.recipient)))
fmt.Println(tx1)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment