aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <obscuren@obscura.com>2013-12-30 06:54:50 +0800
committerobscuren <obscuren@obscura.com>2013-12-30 06:54:50 +0800
commita926686445929d091c2d9e019b017600168e9e47 (patch)
treea328e4f79148461c076b0bd122c591f0bfd213c2
parentad048e9f445ff96b7bfd75c104ab923e1e06754b (diff)
downloadgo-tangerine-a926686445929d091c2d9e019b017600168e9e47.tar.gz
go-tangerine-a926686445929d091c2d9e019b017600168e9e47.tar.zst
go-tangerine-a926686445929d091c2d9e019b017600168e9e47.zip
Added sample server, genesis block, and database interface
-rw-r--r--database.go94
-rw-r--r--database_test.go43
-rw-r--r--genesis.go36
-rw-r--r--server.go55
4 files changed, 228 insertions, 0 deletions
diff --git a/database.go b/database.go
new file mode 100644
index 000000000..f74c1dc7f
--- /dev/null
+++ b/database.go
@@ -0,0 +1,94 @@
+package main
+
+import (
+ "path"
+ "os/user"
+ "github.com/syndtr/goleveldb/leveldb"
+ "fmt"
+)
+
+type Database struct {
+ db *leveldb.DB
+ trie *Trie
+}
+
+func NewDatabase() (*Database, error) {
+ // This will eventually have to be something like a resource folder.
+ // it works on my system for now. Probably won't work on Windows
+ usr, _ := user.Current()
+ dbPath := path.Join(usr.HomeDir, ".ethereum", "database")
+
+ // Open the db
+ db, err := leveldb.OpenFile(dbPath, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ database := &Database{db: db}
+
+ // Bootstrap database. Sets a few defaults; such as the last block
+ database.Bootstrap()
+
+ return database, nil
+}
+
+func (db *Database) Bootstrap() error {
+ db.trie = NewTrie(db)
+
+ return nil
+}
+
+func (db *Database) Put(key []byte, value []byte) {
+ err := db.db.Put(key, value, nil)
+ if err != nil {
+ fmt.Println("Error put", err)
+ }
+}
+
+func (db *Database) Close() {
+ // Close the leveldb database
+ db.db.Close()
+}
+
+type Trie struct {
+ root string
+ db *Database
+}
+
+func NewTrie(db *Database) *Trie {
+ return &Trie{db: db, root: ""}
+}
+
+func (t *Trie) Update(key string, value string) {
+ k := CompactHexDecode(key)
+
+ t.root = t.UpdateState(t.root, k, value)
+}
+
+func (t *Trie) Get(key []byte) ([]byte, error) {
+ return nil, nil
+}
+
+// Inserts a new sate or delete a state based on the value
+func (t *Trie) UpdateState(node, key, value string) string {
+ if value != "" {
+ return t.InsertState(node, key, value)
+ } else {
+ // delete it
+ }
+
+ return ""
+}
+
+func (t *Trie) InsertState(node, key, value string) string {
+ return ""
+}
+
+func (t *Trie) Put(node []byte) []byte {
+ enc := Encode(node)
+ sha := Sha256Bin(enc)
+
+ t.db.Put([]byte(sha), enc)
+
+ return sha
+}
diff --git a/database_test.go b/database_test.go
new file mode 100644
index 000000000..c1a6c7d16
--- /dev/null
+++ b/database_test.go
@@ -0,0 +1,43 @@
+package main
+
+import (
+ "testing"
+ _"fmt"
+)
+
+func TestTriePut(t *testing.T) {
+ db, err := NewDatabase()
+ defer db.Close()
+
+ if err != nil {
+ t.Error("Error starting db")
+ }
+
+ key := db.trie.Put([]byte("testing node"))
+
+ data, err := db.db.Get(key, nil)
+ if err != nil {
+ t.Error("Nothing at node")
+ }
+
+ s, _ := Decode(data, 0)
+ if str, ok := s.([]byte); ok {
+ if string(str) != "testing node" {
+ t.Error("Wrong value node", str)
+ }
+ } else {
+ t.Error("Invalid return type")
+ }
+}
+
+func TestTrieUpdate(t *testing.T) {
+ db, err := NewDatabase()
+ defer db.Close()
+
+ if err != nil {
+ t.Error("Error starting db")
+ }
+
+ db.trie.Update("test", "test")
+}
+
diff --git a/genesis.go b/genesis.go
new file mode 100644
index 000000000..aae9cd1cf
--- /dev/null
+++ b/genesis.go
@@ -0,0 +1,36 @@
+package main
+
+import (
+ "math"
+)
+
+/*
+ * This is the special genesis block.
+ */
+
+var GenisisHeader = []interface{}{
+ // Block number
+ uint32(0),
+ // Previous hash (none)
+ "",
+ // Sha of uncles
+ string(Sha256Bin(Encode([]interface{}{}))),
+ // Coinbase
+ "",
+ // Root state
+ "",
+ // Sha of transactions
+ string(Sha256Bin(Encode([]interface{}{}))),
+ // Difficulty
+ uint32(math.Pow(2, 36)),
+ // Time
+ uint64(1),
+ // Nonce
+ uint32(0),
+ // Extra
+ "",
+}
+
+var Genesis = []interface{}{ GenisisHeader, []interface{}{}, []interface{}{} }
+
+var GenisisBlock = NewBlock( Encode(Genesis) )
diff --git a/server.go b/server.go
new file mode 100644
index 000000000..0c7488787
--- /dev/null
+++ b/server.go
@@ -0,0 +1,55 @@
+package main
+
+import (
+ "container/list"
+ "time"
+)
+
+type Server struct {
+ // Channel for shutting down the server
+ shutdownChan chan bool
+ // DB interface
+ db *Database
+ // Peers (NYI)
+ peers *list.List
+}
+
+func NewServer() (*Server, error) {
+ db, err := NewDatabase()
+ if err != nil {
+ return nil, err
+ }
+
+ server := &Server{
+ shutdownChan: make(chan bool),
+ db: db,
+ peers: list.New(),
+ }
+
+ return server, nil
+}
+
+// Start the server
+func (s *Server) Start() {
+ // For now this function just blocks the main thread
+ for {
+ time.Sleep( time.Second )
+ }
+}
+
+func (s *Server) Stop() {
+ // 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() {
+ // peer close etc
+ }
+
+ s.shutdownChan <- true
+}
+
+// This function will wait for a shutdown and resumes main thread execution
+func (s *Server) WaitForShutdown() {
+ <- s.shutdownChan
+}