diff --git a/.gitignore b/.gitignore index 5c51faa..ed00c96 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ .idea/ **/.DS_Store +nodes.db +masternode.conf \ No newline at end of file diff --git a/README.md b/README.md index bfe9bbf..6796c1c 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,8 @@ There is a coinconf generator included that can auto-generate settings for most The string to use for the sentinel version number (i.e. 1.20.0) (default "0.0.0") -user_agent The user agent string to connect to remote peers with. + -db_path + The destination for database storage (default path is ./peers.db) ``` ## Building (using Docker) diff --git a/cmd/phantom/main.go b/cmd/phantom/main.go index 86f5d81..a6a1b32 100644 --- a/cmd/phantom/main.go +++ b/cmd/phantom/main.go @@ -34,6 +34,7 @@ import ( "flag" "fmt" "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/jackkdev/phantom/pkg/storage" "log" "github.com/breakcrypto/phantom/pkg/socket/wire" "github.com/breakcrypto/phantom/pkg/phantom" @@ -90,7 +91,6 @@ func main() { flag.StringVar(&userAgent, "user_agent", "@_breakcrypto phantom", "The user agent string to connect to remote peers with.") - flag.Parse() if coinConfString != "" { @@ -291,6 +291,14 @@ func processNewHashes(hashChannel chan chainhash.Hash, queue *phantom.Queue) { } func processNewAddresses(addrChannel chan wire.NetAddress, peerSet map[string]wire.NetAddress) { + + // init database + db, err := storage.SetupDB() + if err != nil { + log.Fatal("an error occurred:", err) + return + } + for { addr := <-addrChannel @@ -299,23 +307,47 @@ func processNewAddresses(addrChannel chan wire.NetAddress, peerSet map[string]wi } peerSet[addr.IP.String()] = addr + + err = storage.AddPeer(db, addr.IP.String()) } + + // close db connection + defer db.Close() + } -func getNextPeer(connectionSet map[string]*phantom.PingerConnection, peerSet map[string]wire.NetAddress) (returnValue wire.NetAddress, err error) { - for peer := range peerSet { - if _, ok := connectionSet[peer]; !ok { - //we have a peer that isn't in the conncetion list return it - returnValue = peerSet[peer] +func getNextPeer(peerSet map[string]wire.NetAddress) (returnValue wire.NetAddress, err error) { - //remove the peer from the connection list - delete(peerSet, peer) + // load the database + db, err := storage.SetupDB() + if err != nil { + log.Fatal("an error occurred:", err) + return + } - log.Println("Found new peer: ", peer) + // fetch my peers + list, err := storage.FetchPeers(db) + fmt.Println(list) - return returnValue, nil - } + for i := 0; i <= len(list); i++ { + returnValue = peerSet[list[i]] } + + // LEFT FOR NOW UNTIL FURTHER TESTING IS COMPLETE + //for peer := range peerSet { + // if _, ok := connectionSet[peer]; !ok { + // //we have a peer that isn't in the conncetion list return it + // returnValue = peerSet[peer] + // + // //remove the peer from the connection list + // delete(peerSet, peer) + // + // log.Println("Found new peer: ", peer) + // + // return returnValue, nil + // } + //} + return returnValue, errors.New("No peers found.") } @@ -376,7 +408,7 @@ func sendPings(connectionSet map[string]*phantom.PingerConnection, peerSet map[s for i := 0; i < int(maxConnections) - len(connectionSet); i++ { //spawn off a new connection - peer, err := getNextPeer(connectionSet, peerSet) + peer, err := getNextPeer(peerSet) if err != nil { log.Println("No new peers found.") diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go new file mode 100644 index 0000000..4b58bcc --- /dev/null +++ b/pkg/storage/storage.go @@ -0,0 +1,84 @@ +package storage + +import( + "fmt" + "log" + "github.com/boltdb/bolt" + "github.com/satori/go.uuid" + //"github.com/breakcrypto/phantom/pkg/socket/wire" +) + +// set up the database file +func SetupDB() (*bolt.DB, error) { + db, err := bolt.Open("nodes.db", 0600, nil) + if err != nil { + return nil, fmt.Errorf("could not open db, %v", err) + } + + err = db.Update(func(tx *bolt.Tx) error { + root, err := tx.CreateBucketIfNotExists([]byte("peers")) + if err != nil { + return fmt.Errorf("could not create root bucket: %v", err) + } + + _, err = root.CreateBucketIfNotExists([]byte("nodes")) + if err != nil { + return fmt.Errorf("could not create peers bucket: %v", err) + } + + return nil + }) + + if err != nil { + return nil, fmt.Errorf("could not set up buckets, %v", err) + } + + log.Println("Database setup complete...") + return db, nil +} + +// add a peer (in string format) to the database +func AddPeer(db *bolt.DB, peer string) error { + + // generate a uuid for the key + id := uuid.Must(uuid.NewV4()).String() + + err := db.Update(func(tx *bolt.Tx) error { + err := tx.Bucket([]byte("peers")).Bucket([]byte("nodes")).Put([]byte(id), []byte(peer)) + if err != nil { + return fmt.Errorf("could not insert peer: %v", err) + } + + return nil + }) + + fmt.Println("Added peer to database:", peer) + return err +} + +// retrieve all stored peers +func FetchPeers(db *bolt.DB) ([]string, error) { + + var list []string + + err := db.View(func(tx *bolt.Tx) error { + b := tx.Bucket([]byte("peers")).Bucket([]byte("nodes")) + b.ForEach(func(k, v []byte) error { + fmt.Println("Loaded from database:", string(k), string(v)) + + // load into array + list = append(list, string(v)) + + return nil + }) + fmt.Println(list) + + return nil + }) + + if err != nil { + log.Fatal(err) + } + + return list, nil +} \ No newline at end of file