aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-01-11 22:27:08 +0800
committerobscuren <geffobscura@gmail.com>2014-01-11 22:27:08 +0800
commit9571a512861d4a44c36d368f4baa15b2aa81c37d (patch)
treec5412a119ab885570351f42e512dd2d62d0bae61
parent8bbf879cb31e9cb28700773ed788421f9935ac36 (diff)
downloaddexon-9571a512861d4a44c36d368f4baa15b2aa81c37d.tar.gz
dexon-9571a512861d4a44c36d368f4baa15b2aa81c37d.tar.zst
dexon-9571a512861d4a44c36d368f4baa15b2aa81c37d.zip
gofmt no coding standards
-rw-r--r--README.md5
-rw-r--r--block_manager.go120
-rw-r--r--dagger.go199
-rw-r--r--dagger_test.go18
-rw-r--r--dev_console.go186
-rw-r--r--ethereum.go132
-rw-r--r--peer.go118
-rw-r--r--rlp.go388
-rw-r--r--rlp_test.go74
-rw-r--r--server.go161
-rw-r--r--test_runner.go30
-rw-r--r--test_runner_test.go28
-rw-r--r--testing.go1
-rw-r--r--vm.go451
14 files changed, 973 insertions, 938 deletions
diff --git a/README.md b/README.md
index 4b797b5a7..37e8505f1 100644
--- a/README.md
+++ b/README.md
@@ -21,3 +21,8 @@ Command line options
-c launch the developer console
-m start mining fake blocks and broadcast fake messages to the net
+
+Contribution
+============
+
+See CONTRIB.md
diff --git a/block_manager.go b/block_manager.go
index 59430dca7..968d9a139 100644
--- a/block_manager.go
+++ b/block_manager.go
@@ -1,90 +1,90 @@
package main
import (
- "fmt"
- "github.com/ethereum/ethutil-go"
+ "fmt"
+ "github.com/ethereum/ethutil-go"
)
type BlockChain struct {
- lastBlock *ethutil.Block
+ lastBlock *ethutil.Block
- genesisBlock *ethutil.Block
+ genesisBlock *ethutil.Block
}
func NewBlockChain() *BlockChain {
- bc := &BlockChain{}
- bc.genesisBlock = ethutil.NewBlock( ethutil.Encode(ethutil.Genesis) )
+ bc := &BlockChain{}
+ bc.genesisBlock = ethutil.NewBlock(ethutil.Encode(ethutil.Genesis))
- return bc
+ return bc
}
type BlockManager struct {
- vm *Vm
+ vm *Vm
- blockChain *BlockChain
+ blockChain *BlockChain
}
func NewBlockManager() *BlockManager {
- bm := &BlockManager{vm: NewVm()}
+ bm := &BlockManager{vm: NewVm()}
- return bm
+ return bm
}
// Process a block.
func (bm *BlockManager) ProcessBlock(block *ethutil.Block) error {
- // TODO Validation (Or move to other part of the application)
- if err := bm.ValidateBlock(block); err != nil {
- return err
- }
-
- // Get the tx count. Used to create enough channels to 'join' the go routines
- txCount := len(block.Transactions())
- // Locking channel. When it has been fully buffered this method will return
- lockChan := make(chan bool, txCount)
-
- // Process each transaction/contract
- for _, tx := range block.Transactions() {
- // If there's no recipient, it's a contract
- if tx.IsContract() {
- go bm.ProcessContract(tx, block, lockChan)
- } else {
- // "finish" tx which isn't a contract
- lockChan <- true
- }
- }
-
- // Wait for all Tx to finish processing
- for i := 0; i < txCount; i++ {
- <- lockChan
- }
-
- return nil
+ // TODO Validation (Or move to other part of the application)
+ if err := bm.ValidateBlock(block); err != nil {
+ return err
+ }
+
+ // Get the tx count. Used to create enough channels to 'join' the go routines
+ txCount := len(block.Transactions())
+ // Locking channel. When it has been fully buffered this method will return
+ lockChan := make(chan bool, txCount)
+
+ // Process each transaction/contract
+ for _, tx := range block.Transactions() {
+ // If there's no recipient, it's a contract
+ if tx.IsContract() {
+ go bm.ProcessContract(tx, block, lockChan)
+ } else {
+ // "finish" tx which isn't a contract
+ lockChan <- true
+ }
+ }
+
+ // Wait for all Tx to finish processing
+ for i := 0; i < txCount; i++ {
+ <-lockChan
+ }
+
+ return nil
}
func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error {
- return nil
+ return nil
}
func (bm *BlockManager) ProcessContract(tx *ethutil.Transaction, block *ethutil.Block, lockChan chan bool) {
- // Recovering function in case the VM had any errors
- defer func() {
- if r := recover(); r != nil {
- fmt.Println("Recovered from VM execution with err =", r)
- // Let the channel know where done even though it failed (so the execution may resume normally)
- lockChan <- true
- }
- }()
-
- // Process contract
- bm.vm.ProcContract(tx, block, func(opType OpType) bool {
- // TODO turn on once big ints are in place
- //if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
- // return false
- //}
-
- return true // Continue
- })
-
- // Broadcast we're done
- lockChan <- true
+ // Recovering function in case the VM had any errors
+ defer func() {
+ if r := recover(); r != nil {
+ fmt.Println("Recovered from VM execution with err =", r)
+ // Let the channel know where done even though it failed (so the execution may resume normally)
+ lockChan <- true
+ }
+ }()
+
+ // Process contract
+ bm.vm.ProcContract(tx, block, func(opType OpType) bool {
+ // TODO turn on once big ints are in place
+ //if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
+ // return false
+ //}
+
+ return true // Continue
+ })
+
+ // Broadcast we're done
+ lockChan <- true
}
diff --git a/dagger.go b/dagger.go
index 5aa5dd755..70b0b4692 100644
--- a/dagger.go
+++ b/dagger.go
@@ -1,142 +1,145 @@
package main
import (
- "math/big"
- "math/rand"
- "time"
- "github.com/obscuren/sha3"
- "hash"
- "github.com/ethereum/ethutil-go"
+ "github.com/ethereum/ethutil-go"
+ "github.com/obscuren/sha3"
+ "hash"
+ "math/big"
+ "math/rand"
+ "time"
)
type Dagger struct {
- hash *big.Int
- xn *big.Int
+ hash *big.Int
+ xn *big.Int
}
var Found bool
+
func (dag *Dagger) Find(obj *big.Int, resChan chan int64) {
- r := rand.New(rand.NewSource(time.Now().UnixNano()))
+ r := rand.New(rand.NewSource(time.Now().UnixNano()))
- for i := 0; i < 1000; i++ {
- rnd := r.Int63()
+ for i := 0; i < 1000; i++ {
+ rnd := r.Int63()
- if dag.Eval(big.NewInt(rnd)).Cmp(obj) < 0 {
- // Post back result on the channel
- resChan <- rnd
- // Notify other threads we've found a valid nonce
- Found = true
- }
+ if dag.Eval(big.NewInt(rnd)).Cmp(obj) < 0 {
+ // Post back result on the channel
+ resChan <- rnd
+ // Notify other threads we've found a valid nonce
+ Found = true
+ }
- // Break out if found
- if Found { break }
- }
+ // Break out if found
+ if Found {
+ break
+ }
+ }
- resChan <- 0
+ resChan <- 0
}
func (dag *Dagger) Search(hash, diff *big.Int) *big.Int {
- // TODO fix multi threading. Somehow it results in the wrong nonce
- amountOfRoutines := 1
+ // TODO fix multi threading. Somehow it results in the wrong nonce
+ amountOfRoutines := 1
- dag.hash = hash
+ dag.hash = hash
- obj := ethutil.BigPow(2, 256)
- obj = obj.Div(obj, diff)
+ obj := ethutil.BigPow(2, 256)
+ obj = obj.Div(obj, diff)
- Found = false
- resChan := make(chan int64, 3)
- var res int64
+ Found = false
+ resChan := make(chan int64, 3)
+ var res int64
- for k := 0; k < amountOfRoutines; k++ {
- go dag.Find(obj, resChan)
- }
+ for k := 0; k < amountOfRoutines; k++ {
+ go dag.Find(obj, resChan)
+ }
- // Wait for each go routine to finish
- for k := 0; k < amountOfRoutines; k++ {
- // Get the result from the channel. 0 = quit
- if r := <- resChan; r != 0 {
- res = r
- }
- }
+ // Wait for each go routine to finish
+ for k := 0; k < amountOfRoutines; k++ {
+ // Get the result from the channel. 0 = quit
+ if r := <-resChan; r != 0 {
+ res = r
+ }
+ }
- return big.NewInt(res)
+ return big.NewInt(res)
}
func DaggerVerify(hash, diff, nonce *big.Int) bool {
- dagger := &Dagger{}
- dagger.hash = hash
+ dagger := &Dagger{}
+ dagger.hash = hash
- obj := ethutil.BigPow(2, 256)
- obj = obj.Div(obj, diff)
+ obj := ethutil.BigPow(2, 256)
+ obj = obj.Div(obj, diff)
- return dagger.Eval(nonce).Cmp(obj) < 0
+ return dagger.Eval(nonce).Cmp(obj) < 0
}
func (dag *Dagger) Node(L uint64, i uint64) *big.Int {
- if L == i {
- return dag.hash
- }
-
- var m *big.Int
- if L == 9 {
- m = big.NewInt(16)
- } else {
- m = big.NewInt(3)
- }
-
- sha := sha3.NewKeccak256()
- sha.Reset()
- d := sha3.NewKeccak256()
- b := new(big.Int)
- ret := new(big.Int)
-
- for k := 0; k < int(m.Uint64()); k++ {
- d.Reset()
- d.Write(dag.hash.Bytes())
- d.Write(dag.xn.Bytes())
- d.Write(big.NewInt(int64(L)).Bytes())
- d.Write(big.NewInt(int64(i)).Bytes())
- d.Write(big.NewInt(int64(k)).Bytes())
-
- b.SetBytes(Sum(d))
- pk := b.Uint64() & ((1 << ((L - 1) * 3)) - 1)
- sha.Write(dag.Node(L - 1, pk).Bytes())
- }
-
- ret.SetBytes(Sum(sha))
-
- return ret
+ if L == i {
+ return dag.hash
+ }
+
+ var m *big.Int
+ if L == 9 {
+ m = big.NewInt(16)
+ } else {
+ m = big.NewInt(3)
+ }
+
+ sha := sha3.NewKeccak256()
+ sha.Reset()
+ d := sha3.NewKeccak256()
+ b := new(big.Int)
+ ret := new(big.Int)
+
+ for k := 0; k < int(m.Uint64()); k++ {
+ d.Reset()
+ d.Write(dag.hash.Bytes())
+ d.Write(dag.xn.Bytes())
+ d.Write(big.NewInt(int64(L)).Bytes())
+ d.Write(big.NewInt(int64(i)).Bytes())
+ d.Write(big.NewInt(int64(k)).Bytes())
+
+ b.SetBytes(Sum(d))
+ pk := b.Uint64() & ((1 << ((L - 1) * 3)) - 1)
+ sha.Write(dag.Node(L-1, pk).Bytes())
+ }
+
+ ret.SetBytes(Sum(sha))
+
+ return ret
}
func Sum(sha hash.Hash) []byte {
- in := make([]byte, 32)
- return sha.Sum(in)
+ in := make([]byte, 32)
+ return sha.Sum(in)
}
func (dag *Dagger) Eval(N *big.Int) *big.Int {
- pow := ethutil.BigPow(2, 26)
- dag.xn = N.Div(N, pow)
+ pow := ethutil.BigPow(2, 26)
+ dag.xn = N.Div(N, pow)
- sha := sha3.NewKeccak256()
- sha.Reset()
- ret := new(big.Int)
+ sha := sha3.NewKeccak256()
+ sha.Reset()
+ ret := new(big.Int)
- for k := 0; k < 4; k++ {
- d := sha3.NewKeccak256()
- b := new(big.Int)
+ for k := 0; k < 4; k++ {
+ d := sha3.NewKeccak256()
+ b := new(big.Int)
- d.Reset()
- d.Write(dag.hash.Bytes())
- d.Write(dag.xn.Bytes())
- d.Write(N.Bytes())
- d.Write(big.NewInt(int64(k)).Bytes())
+ d.Reset()
+ d.Write(dag.hash.Bytes())
+ d.Write(dag.xn.Bytes())
+ d.Write(N.Bytes())
+ d.Write(big.NewInt(int64(k)).Bytes())
- b.SetBytes(Sum(d))
- pk := (b.Uint64() & 0x1ffffff)
+ b.SetBytes(Sum(d))
+ pk := (b.Uint64() & 0x1ffffff)
- sha.Write(dag.Node(9, pk).Bytes())
- }
+ sha.Write(dag.Node(9, pk).Bytes())
+ }
- return ret.SetBytes(Sum(sha))
+ return ret.SetBytes(Sum(sha))
}
diff --git a/dagger_test.go b/dagger_test.go
index 7953ec1da..58cdd6afd 100644
--- a/dagger_test.go
+++ b/dagger_test.go
@@ -1,17 +1,17 @@
package main
import (
- "testing"
- "math/big"
+ "math/big"
+ "testing"
)
func BenchmarkDaggerSearch(b *testing.B) {
- hash := big.NewInt(0)
- diff := BigPow(2, 36)
- o := big.NewInt(0) // nonce doesn't matter. We're only testing against speed, not validity
+ hash := big.NewInt(0)
+ diff := BigPow(2, 36)
+ o := big.NewInt(0) // nonce doesn't matter. We're only testing against speed, not validity
- // Reset timer so the big generation isn't included in the benchmark
- b.ResetTimer()
- // Validate
- DaggerVerify(hash, diff, o)
+ // Reset timer so the big generation isn't included in the benchmark
+ b.ResetTimer()
+ // Validate
+ DaggerVerify(hash, diff, o)
}
diff --git a/dev_console.go b/dev_console.go
index 27fc2e65e..923c483c2 100644
--- a/dev_console.go
+++ b/dev_console.go
@@ -1,119 +1,121 @@
package main
import (
- "fmt"
- "bufio"
- "strings"
- "os"
- "errors"
- "encoding/hex"
- "github.com/ethereum/ethdb-go"
- "github.com/ethereum/ethutil-go"
+ "bufio"
+ "encoding/hex"
+ "errors"
+ "fmt"
+ "github.com/ethereum/ethdb-go"
+ "github.com/ethereum/ethutil-go"
+ "os"
+ "strings"
)
type Console struct {
- db *ethdb.MemDatabase
- trie *ethutil.Trie
+ db *ethdb.MemDatabase
+ trie *ethutil.Trie
}
func NewConsole() *Console {
- db, _ := ethdb.NewMemDatabase()
- trie := ethutil.NewTrie(db, "")
+ db, _ := ethdb.NewMemDatabase()
+ trie := ethutil.NewTrie(db, "")
- return &Console{db: db, trie: trie}
+ return &Console{db: db, trie: trie}
}
func (i *Console) ValidateInput(action string, argumentLength int) error {
- err := false
- var expArgCount int
+ err := false
+ var expArgCount int
- switch {
- case action == "update" && argumentLength != 2:
- err = true
- expArgCount = 2
- case action == "get" && argumentLength != 1:
- err = true
- expArgCount = 1
- case action == "dag" && argumentLength != 2:
- err = true
- expArgCount = 2
- }
+ switch {
+ case action == "update" && argumentLength != 2:
+ err = true
+ expArgCount = 2
+ case action == "get" && argumentLength != 1:
+ err = true
+ expArgCount = 1
+ case action == "dag" && argumentLength != 2:
+ err = true
+ expArgCount = 2
+ }
- if err {
- return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
- } else {
- return nil
- }
+ if err {
+ return errors.New(fmt.Sprintf("'%s' requires %d args, got %d", action, expArgCount, argumentLength))
+ } else {
+ return nil
+ }
}
func (i *Console) ParseInput(input string) bool {
- scanner := bufio.NewScanner(strings.NewReader(input))
- scanner.Split(bufio.ScanWords)
+ scanner := bufio.NewScanner(strings.NewReader(input))
+ scanner.Split(bufio.ScanWords)
- count := 0
- var tokens []string
- for scanner.Scan() {
- count++
- tokens = append(tokens, scanner.Text())
- }
- if err := scanner.Err(); err != nil {
- fmt.Fprintln(os.Stderr, "reading input:", err)
- }
+ count := 0
+ var tokens []string
+ for scanner.Scan() {
+ count++
+ tokens = append(tokens, scanner.Text())
+ }
+ if err := scanner.Err(); err != nil {
+ fmt.Fprintln(os.Stderr, "reading input:", err)
+ }
- if len(tokens) == 0 { return true }
+ if len(tokens) == 0 {
+ return true
+ }
- err := i.ValidateInput(tokens[0], count-1)
- if err != nil {
- fmt.Println(err)
- } else {
- switch tokens[0] {
- case "update":
- i.trie.Update(tokens[1], tokens[2])
+ err := i.ValidateInput(tokens[0], count-1)
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ switch tokens[0] {
+ case "update":
+ i.trie.Update(tokens[1], tokens[2])
- fmt.Println(hex.EncodeToString([]byte(i.trie.Root)))
- case "get":
- fmt.Println(i.trie.Get(tokens[1]))
- case "root":
- fmt.Println(hex.EncodeToString([]byte(i.trie.Root)))
- case "rawroot":
- fmt.Println(i.trie.Root)
- case "print":
- i.db.Print()
- case "dag":
- fmt.Println(DaggerVerify( ethutil.Big(tokens[1]), // hash
- ethutil.BigPow(2, 36), // diff
- ethutil.Big(tokens[2])))// nonce
- case "exit", "quit", "q":
- return false
- case "help":
- fmt.Printf( "COMMANDS:\n"+
- "\033[1m= DB =\033[0m\n"+
- "update KEY VALUE - Updates/Creates a new value for the given key\n"+
- "get KEY - Retrieves the given key\n"+
- "root - Prints the hex encoded merkle root\n"+
- "rawroot - Prints the raw merkle root\n"+
- "\033[1m= Dagger =\033[0m\n"+
- "dag HASH NONCE - Verifies a nonce with the given hash with dagger\n")
- default:
- fmt.Println("Unknown command:", tokens[0])
- }
- }
+ fmt.Println(hex.EncodeToString([]byte(i.trie.Root)))
+ case "get":
+ fmt.Println(i.trie.Get(tokens[1]))
+ case "root":
+ fmt.Println(hex.EncodeToString([]byte(i.trie.Root)))
+ case "rawroot":
+ fmt.Println(i.trie.Root)
+ case "print":
+ i.db.Print()
+ case "dag":
+ fmt.Println(DaggerVerify(ethutil.Big(tokens[1]), // hash
+ ethutil.BigPow(2, 36), // diff
+ ethutil.Big(tokens[2]))) // nonce
+ case "exit", "quit", "q":
+ return false
+ case "help":
+ fmt.Printf("COMMANDS:\n" +
+ "\033[1m= DB =\033[0m\n" +
+ "update KEY VALUE - Updates/Creates a new value for the given key\n" +
+ "get KEY - Retrieves the given key\n" +
+ "root - Prints the hex encoded merkle root\n" +
+ "rawroot - Prints the raw merkle root\n" +
+ "\033[1m= Dagger =\033[0m\n" +
+ "dag HASH NONCE - Verifies a nonce with the given hash with dagger\n")
+ default:
+ fmt.Println("Unknown command:", tokens[0])
+ }
+ }
- return true
+ return true
}
func (i *Console) Start() {
- fmt.Printf("Eth Console. Type (help) for help\n")
- reader := bufio.NewReader(os.Stdin)
- for {
- fmt.Printf("eth >>> ")
- str, _, err := reader.ReadLine()
- if err != nil {
- fmt.Println("Error reading input", err)
- } else {
- if !i.ParseInput(string(str)) {
- return
- }
- }
- }
+ fmt.Printf("Eth Console. Type (help) for help\n")
+ reader := bufio.NewReader(os.Stdin)
+ for {
+ fmt.Printf("eth >>> ")
+ str, _, err := reader.ReadLine()
+ if err != nil {
+ fmt.Println("Error reading input", err)
+ } else {
+ if !i.ParseInput(string(str)) {
+ return
+ }
+ }
+ }
}
diff --git a/ethereum.go b/ethereum.go
index 96b67f970..dd5b44308 100644
--- a/ethereum.go
+++ b/ethereum.go
@@ -1,85 +1,85 @@
package main
import (
- "fmt"
- "os"
- "os/signal"
- "flag"
- "runtime"
- "log"
- "github.com/ethereum/ethutil-go"
+ "flag"
+ "fmt"
+ "github.com/ethereum/ethutil-go"
+ "log"
+ "os"
+ "os/signal"
+ "runtime"
)
const Debug = true
var StartConsole bool
var StartMining bool
+
func Init() {
- flag.BoolVar(&StartConsole, "c", false, "debug and testing console")
- flag.BoolVar(&StartMining, "m", false, "start dagger mining")
+ flag.BoolVar(&StartConsole, "c", false, "debug and testing console")
+ flag.BoolVar(&StartMining, "m", false, "start dagger mining")
- flag.Parse()
+ flag.Parse()
}
// Register interrupt handlers so we can stop the server
func RegisterInterupts(s *Server) {
- // Buffered chan of one is enough
- c := make(chan os.Signal, 1)
- // Notify about interrupts for now
- signal.Notify(c, os.Interrupt)
- go func() {
- for sig := range c {
- fmt.Printf("Shutting down (%v) ... \n", sig)
-
- s.Stop()
- }
- }()
+ // Buffered chan of one is enough
+ c := make(chan os.Signal, 1)
+ // Notify about interrupts for now
+ signal.Notify(c, os.Interrupt)
+ go func() {
+ for sig := range c {
+ fmt.Printf("Shutting down (%v) ... \n", sig)
+
+ s.Stop()
+ }
+ }()
}
func main() {
- runtime.GOMAXPROCS(runtime.NumCPU())
-
- ethutil.InitFees()
-
- Init()
-
- if StartConsole {
- console := NewConsole()
- console.Start()
- } else{
- log.Println("Starting Ethereum")
- server, err := NewServer()
-
- if err != nil {
- log.Println(err)
- return
- }
-
- RegisterInterupts(server)
-
- if StartMining {
- log.Println("Mining started")
- dagger := &Dagger{}
-
- go func() {
- for {
- res := dagger.Search(ethutil.Big("0"), ethutil.BigPow(2, 36))
- server.Broadcast("block", Encode(res.String()))
- }
- }()
- }
-
- server.Start()
-
- err = server.ConnectToPeer("localhost:12345")
- if err != nil {
- log.Println(err)
- server.Stop()
- return
- }
-
-
- // Wait for shutdown
- server.WaitForShutdown()
- }
+ runtime.GOMAXPROCS(runtime.NumCPU())
+
+ ethutil.InitFees()
+
+ Init()
+
+ if StartConsole {
+ console := NewConsole()
+ console.Start()
+ } else {
+ log.Println("Starting Ethereum")
+ server, err := NewServer()
+
+ if err != nil {
+ log.Println(err)
+ return
+ }
+
+ RegisterInterupts(server)
+
+ if StartMining {
+ log.Println("Mining started")
+ dagger := &Dagger{}
+
+ go func() {
+ for {
+ res := dagger.Search(ethutil.Big("0"), ethutil.BigPow(2, 36))
+ server.Broadcast("block", Encode(res.String()))
+ }
+ }()
+ }
+
+ server.Start()
+
+ err = server.ConnectToPeer("localhost:12345")
+ if err != nil {
+ log.Println(err)
+ server.Stop()
+ return
+ }
+
+ // Wait for shutdown
+ server.WaitForShutdown()
+ }
}
diff --git a/peer.go b/peer.go
index d47af73de..a9f88b1e1 100644
--- a/peer.go
+++ b/peer.go
@@ -1,92 +1,92 @@
package main
import (
- "net"
- "log"
- "github.com/ethereum/ethwire-go"
+ "github.com/ethereum/ethwire-go"
+ "log"
+ "net"
)
type Peer struct {
- // Server interface
- server *Server
- // Net connection
- conn net.Conn
- // Output queue which is used to communicate and handle messages
- outputQueue chan ethwire.InOutMsg
- // Quit channel
- quit chan bool
+ // Server interface
+ server *Server
+ // Net connection
+ conn net.Conn
+ // Output queue which is used to communicate and handle messages
+ outputQueue chan ethwire.InOutMsg
+ // Quit channel
+ quit chan bool
}
func NewPeer(conn net.Conn, server *Server) *Peer {
- return &Peer{
- outputQueue: make(chan ethwire.InOutMsg, 1), // Buffered chan of 1 is enough
- quit: make(chan bool),
+ return &Peer{
+ outputQueue: make(chan ethwire.InOutMsg, 1), // Buffered chan of 1 is enough
+ quit: make(chan bool),
- server: server,
- conn: conn,
- }
+ server: server,
+ conn: conn,
+ }
}
// Outputs any RLP encoded data to the peer
func (p *Peer) QueueMessage(msgType string, data []byte) {
- p.outputQueue <- ethwire.InOutMsg{MsgType: msgType, Data: data}
+ p.outputQueue <- ethwire.InOutMsg{MsgType: msgType, Data: data}
}
// Outbound message handler. Outbound messages are handled here
func (p *Peer) HandleOutbound() {
out:
- for {
- select {
- // Main message queue. All outbound messages are processed through here
- case msg := <-p.outputQueue:
- // TODO Message checking and handle accordingly
- err := ethwire.WriteMessage(p.conn, msg)
- if err != nil {
- log.Println(err)
-
- // Stop the client if there was an error writing to it
- p.Stop()
- }
-
- // Break out of the for loop if a quit message is posted
- case <- p.quit:
- break out
- }
- }
+ for {
+ select {
+ // Main message queue. All outbound messages are processed through here
+ case msg := <-p.outputQueue:
+ // TODO Message checking and handle accordingly
+ err := ethwire.WriteMessage(p.conn, msg)
+ if err != nil {
+ log.Println(err)
+
+ // Stop the client if there was an error writing to it
+ p.Stop()
+ }
+
+ // Break out of the for loop if a quit message is posted
+ case <-p.quit:
+ break out
+ }
+ }
}
// Inbound handler. Inbound messages are received here and passed to the appropriate methods
func (p *Peer) HandleInbound() {
- defer p.Stop()
+ defer p.Stop()
out:
- for {
- // Wait for a message from the peer
- msg, err := ethwire.ReadMessage(p.conn)
- if err != nil {
- log.Println(err)
-
- break out
- }
-
- // TODO
- data, _ := Decode(msg.Data, 0)
- log.Printf("%s, %s\n", msg.MsgType, data)
- }
-
- // Notify the out handler we're quiting
- p.quit <- true
+ for {
+ // Wait for a message from the peer
+ msg, err := ethwire.ReadMessage(p.conn)
+ if err != nil {
+ log.Println(err)
+
+ break out
+ }
+
+ // TODO
+ data, _ := Decode(msg.Data, 0)
+ log.Printf("%s, %s\n", msg.MsgType, data)
+ }
+
+ // Notify the out handler we're quiting
+ p.quit <- true
}
func (p *Peer) Start() {
- // Run the outbound handler in a new goroutine
- go p.HandleOutbound()
- // Run the inbound handler in a new goroutine
- go p.HandleInbound()
+ // Run the outbound handler in a new goroutine
+ go p.HandleOutbound()
+ // Run the inbound handler in a new goroutine
+ go p.HandleInbound()
}
func (p *Peer) Stop() {
- p.conn.Close()
+ p.conn.Close()
- p.quit <- true
+ p.quit <- true
}
diff --git a/rlp.go b/rlp.go
index cee9da613..91ec50164 100644
--- a/rlp.go
+++ b/rlp.go
@@ -1,270 +1,278 @@
package main
import (
- "fmt"
- "bytes"
- "math"
- "math/big"
- "github.com/ethereum/ethutil-go"
+ "bytes"
+ "fmt"
+ "github.com/ethereum/ethutil-go"
+ "math"
+ "math/big"
)
type RlpEncoder struct {
- rlpData []byte
+ rlpData []byte
}
+
func NewRlpEncoder() *RlpEncoder {
- encoder := &RlpEncoder{}
+ encoder := &RlpEncoder{}
- return encoder
+ return encoder
}
func (coder *RlpEncoder) EncodeData(rlpData []interface{}) []byte {
- return nil
+ return nil
}
// Data attributes are returned by the rlp decoder. The data attributes represents
// one item within the rlp data structure. It's responsible for all the casting
// It always returns something valid
type RlpDataAttribute struct {
- dataAttrib interface{}
+ dataAttrib interface{}
}
func NewRlpDataAttribute(attrib interface{}) *RlpDataAttribute {
- return &RlpDataAttribute{dataAttrib: attrib}
+ return &RlpDataAttribute{dataAttrib: attrib}
}
func (attr *RlpDataAttribute) Length() int {
- if data, ok := attr.dataAttrib.([]interface{}); ok {
- return len(data)
- }
+ if data, ok := attr.dataAttrib.([]interface{}); ok {
+ return len(data)
+ }
- return 0
+ return 0
}
func (attr *RlpDataAttribute) AsUint() uint64 {
- if value, ok := attr.dataAttrib.(uint8); ok {
- return uint64(value)
- } else if value, ok := attr.dataAttrib.(uint16); ok {
- return uint64(value)
- } else if value, ok := attr.dataAttrib.(uint32); ok {
- return uint64(value)
- } else if value, ok := attr.dataAttrib.(uint64); ok {
- return value
- }
-
- return 0
+ if value, ok := attr.dataAttrib.(uint8); ok {
+ return uint64(value)
+ } else if value, ok := attr.dataAttrib.(uint16); ok {
+ return uint64(value)
+ } else if value, ok := attr.dataAttrib.(uint32); ok {
+ return uint64(value)
+ } else if value, ok := attr.dataAttrib.(uint64); ok {
+ return value
+ }
+
+ return 0
}
func (attr *RlpDataAttribute) AsBigInt() *big.Int {
- if a, ok := attr.dataAttrib.([]byte); ok {
- return ethutil.Big(string(a))
- }
+ if a, ok := attr.dataAttrib.([]byte); ok {
+ return ethutil.Big(string(a))
+ }
- return big.NewInt(0)
+ return big.NewInt(0)
}
func (attr *RlpDataAttribute) AsString() string {
- if a, ok := attr.dataAttrib.([]byte); ok {
- return string(a)
- }
+ if a, ok := attr.dataAttrib.([]byte); ok {
+ return string(a)
+ }
- return ""
+ return ""
}
func (attr *RlpDataAttribute) AsBytes() []byte {
- if a, ok := attr.dataAttrib.([]byte); ok {
- return a
- }
+ if a, ok := attr.dataAttrib.([]byte); ok {
+ return a
+ }
- return make([]byte, 0)
+ return make([]byte, 0)
}
// Threat the attribute as a slice
func (attr *RlpDataAttribute) Get(idx int) *RlpDataAttribute {
- if d, ok := attr.dataAttrib.([]interface{}); ok {
- // Guard for oob
- if len(d) < idx {
- return NewRlpDataAttribute(nil)
- }
+ if d, ok := attr.dataAttrib.([]interface{}); ok {
+ // Guard for oob
+ if len(d) < idx {
+ return NewRlpDataAttribute(nil)
+ }
- return NewRlpDataAttribute(d[idx])
- }
+ return NewRlpDataAttribute(d[idx])
+ }
- // If this wasn't a slice you probably shouldn't be using this function
- return NewRlpDataAttribute(nil)
+ // If this wasn't a slice you probably shouldn't be using this function
+ return NewRlpDataAttribute(nil)
}
type RlpDecoder struct {
- rlpData interface{}
+ rlpData interface{}
}
+
func NewRlpDecoder(rlpData []byte) *RlpDecoder {
- decoder := &RlpDecoder{}
- // Decode the data
- data, _ := Decode(rlpData,0)
- decoder.rlpData = data
+ decoder := &RlpDecoder{}
+ // Decode the data
+ data, _ := Decode(rlpData, 0)
+ decoder.rlpData = data
- return decoder
+ return decoder
}
func (dec *RlpDecoder) Get(idx int) *RlpDataAttribute {
- return NewRlpDataAttribute(dec.rlpData).Get(idx)
+ return NewRlpDataAttribute(dec.rlpData).Get(idx)
}
/// Raw methods
func BinaryLength(n uint64) uint64 {
- if n == 0 { return 0 }
+ if n == 0 {
+ return 0
+ }
- return 1 + BinaryLength(n / 256)
+ return 1 + BinaryLength(n/256)
}
func ToBinarySlice(n uint64, length uint64) []uint64 {
- if length == 0 {
- length = BinaryLength(n)
- }
+ if length == 0 {
+ length = BinaryLength(n)
+ }
- if n == 0 { return make([]uint64, 1) }
+ if n == 0 {
+ return make([]uint64, 1)
+ }
- slice := ToBinarySlice(n / 256, 0)
- slice = append(slice, n % 256)
+ slice := ToBinarySlice(n/256, 0)
+ slice = append(slice, n%256)
- return slice
+ return slice
}
func ToBin(n uint64, length uint64) string {
- var buf bytes.Buffer
- for _, val := range ToBinarySlice(n, length) {
- buf.WriteString(string(val))
- }
+ var buf bytes.Buffer
+ for _, val := range ToBinarySlice(n, length) {
+ buf.WriteString(string(val))
+ }
- return buf.String()
+ return buf.String()
}
func FromBin(data []byte) uint64 {
- if len(data) == 0 { return 0 }
+ if len(data) == 0 {
+ return 0
+ }
- return FromBin(data[:len(data)-1]) * 256 + uint64(data[len(data)-1])
+ return FromBin(data[:len(data)-1])*256 + uint64(data[len(data)-1])
}
func Decode(data []byte, pos int) (interface{}, int) {
- if pos > len(data)-1 {
- panic(fmt.Sprintf("index out of range %d for data %q, l = %d", pos, data, len(data)))
- }
-
- char := int(data[pos])
- slice := make([]interface{}, 0)
- switch {
- case char < 24:
- return data[pos], pos + 1
-
- case char < 56:
- b := int(data[pos]) - 23
- return FromBin(data[pos+1 : pos+1+b]), pos + 1 + b
-
- case char < 64:
- b := int(data[pos]) - 55
- b2 := int(FromBin(data[pos+1 : pos+1+b]))
- return FromBin(data[pos+1+b : pos+1+b+b2]), pos+1+b+b2
-
- case char < 120:
- b := int(data[pos]) - 64
- return data[pos+1:pos+1+b], pos+1+b
-
- case char < 128:
- b := int(data[pos]) - 119
- b2 := int(FromBin(data[pos+1 : pos+1+b]))
- return data[pos+1+b : pos+1+b+b2], pos+1+b+b2
-
- case char < 184:
- b := int(data[pos]) - 128
- pos++
- for i := 0; i < b; i++ {
- var obj interface{}
-
- obj, pos = Decode(data, pos)
- slice = append(slice, obj)
- }
- return slice, pos
-
- case char < 192:
- b := int(data[pos]) - 183
- //b2 := int(FromBin(data[pos+1 : pos+1+b])) (ref implementation has an unused variable)
- pos = pos+1+b
- for i := 0; i < b; i++ {
- var obj interface{}
-
- obj, pos = Decode(data, pos)
- slice = append(slice, obj)
- }
- return slice, pos
-
- default:
- panic(fmt.Sprintf("byte not supported: %q", char))
- }
-
- return slice, 0
+ if pos > len(data)-1 {
+ panic(fmt.Sprintf("index out of range %d for data %q, l = %d", pos, data, len(data)))
+ }
+
+ char := int(data[pos])
+ slice := make([]interface{}, 0)
+ switch {
+ case char < 24:
+ return data[pos], pos + 1
+
+ case char < 56:
+ b := int(data[pos]) - 23
+ return FromBin(data[pos+1 : pos+1+b]), pos + 1 + b
+
+ case char < 64:
+ b := int(data[pos]) - 55
+ b2 := int(FromBin(data[pos+1 : pos+1+b]))
+ return FromBin(data[pos+1+b : pos+1+b+b2]), pos + 1 + b + b2
+
+ case char < 120:
+ b := int(data[pos]) - 64
+ return data[pos+1 : pos+1+b], pos + 1 + b
+
+ case char < 128:
+ b := int(data[pos]) - 119
+ b2 := int(FromBin(data[pos+1 : pos+1+b]))
+ return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2
+
+ case char < 184:
+ b := int(data[pos]) - 128
+ pos++
+ for i := 0; i < b; i++ {
+ var obj interface{}
+
+ obj, pos = Decode(data, pos)
+ slice = append(slice, obj)
+ }
+ return slice, pos
+
+ case char < 192:
+ b := int(data[pos]) - 183
+ //b2 := int(FromBin(data[pos+1 : pos+1+b])) (ref implementation has an unused variable)
+ pos = pos + 1 + b
+ for i := 0; i < b; i++ {
+ var obj interface{}
+
+ obj, pos = Decode(data, pos)
+ slice = append(slice, obj)
+ }
+ return slice, pos
+
+ default:
+ panic(fmt.Sprintf("byte not supported: %q", char))
+ }
+
+ return slice, 0
}
func Encode(object interface{}) []byte {
- var buff bytes.Buffer
-
- switch t := object.(type) {
- case uint32, uint64:
- var num uint64
- if _num, ok := t.(uint64); ok {
- num = _num
- } else if _num, ok := t.(uint32); ok {
- num = uint64(_num)
- }
-
- if num >= 0 && num < 24 {
- buff.WriteString(string(num))
- } else if num <= uint64(math.Pow(2, 256)) {
- b := ToBin(num, 0)
- buff.WriteString(string(len(b) + 23) + b)
- } else {
- b := ToBin(num, 0)
- b2 := ToBin(uint64(len(b)), 0)
- buff.WriteString(string(len(b2) + 55) + b2 + b)
- }
-
- case *big.Int:
- buff.Write(Encode(t.String()))
-
- case string:
- if len(t) < 56 {
- buff.WriteString(string(len(t) + 64) + t)
- } else {
- b2 := ToBin(uint64(len(t)), 0)
- buff.WriteString(string(len(b2) + 119) + b2 + t)
- }
-
- case []byte:
- // Cast the byte slice to a string
- buff.Write(Encode(string(t)))
-
- case []interface{}, []string:
- // Inline function for writing the slice header
- WriteSliceHeader := func(length int) {
- if length < 56 {
- buff.WriteByte(byte(length + 128))
- } else {
- b2 := ToBin(uint64(length), 0)
- buff.WriteByte(byte(len(b2) + 183))
- buff.WriteString(b2)
- }
- }
-
- // FIXME How can I do this "better"?
- if interSlice, ok := t.([]interface{}); ok {
- WriteSliceHeader(len(interSlice))
- for _, val := range interSlice {
- buff.Write(Encode(val))
- }
- } else if stringSlice, ok := t.([]string); ok {
- WriteSliceHeader(len(stringSlice))
- for _, val := range stringSlice {
- buff.Write(Encode(val))
- }
- }
- }
-
- return buff.Bytes()
+ var buff bytes.Buffer
+
+ switch t := object.(type) {
+ case uint32, uint64:
+ var num uint64
+ if _num, ok := t.(uint64); ok {
+ num = _num
+ } else if _num, ok := t.(uint32); ok {
+ num = uint64(_num)
+ }
+
+ if num >= 0 && num < 24 {
+ buff.WriteString(string(num))
+ } else if num <= uint64(math.Pow(2, 256)) {
+ b := ToBin(num, 0)
+ buff.WriteString(string(len(b)+23) + b)
+ } else {
+ b := ToBin(num, 0)
+ b2 := ToBin(uint64(len(b)), 0)
+ buff.WriteString(string(len(b2)+55) + b2 + b)
+ }
+
+ case *big.Int:
+ buff.Write(Encode(t.String()))
+
+ case string:
+ if len(t) < 56 {
+ buff.WriteString(string(len(t)+64) + t)
+ } else {
+ b2 := ToBin(uint64(len(t)), 0)
+ buff.WriteString(string(len(b2)+119) + b2 + t)
+ }
+
+ case []byte:
+ // Cast the byte slice to a string
+ buff.Write(Encode(string(t)))
+
+ case []interface{}, []string:
+ // Inline function for writing the slice header
+ WriteSliceHeader := func(length int) {
+ if length < 56 {
+ buff.WriteByte(byte(length + 128))
+ } else {
+ b2 := ToBin(uint64(length), 0)
+ buff.WriteByte(byte(len(b2) + 183))
+ buff.WriteString(b2)
+ }
+ }
+
+ // FIXME How can I do this "better"?
+ if interSlice, ok := t.([]interface{}); ok {
+ WriteSliceHeader(len(interSlice))
+ for _, val := range interSlice {
+ buff.Write(Encode(val))
+ }
+ } else if stringSlice, ok := t.([]string); ok {
+ WriteSliceHeader(len(stringSlice))
+ for _, val := range stringSlice {
+ buff.Write(Encode(val))
+ }
+ }
+ }
+
+ return buff.Bytes()
}
diff --git a/rlp_test.go b/rlp_test.go
index 68676d030..65cf34b39 100644
--- a/rlp_test.go
+++ b/rlp_test.go
@@ -1,54 +1,54 @@
package main
import (
- "testing"
- "fmt"
+ "fmt"
+ "testing"
)
func TestEncode(t *testing.T) {
- strRes := "Cdog"
+ strRes := "Cdog"
- bytes := Encode("dog")
+ bytes := Encode("dog")
- str := string(bytes)
- if str != strRes {
- t.Error(fmt.Sprintf("Expected %q, got %q", strRes, str))
- }
- //dec,_ := Decode(bytes, 0)
+ str := string(bytes)
+ if str != strRes {
+ t.Error(fmt.Sprintf("Expected %q, got %q", strRes, str))
+ }
+ //dec,_ := Decode(bytes, 0)
- sliceRes := "\x83CdogCgodCcat"
- strs := []string{"dog", "god", "cat"}
- bytes = Encode(strs)
- slice := string(bytes)
- if slice != sliceRes {
- t.Error(fmt.Sprintf("Expected %q, got %q", sliceRes, slice))
- }
+ sliceRes := "\x83CdogCgodCcat"
+ strs := []string{"dog", "god", "cat"}
+ bytes = Encode(strs)
+ slice := string(bytes)
+ if slice != sliceRes {
+ t.Error(fmt.Sprintf("Expected %q, got %q", sliceRes, slice))
+ }
- //dec,_ = Decode(bytes, 0)
+ //dec,_ = Decode(bytes, 0)
}
func TestMultiEncode(t *testing.T) {
- inter := []interface{}{
- []interface{}{
- "1","2","3",
- },
- []string{
- "string",
- "string2",
- "\x86A0J1234567890A\x00B20A0\x82F395843F657986",
- "\x86A0J1234567890A\x00B20A0\x8cF395843F657986I335612448F524099H16716881A0H13114947G2039362G1507139H16719697G1048387E65360",
- },
- "test",
- }
-
- bytes := Encode(inter)
-
- Decode(bytes, 0)
+ inter := []interface{}{
+ []interface{}{
+ "1", "2", "3",
+ },
+ []string{
+ "string",
+ "string2",
+ "\x86A0J1234567890A\x00B20A0\x82F395843F657986",
+ "\x86A0J1234567890A\x00B20A0\x8cF395843F657986I335612448F524099H16716881A0H13114947G2039362G1507139H16719697G1048387E65360",
+ },
+ "test",
+ }
+
+ bytes := Encode(inter)
+
+ Decode(bytes, 0)
}
func BenchmarkEncodeDecode(b *testing.B) {
- for i := 0; i < b.N; i++ {
- bytes := Encode([]string{"dog", "god", "cat"})
- Decode(bytes, 0)
- }
+ for i := 0; i < b.N; i++ {
+ bytes := Encode([]string{"dog", "god", "cat"})
+ Decode(bytes, 0)
+ }
}
diff --git a/server.go b/server.go
index d81fe1bce..5373e2418 100644
--- a/server.go
+++ b/server.go
@@ -1,121 +1,120 @@
package main
import (
- "container/list"
- "net"
- "log"
- _"time"
- "github.com/ethereum/ethdb-go"
- "github.com/ethereum/ethutil-go"
+ "container/list"
+ "github.com/ethereum/ethdb-go"
+ "github.com/ethereum/ethutil-go"
+ "log"
+ "net"
+ _ "time"
)
type Server struct {
- // Channel for shutting down the server
- shutdownChan chan bool
- // DB interface
- db *ethdb.LDBDatabase
- // Block manager for processing new blocks and managing the block chain
- blockManager *BlockManager
- // Peers (NYI)
- peers *list.List
+ // Channel for shutting down the server
+ shutdownChan chan bool
+ // DB interface
+ db *ethdb.LDBDatabase
+ // Block manager for processing new blocks and managing the block chain
+ blockManager *BlockManager
+ // Peers (NYI)
+ peers *list.List
}
func NewServer() (*Server, error) {
- db, err := ethdb.NewLDBDatabase()
- if err != nil {
- return nil, err
- }
+ db, err := ethdb.NewLDBDatabase()
+ if err != nil {
+ return nil, err
+ }
- ethutil.SetConfig(db)
+ ethutil.SetConfig(db)
- server := &Server{
- shutdownChan: make(chan bool),
- blockManager: NewBlockManager(),
- db: db,
- peers: list.New(),
- }
+ server := &Server{
+ shutdownChan: make(chan bool),
+ blockManager: NewBlockManager(),
+ db: db,
+ peers: list.New(),
+ }
- return server, nil
+ return server, nil
}
func (s *Server) AddPeer(conn net.Conn) {
- peer := NewPeer(conn, s)
- s.peers.PushBack(peer)
- peer.Start()
+ peer := NewPeer(conn, s)
+ s.peers.PushBack(peer)
+ peer.Start()
- log.Println("Peer connected ::", conn.RemoteAddr())
+ log.Println("Peer connected ::", conn.RemoteAddr())
}
func (s *Server) ConnectToPeer(addr string) error {
- conn, err := net.Dial("tcp", addr)
+ conn, err := net.Dial("tcp", addr)
- if err != nil {
- return err
- }
+ if err != nil {
+ return err
+ }
- peer := NewPeer(conn, s)
- s.peers.PushBack(peer)
- peer.Start()
+ peer := NewPeer(conn, s)
+ s.peers.PushBack(peer)
+ peer.Start()
+ log.Println("Connected to peer ::", conn.RemoteAddr())
- log.Println("Connected to peer ::", conn.RemoteAddr())
-
- return nil
+ return nil
}
func (s *Server) Broadcast(msgType string, data []byte) {
- for e := s.peers.Front(); e != nil; e = e.Next() {
- if peer, ok := e.Value.(*Peer); ok {
- peer.QueueMessage(msgType, data)
- }
- }
+ for e := s.peers.Front(); e != nil; e = e.Next() {
+ if peer, ok := e.Value.(*Peer); ok {
+ peer.QueueMessage(msgType, data)
+ }
+ }
}
// Start the server
func (s *Server) Start() {
- // For now this function just blocks the main thread
- ln, err := net.Listen("tcp", ":12345")
- if err != nil {
- log.Fatal(err)
- }
-
- go func() {
- for {
- conn, err := ln.Accept()
- if err != nil {
- log.Println(err)
- continue
- }
-
- go s.AddPeer(conn)
- }
- }()
-
- // TMP
- //go func() {
- // for {
- // s.Broadcast("block", Encode("blockdata"))
-//
-// time.Sleep(100 * time.Millisecond)
-// }
-// }()
+ // For now this function just blocks the main thread
+ ln, err := net.Listen("tcp", ":12345")
+ if err != nil {
+ log.Fatal(err)
+ }
+
+ go func() {
+ for {
+ conn, err := ln.Accept()
+ if err != nil {
+ log.Println(err)
+ continue
+ }
+
+ go s.AddPeer(conn)
+ }
+ }()
+
+ // TMP
+ //go func() {
+ // for {
+ // s.Broadcast("block", Encode("blockdata"))
+ //
+ // time.Sleep(100 * time.Millisecond)
+ // }
+ // }()
}
func (s *Server) Stop() {
- // Close the database
- defer s.db.Close()
+ // Close the database
+ defer s.db.Close()
- // Loop thru the peers and close them (if we had them)
- for e := s.peers.Front(); e != nil; e = e.Next() {
- if peer, ok := e.Value.(*Peer); ok {
- peer.Stop()
- }
- }
+ // Loop thru the peers and close them (if we had them)
+ for e := s.peers.Front(); e != nil; e = e.Next() {
+ if peer, ok := e.Value.(*Peer); ok {
+ peer.Stop()
+ }
+ }
- s.shutdownChan <- true
+ s.shutdownChan <- true
}
// This function will wait for a shutdown and resumes main thread execution
func (s *Server) WaitForShutdown() {
- <- s.shutdownChan
+ <-s.shutdownChan
}
diff --git a/test_runner.go b/test_runner.go
index da93533dd..e8a1698ce 100644
--- a/test_runner.go
+++ b/test_runner.go
@@ -1,35 +1,35 @@
package main
import (
- "fmt"
- "testing"
- "encoding/json"
+ "encoding/json"
+ "fmt"
+ "testing"
)
type TestSource struct {
- Inputs map[string]string
- Expectation string
+ Inputs map[string]string
+ Expectation string
}
func NewTestSource(source string) *TestSource {
- s := &TestSource{}
- err := json.Unmarshal([]byte(source), s)
- if err != nil {
- fmt.Println(err)
- }
+ s := &TestSource{}
+ err := json.Unmarshal([]byte(source), s)
+ if err != nil {
+ fmt.Println(err)
+ }
- return s
+ return s
}
type TestRunner struct {
- source *TestSource
+ source *TestSource
}
func NewTestRunner(t *testing.T) *TestRunner {
- return &TestRunner{}
+ return &TestRunner{}
}
func (runner *TestRunner) RunFromString(input string, Cb func(*TestSource)) {
- source := NewTestSource(input)
- Cb(source)
+ source := NewTestSource(input)
+ Cb(source)
}
diff --git a/test_runner_test.go b/test_runner_test.go
index 190bf3caf..5abe20002 100644
--- a/test_runner_test.go
+++ b/test_runner_test.go
@@ -1,9 +1,9 @@
package main
import (
- _"fmt"
- "testing"
- "encoding/hex"
+ "encoding/hex"
+ _ "fmt"
+ "testing"
)
var testsource = `{"Inputs":{
@@ -15,17 +15,17 @@ var testsource = `{"Inputs":{
}`
func TestTestRunner(t *testing.T) {
- db, _ := NewMemDatabase()
- trie := NewTrie(db, "")
+ db, _ := NewMemDatabase()
+ trie := NewTrie(db, "")
- runner := NewTestRunner(t)
- runner.RunFromString(testsource, func(source *TestSource) {
- for key, value := range source.Inputs {
- trie.Update(key, value)
- }
+ runner := NewTestRunner(t)
+ runner.RunFromString(testsource, func(source *TestSource) {
+ for key, value := range source.Inputs {
+ trie.Update(key, value)
+ }
- if hex.EncodeToString([]byte(trie.root)) != source.Expectation {
- t.Error("trie root did not match")
- }
- })
+ if hex.EncodeToString([]byte(trie.root)) != source.Expectation {
+ t.Error("trie root did not match")
+ }
+ })
}
diff --git a/testing.go b/testing.go
index 9b7b7b3ce..5e2aec02b 100644
--- a/testing.go
+++ b/testing.go
@@ -1,4 +1,5 @@
package main
+
/*
import (
diff --git a/vm.go b/vm.go
index 5605cb7c7..96a3dfa05 100644
--- a/vm.go
+++ b/vm.go
@@ -1,267 +1,284 @@
package main
import (
- "math/big"
- "fmt"
- "strconv"
- "github.com/ethereum/ethutil-go"
+ "fmt"
+ "github.com/ethereum/ethutil-go"
+ "math/big"
+ "strconv"
)
// Op codes
const (
- oSTOP int = 0x00
- oADD int = 0x01
- oMUL int = 0x02
- oSUB int = 0x03
- oDIV int = 0x04
- oSDIV int = 0x05
- oMOD int = 0x06
- oSMOD int = 0x07
- oEXP int = 0x08
- oNEG int = 0x09
- oLT int = 0x0a
- oLE int = 0x0b
- oGT int = 0x0c
- oGE int = 0x0d
- oEQ int = 0x0e
- oNOT int = 0x0f
- oMYADDRESS int = 0x10
- oTXSENDER int = 0x11
- oTXVALUE int = 0x12
- oTXFEE int = 0x13
- oTXDATAN int = 0x14
- oTXDATA int = 0x15
- oBLK_PREVHASH int = 0x16
- oBLK_COINBASE int = 0x17
- oBLK_TIMESTAMP int = 0x18
- oBLK_NUMBER int = 0x19
- oBLK_DIFFICULTY int = 0x1a
- oSHA256 int = 0x20
- oRIPEMD160 int = 0x21
- oECMUL int = 0x22
- oECADD int = 0x23
- oECSIGN int = 0x24
- oECRECOVER int = 0x25
- oECVALID int = 0x26
- oPUSH int = 0x30
- oPOP int = 0x31
- oDUP int = 0x32
- oDUPN int = 0x33
- oSWAP int = 0x34
- oSWAPN int = 0x35
- oLOAD int = 0x36
- oSTORE int = 0x37
- oJMP int = 0x40
- oJMPI int = 0x41
- oIND int = 0x42
- oEXTRO int = 0x50
- oBALANCE int = 0x51
- oMKTX int = 0x60
- oSUICIDE int = 0xff
+ oSTOP int = 0x00
+ oADD int = 0x01
+ oMUL int = 0x02
+ oSUB int = 0x03
+ oDIV int = 0x04
+ oSDIV int = 0x05
+ oMOD int = 0x06
+ oSMOD int = 0x07
+ oEXP int = 0x08
+ oNEG int = 0x09
+ oLT int = 0x0a
+ oLE int = 0x0b
+ oGT int = 0x0c
+ oGE int = 0x0d
+ oEQ int = 0x0e
+ oNOT int = 0x0f
+ oMYADDRESS int = 0x10
+ oTXSENDER int = 0x11
+ oTXVALUE int = 0x12
+ oTXFEE int = 0x13
+ oTXDATAN int = 0x14
+ oTXDATA int = 0x15
+ oBLK_PREVHASH int = 0x16
+ oBLK_COINBASE int = 0x17
+ oBLK_TIMESTAMP int = 0x18
+ oBLK_NUMBER int = 0x19
+ oBLK_DIFFICULTY int = 0x1a
+ oSHA256 int = 0x20
+ oRIPEMD160 int = 0x21
+ oECMUL int = 0x22
+ oECADD int = 0x23
+ oECSIGN int = 0x24
+ oECRECOVER int = 0x25
+ oECVALID int = 0x26
+ oPUSH int = 0x30
+ oPOP int = 0x31
+ oDUP int = 0x32
+ oDUPN int = 0x33
+ oSWAP int = 0x34
+ oSWAPN int = 0x35
+ oLOAD int = 0x36
+ oSTORE int = 0x37
+ oJMP int = 0x40
+ oJMPI int = 0x41
+ oIND int = 0x42
+ oEXTRO int = 0x50
+ oBALANCE int = 0x51
+ oMKTX int = 0x60
+ oSUICIDE int = 0xff
)
type OpType int
+
const (
- tNorm = iota
- tData
- tExtro
- tCrypto
+ tNorm = iota
+ tData
+ tExtro
+ tCrypto
)
+
type TxCallback func(opType OpType) bool
// Simple push/pop stack mechanism
type Stack struct {
- data []string
+ data []string
}
+
func NewStack() *Stack {
- return &Stack{}
+ return &Stack{}
}
func (st *Stack) Pop() string {
- s := len(st.data)
+ s := len(st.data)
- str := st.data[s-1]
- st.data = st.data[:s-1]
+ str := st.data[s-1]
+ st.data = st.data[:s-1]
- return str
+ return str
}
func (st *Stack) Popn() (*big.Int, *big.Int) {
- s := len(st.data)
+ s := len(st.data)
- strs := st.data[s-2:]
- st.data = st.data[:s-2]
+ strs := st.data[s-2:]
+ st.data = st.data[:s-2]
- return ethutil.Big(strs[0]), ethutil.Big(strs[1])
+ return ethutil.Big(strs[0]), ethutil.Big(strs[1])
}
func (st *Stack) Push(d string) {
- st.data = append(st.data, d)
+ st.data = append(st.data, d)
}
func (st *Stack) Print() {
- fmt.Println(st.data)
+ fmt.Println(st.data)
}
type Vm struct {
- // Stack
- stack *Stack
+ // Stack
+ stack *Stack
}
func NewVm() *Vm {
- return &Vm{
- stack: NewStack(),
- }
+ return &Vm{
+ stack: NewStack(),
+ }
}
-func (vm *Vm) ProcContract( tx *ethutil.Transaction,
- block *ethutil.Block, cb TxCallback) {
- // Instruction pointer
- pc := 0
+func (vm *Vm) ProcContract(tx *ethutil.Transaction,
+ block *ethutil.Block, cb TxCallback) {
+ // Instruction pointer
+ pc := 0
- contract := block.GetContract(tx.Hash())
- if contract == nil {
- fmt.Println("Contract not found")
- return
- }
+ contract := block.GetContract(tx.Hash())
+ if contract == nil {
+ fmt.Println("Contract not found")
+ return
+ }
- Pow256 := ethutil.BigPow(2, 256)
+ Pow256 := ethutil.BigPow(2, 256)
- //fmt.Printf("# op arg\n")
+ //fmt.Printf("# op arg\n")
out:
- for {
- // The base big int for all calculations. Use this for any results.
- base := new(big.Int)
- // XXX Should Instr return big int slice instead of string slice?
- // Get the next instruction from the contract
- //op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
- nb := ethutil.NumberToBytes(uint64(pc), 32)
- op, _, _ := ethutil.Instr(contract.State().Get(string(nb)))
+ for {
+ // The base big int for all calculations. Use this for any results.
+ base := new(big.Int)
+ // XXX Should Instr return big int slice instead of string slice?
+ // Get the next instruction from the contract
+ //op, _, _ := Instr(contract.state.Get(string(Encode(uint32(pc)))))
+ nb := ethutil.NumberToBytes(uint64(pc), 32)
+ op, _, _ := ethutil.Instr(contract.State().Get(string(nb)))
- if !cb(0) { break }
+ if !cb(0) {
+ break
+ }
- if Debug {
- //fmt.Printf("%-3d %-4d\n", pc, op)
- }
+ if Debug {
+ //fmt.Printf("%-3d %-4d\n", pc, op)
+ }
- switch op {
- case oADD:
- x, y := vm.stack.Popn()
- // (x + y) % 2 ** 256
- base.Add(x, y)
- base.Mod(base, Pow256)
- // Pop result back on the stack
- vm.stack.Push(base.String())
- case oSUB:
- x, y := vm.stack.Popn()
- // (x - y) % 2 ** 256
- base.Sub(x, y)
- base.Mod(base, Pow256)
- // Pop result back on the stack
- vm.stack.Push(base.String())
- case oMUL:
- x, y := vm.stack.Popn()
- // (x * y) % 2 ** 256
- base.Mul(x, y)
- base.Mod(base, Pow256)
- // Pop result back on the stack
- vm.stack.Push(base.String())
- case oDIV:
- x, y := vm.stack.Popn()
- // floor(x / y)
- base.Div(x, y)
- // Pop result back on the stack
- vm.stack.Push(base.String())
- case oSDIV:
- x, y := vm.stack.Popn()
- // n > 2**255
- if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) }
- if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) }
- z := new(big.Int)
- z.Div(x, y)
- if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) }
- // Push result on to the stack
- vm.stack.Push(z.String())
- case oMOD:
- x, y := vm.stack.Popn()
- base.Mod(x, y)
- vm.stack.Push(base.String())
- case oSMOD:
- x, y := vm.stack.Popn()
- // n > 2**255
- if x.Cmp(Pow256) > 0 { x.Sub(Pow256, x) }
- if y.Cmp(Pow256) > 0 { y.Sub(Pow256, y) }
- z := new(big.Int)
- z.Mod(x, y)
- if z.Cmp(Pow256) > 0 { z.Sub(Pow256, z) }
- // Push result on to the stack
- vm.stack.Push(z.String())
- case oEXP:
- x, y := vm.stack.Popn()
- base.Exp(x, y, Pow256)
+ switch op {
+ case oADD:
+ x, y := vm.stack.Popn()
+ // (x + y) % 2 ** 256
+ base.Add(x, y)
+ base.Mod(base, Pow256)
+ // Pop result back on the stack
+ vm.stack.Push(base.String())
+ case oSUB:
+ x, y := vm.stack.Popn()
+ // (x - y) % 2 ** 256
+ base.Sub(x, y)
+ base.Mod(base, Pow256)
+ // Pop result back on the stack
+ vm.stack.Push(base.String())
+ case oMUL:
+ x, y := vm.stack.Popn()
+ // (x * y) % 2 ** 256
+ base.Mul(x, y)
+ base.Mod(base, Pow256)
+ // Pop result back on the stack
+ vm.stack.Push(base.String())
+ case oDIV:
+ x, y := vm.stack.Popn()
+ // floor(x / y)
+ base.Div(x, y)
+ // Pop result back on the stack
+ vm.stack.Push(base.String())
+ case oSDIV:
+ x, y := vm.stack.Popn()
+ // n > 2**255
+ if x.Cmp(Pow256) > 0 {
+ x.Sub(Pow256, x)
+ }
+ if y.Cmp(Pow256) > 0 {
+ y.Sub(Pow256, y)
+ }
+ z := new(big.Int)
+ z.Div(x, y)
+ if z.Cmp(Pow256) > 0 {
+ z.Sub(Pow256, z)
+ }
+ // Push result on to the stack
+ vm.stack.Push(z.String())
+ case oMOD:
+ x, y := vm.stack.Popn()
+ base.Mod(x, y)
+ vm.stack.Push(base.String())
+ case oSMOD:
+ x, y := vm.stack.Popn()
+ // n > 2**255
+ if x.Cmp(Pow256) > 0 {
+ x.Sub(Pow256, x)
+ }
+ if y.Cmp(Pow256) > 0 {
+ y.Sub(Pow256, y)
+ }
+ z := new(big.Int)
+ z.Mod(x, y)
+ if z.Cmp(Pow256) > 0 {
+ z.Sub(Pow256, z)
+ }
+ // Push result on to the stack
+ vm.stack.Push(z.String())
+ case oEXP:
+ x, y := vm.stack.Popn()
+ base.Exp(x, y, Pow256)
- vm.stack.Push(base.String())
- case oNEG:
- base.Sub(Pow256, ethutil.Big(vm.stack.Pop()))
- vm.stack.Push(base.String())
- case oLT:
- x, y := vm.stack.Popn()
- // x < y
- if x.Cmp(y) < 0 {
- vm.stack.Push("1")
- } else {
- vm.stack.Push("0")
- }
- case oLE:
- x, y := vm.stack.Popn()
- // x <= y
- if x.Cmp(y) < 1 {
- vm.stack.Push("1")
- } else {
- vm.stack.Push("0")
- }
- case oGT:
- x, y := vm.stack.Popn()
- // x > y
- if x.Cmp(y) > 0 {
- vm.stack.Push("1")
- } else {
- vm.stack.Push("0")
- }
- case oGE:
- x, y := vm.stack.Popn()
- // x >= y
- if x.Cmp(y) > -1 {
- vm.stack.Push("1")
- } else {
- vm.stack.Push("0")
- }
- case oNOT:
- x, y := vm.stack.Popn()
- // x != y
- if x.Cmp(y) != 0 {
- vm.stack.Push("1")
- } else {
- vm.stack.Push("0")
- }
- case oMYADDRESS:
- vm.stack.Push(string(tx.Hash()))
- case oTXSENDER:
- vm.stack.Push(string(tx.Sender()))
- case oPUSH:
- // Get the next entry and pushes the value on the stack
- pc++
- vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(pc), 32))))
- case oPOP:
- // Pop current value of the stack
- vm.stack.Pop()
- case oLOAD:
- // Load instruction X on the stack
- i, _ := strconv.Atoi(vm.stack.Pop())
- vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32))))
- case oSTOP:
- break out
- }
- pc++
- }
+ vm.stack.Push(base.String())
+ case oNEG:
+ base.Sub(Pow256, ethutil.Big(vm.stack.Pop()))
+ vm.stack.Push(base.String())
+ case oLT:
+ x, y := vm.stack.Popn()
+ // x < y
+ if x.Cmp(y) < 0 {
+ vm.stack.Push("1")
+ } else {
+ vm.stack.Push("0")
+ }
+ case oLE:
+ x, y := vm.stack.Popn()
+ // x <= y
+ if x.Cmp(y) < 1 {
+ vm.stack.Push("1")
+ } else {
+ vm.stack.Push("0")
+ }
+ case oGT:
+ x, y := vm.stack.Popn()
+ // x > y
+ if x.Cmp(y) > 0 {
+ vm.stack.Push("1")
+ } else {
+ vm.stack.Push("0")
+ }
+ case oGE:
+ x, y := vm.stack.Popn()
+ // x >= y
+ if x.Cmp(y) > -1 {
+ vm.stack.Push("1")
+ } else {
+ vm.stack.Push("0")
+ }
+ case oNOT:
+ x, y := vm.stack.Popn()
+ // x != y
+ if x.Cmp(y) != 0 {
+ vm.stack.Push("1")
+ } else {
+ vm.stack.Push("0")
+ }
+ case oMYADDRESS:
+ vm.stack.Push(string(tx.Hash()))
+ case oTXSENDER:
+ vm.stack.Push(string(tx.Sender()))
+ case oPUSH:
+ // Get the next entry and pushes the value on the stack
+ pc++
+ vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(pc), 32))))
+ case oPOP:
+ // Pop current value of the stack
+ vm.stack.Pop()
+ case oLOAD:
+ // Load instruction X on the stack
+ i, _ := strconv.Atoi(vm.stack.Pop())
+ vm.stack.Push(contract.State().Get(string(ethutil.NumberToBytes(uint64(i), 32))))
+ case oSTOP:
+ break out
+ }
+ pc++
+ }
- vm.stack.Print()
+ vm.stack.Print()
}