From 26b21e8eea1e9760a7355a4e7b12b06b3a46e292 Mon Sep 17 00:00:00 2001 From: Eric Meyer Date: Mon, 6 Nov 2017 10:42:33 -0600 Subject: [PATCH 1/3] Add InMemory Repository --- repositories/in_memory.go | 27 +++++++ repositories/in_memory_test.go | 141 +++++++++++++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 repositories/in_memory.go create mode 100644 repositories/in_memory_test.go diff --git a/repositories/in_memory.go b/repositories/in_memory.go new file mode 100644 index 00000000..a28ead8b --- /dev/null +++ b/repositories/in_memory.go @@ -0,0 +1,27 @@ +package repositories + +import ( + "github.com/8thlight/vulcanizedb/core" +) + +type InMemory struct { + blocks map[int64]*core.Block +} + +func NewInMemory() *InMemory { + return &InMemory{ + blocks: make(map[int64]*core.Block), + } +} + +func (repository *InMemory) CreateBlock(block core.Block) { + repository.blocks[block.Number] = &block +} + +func (repository *InMemory) BlockCount() int { + return len(repository.blocks) +} + +func (repository *InMemory) FindBlockByNumber(blockNumber int64) *core.Block { + return repository.blocks[blockNumber] +} diff --git a/repositories/in_memory_test.go b/repositories/in_memory_test.go new file mode 100644 index 00000000..7d4bcb96 --- /dev/null +++ b/repositories/in_memory_test.go @@ -0,0 +1,141 @@ +package repositories_test + +import ( + "github.com/8thlight/vulcanizedb/core" + "github.com/8thlight/vulcanizedb/repositories" + _ "github.com/lib/pq" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("The In Memory Repository", func() { + + Describe("Saving blocks", func() { + It("starts with no blocks", func() { + count := buildRepository().BlockCount() + Expect(count).Should(Equal(0)) + }) + + It("increments the block count", func() { + block := core.Block{Number: 123} + repository := buildRepository() + + repository.CreateBlock(block) + + Expect(repository.BlockCount()).To(Equal(1)) + }) + + It("saves the attributes of the block", func() { + blockNumber := int64(123) + gasLimit := int64(1000000) + gasUsed := int64(10) + blockHash := "x123" + blockParentHash := "x456" + blockNonce := "0x881db2ca900682e9a9" + blockTime := int64(1508981640) + uncleHash := "x789" + blockSize := int64(1000) + difficulty := int64(10) + block := core.Block{ + Difficulty: difficulty, + GasLimit: gasLimit, + GasUsed: gasUsed, + Hash: blockHash, + Nonce: blockNonce, + Number: blockNumber, + ParentHash: blockParentHash, + Size: blockSize, + Time: blockTime, + UncleHash: uncleHash, + } + + repository := buildRepository() + repository.CreateBlock(block) + + savedBlock := repository.FindBlockByNumber(blockNumber) + Expect(savedBlock.Difficulty).To(Equal(difficulty)) + Expect(savedBlock.GasLimit).To(Equal(gasLimit)) + Expect(savedBlock.GasUsed).To(Equal(gasUsed)) + Expect(savedBlock.Hash).To(Equal(blockHash)) + Expect(savedBlock.Nonce).To(Equal(blockNonce)) + Expect(savedBlock.Number).To(Equal(blockNumber)) + Expect(savedBlock.ParentHash).To(Equal(blockParentHash)) + Expect(savedBlock.Size).To(Equal(blockSize)) + Expect(savedBlock.Time).To(Equal(blockTime)) + Expect(savedBlock.UncleHash).To(Equal(uncleHash)) + }) + + It("does not find a block when searching for a number that does not exist", func() { + repository := buildRepository() + + savedBlock := repository.FindBlockByNumber(111) + + Expect(savedBlock).To(BeNil()) + }) + + It("saves one transaction associated to the block", func() { + block := core.Block{ + Number: 123, + Transactions: []core.Transaction{{}}, + } + repository := buildRepository() + + repository.CreateBlock(block) + + savedBlock := repository.FindBlockByNumber(123) + Expect(len(savedBlock.Transactions)).To(Equal(1)) + }) + + It("saves two transactions associated to the block", func() { + block := core.Block{ + Number: 123, + Transactions: []core.Transaction{{}, {}}, + } + repository := buildRepository() + + repository.CreateBlock(block) + + savedBlock := repository.FindBlockByNumber(123) + Expect(len(savedBlock.Transactions)).To(Equal(2)) + }) + + It("saves the attributes associated to a transaction", func() { + gasLimit := int64(5000) + gasPrice := int64(3) + nonce := uint64(10000) + to := "1234567890" + value := int64(10) + + transaction := core.Transaction{ + Hash: "x1234", + GasPrice: gasPrice, + GasLimit: gasLimit, + Nonce: nonce, + To: to, + Value: value, + } + block := core.Block{ + Number: 123, + Transactions: []core.Transaction{transaction}, + } + repository := buildRepository() + + repository.CreateBlock(block) + + savedBlock := repository.FindBlockByNumber(123) + Expect(len(savedBlock.Transactions)).To(Equal(1)) + savedTransaction := savedBlock.Transactions[0] + Expect(savedTransaction.Hash).To(Equal(transaction.Hash)) + Expect(savedTransaction.To).To(Equal(to)) + Expect(savedTransaction.Nonce).To(Equal(nonce)) + Expect(savedTransaction.GasLimit).To(Equal(gasLimit)) + Expect(savedTransaction.GasPrice).To(Equal(gasPrice)) + Expect(savedTransaction.Value).To(Equal(value)) + }) + }) + +}) + +func buildRepository() *repositories.InMemory { + return repositories.NewInMemory() +} From 24a8fcbadb2e7768b8eb8fb322795d6cae35ddf3 Mon Sep 17 00:00:00 2001 From: Eric Meyer Date: Mon, 6 Nov 2017 10:52:07 -0600 Subject: [PATCH 2/3] Refactor DB observer to depend on repository --- Gododir/main.go | 4 ++- .../blockchain_listener_test.go | 8 +++--- fakes/blockchain_observer.go | 2 +- integration_test/geth_blockchain_test.go | 2 +- observers/blockchain_db_observer.go | 13 +++++---- observers/blockchain_db_observer_test.go | 27 +++---------------- repositories/repository.go | 7 +++++ 7 files changed, 28 insertions(+), 35 deletions(-) create mode 100644 repositories/repository.go diff --git a/Gododir/main.go b/Gododir/main.go index 0733602c..57a0f34e 100644 --- a/Gododir/main.go +++ b/Gododir/main.go @@ -10,6 +10,7 @@ import ( "github.com/8thlight/vulcanizedb/core" "github.com/8thlight/vulcanizedb/geth" "github.com/8thlight/vulcanizedb/observers" + "github.com/8thlight/vulcanizedb/repositories" "github.com/jmoiron/sqlx" do "gopkg.in/godo.v2" ) @@ -31,7 +32,8 @@ func startBlockchainListener(cfg config.Config) { if err != nil { log.Fatalf("Error connecting to DB: %v\n", err) } - dbObserver := (observers.BlockchainDBObserver{Db: db}) + repository := repositories.NewPostgres(db) + dbObserver := observers.NewBlockchainDbObserver(repository) listener := blockchain_listener.NewBlockchainListener(blockchain, []core.BlockchainObserver{ loggingObserver, dbObserver, diff --git a/blockchain_listener/blockchain_listener_test.go b/blockchain_listener/blockchain_listener_test.go index c64eb5c4..9f55db94 100644 --- a/blockchain_listener/blockchain_listener_test.go +++ b/blockchain_listener/blockchain_listener_test.go @@ -11,7 +11,7 @@ import ( var _ = Describe("Blockchain listeners", func() { It("starts with no blocks", func(done Done) { - observer := fakes.NewFakeBlockchainObserverTwo() + observer := fakes.NewFakeBlockchainObserver() blockchain := &fakes.Blockchain{} blockchain_listener.NewBlockchainListener(blockchain, []core.BlockchainObserver{observer}) @@ -21,7 +21,7 @@ var _ = Describe("Blockchain listeners", func() { }, 1) It("sees when one block was added", func(done Done) { - observer := fakes.NewFakeBlockchainObserverTwo() + observer := fakes.NewFakeBlockchainObserver() blockchain := &fakes.Blockchain{} listener := blockchain_listener.NewBlockchainListener(blockchain, []core.BlockchainObserver{observer}) go listener.Start() @@ -37,7 +37,7 @@ var _ = Describe("Blockchain listeners", func() { }, 1) It("sees a second block", func(done Done) { - observer := fakes.NewFakeBlockchainObserverTwo() + observer := fakes.NewFakeBlockchainObserver() blockchain := &fakes.Blockchain{} listener := blockchain_listener.NewBlockchainListener(blockchain, []core.BlockchainObserver{observer}) go listener.Start() @@ -55,7 +55,7 @@ var _ = Describe("Blockchain listeners", func() { }, 1) It("stops listening", func(done Done) { - observer := fakes.NewFakeBlockchainObserverTwo() + observer := fakes.NewFakeBlockchainObserver() blockchain := &fakes.Blockchain{} listener := blockchain_listener.NewBlockchainListener(blockchain, []core.BlockchainObserver{observer}) go listener.Start() diff --git a/fakes/blockchain_observer.go b/fakes/blockchain_observer.go index add572e2..8dd444c0 100644 --- a/fakes/blockchain_observer.go +++ b/fakes/blockchain_observer.go @@ -11,7 +11,7 @@ func (observer *BlockchainObserver) LastBlock() core.Block { return observer.CurrentBlocks[len(observer.CurrentBlocks)-1] } -func NewFakeBlockchainObserverTwo() *BlockchainObserver { +func NewFakeBlockchainObserver() *BlockchainObserver { return &BlockchainObserver{ WasNotified: make(chan bool), } diff --git a/integration_test/geth_blockchain_test.go b/integration_test/geth_blockchain_test.go index 199c173f..116527e4 100644 --- a/integration_test/geth_blockchain_test.go +++ b/integration_test/geth_blockchain_test.go @@ -26,7 +26,7 @@ var _ = Describe("Reading from the Geth blockchain", func() { var observer *fakes.BlockchainObserver BeforeEach(func() { - observer = fakes.NewFakeBlockchainObserverTwo() + observer = fakes.NewFakeBlockchainObserver() blockchain := geth.NewGethBlockchain(RunTimePath() + "/test_data_dir/geth.ipc") observers := []core.BlockchainObserver{observer} listener = blockchain_listener.NewBlockchainListener(blockchain, observers) diff --git a/observers/blockchain_db_observer.go b/observers/blockchain_db_observer.go index 911930ef..504a0367 100644 --- a/observers/blockchain_db_observer.go +++ b/observers/blockchain_db_observer.go @@ -3,13 +3,16 @@ package observers import ( "github.com/8thlight/vulcanizedb/core" "github.com/8thlight/vulcanizedb/repositories" - "github.com/jmoiron/sqlx" ) -type BlockchainDBObserver struct { - Db *sqlx.DB +type BlockchainDbObserver struct { + repository repositories.Repository } -func (observer BlockchainDBObserver) NotifyBlockAdded(block core.Block) { - repositories.NewPostgres(observer.Db).CreateBlock(block) +func NewBlockchainDbObserver(repository repositories.Repository) BlockchainDbObserver { + return BlockchainDbObserver{repository: repository} +} + +func (observer BlockchainDbObserver) NotifyBlockAdded(block core.Block) { + observer.repository.CreateBlock(block) } diff --git a/observers/blockchain_db_observer_test.go b/observers/blockchain_db_observer_test.go index 4bbcec73..0f636a15 100644 --- a/observers/blockchain_db_observer_test.go +++ b/observers/blockchain_db_observer_test.go @@ -1,41 +1,23 @@ package observers_test import ( - "runtime" - - "github.com/8thlight/vulcanizedb/config" "github.com/8thlight/vulcanizedb/core" "github.com/8thlight/vulcanizedb/observers" "github.com/8thlight/vulcanizedb/repositories" - "github.com/jmoiron/sqlx" - _ "github.com/lib/pq" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) -var ( - _, filename, _, _ = runtime.Caller(0) -) - var _ = Describe("Saving blocks to the database", func() { - var db *sqlx.DB - var err error + var repository *repositories.InMemory BeforeEach(func() { - cfg := config.NewConfig("private") - pgConfig := config.DbConnectionString(cfg.Database) - db, err = sqlx.Connect("postgres", pgConfig) - db.MustExec("DELETE FROM transactions") - db.MustExec("DELETE FROM blocks") - }) - - AfterEach(func() { - db.Close() + repository = repositories.NewInMemory() }) It("implements the observer interface", func() { - var observer core.BlockchainObserver = observers.BlockchainDBObserver{Db: db} + var observer core.BlockchainObserver = observers.NewBlockchainDbObserver(repository) Expect(observer).NotTo(BeNil()) }) @@ -45,10 +27,9 @@ var _ = Describe("Saving blocks to the database", func() { Transactions: []core.Transaction{{}}, } - observer := observers.BlockchainDBObserver{Db: db} + observer := observers.NewBlockchainDbObserver(repository) observer.NotifyBlockAdded(block) - repository := repositories.NewPostgres(db) savedBlock := repository.FindBlockByNumber(123) Expect(savedBlock).NotTo(BeNil()) Expect(len(savedBlock.Transactions)).To(Equal(1)) diff --git a/repositories/repository.go b/repositories/repository.go new file mode 100644 index 00000000..16aa4055 --- /dev/null +++ b/repositories/repository.go @@ -0,0 +1,7 @@ +package repositories + +import "github.com/8thlight/vulcanizedb/core" + +type Repository interface { + CreateBlock(block core.Block) +} From 9ef1fda6677975ad1fd8b0d178a3c6d925c25337 Mon Sep 17 00:00:00 2001 From: Eric Meyer Date: Mon, 6 Nov 2017 11:40:52 -0600 Subject: [PATCH 3/3] Fix issue where godo would not build project * The solution is to add a main.go and call run * parses the current file contents --- Gododir/main.go | 28 ++-------------------------- cmd/run/main.go | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 26 deletions(-) create mode 100644 cmd/run/main.go diff --git a/Gododir/main.go b/Gododir/main.go index 57a0f34e..caffb7d3 100644 --- a/Gododir/main.go +++ b/Gododir/main.go @@ -5,13 +5,7 @@ import ( "fmt" - "github.com/8thlight/vulcanizedb/blockchain_listener" "github.com/8thlight/vulcanizedb/config" - "github.com/8thlight/vulcanizedb/core" - "github.com/8thlight/vulcanizedb/geth" - "github.com/8thlight/vulcanizedb/observers" - "github.com/8thlight/vulcanizedb/repositories" - "github.com/jmoiron/sqlx" do "gopkg.in/godo.v2" ) @@ -23,30 +17,12 @@ func parseEnvironment(context *do.Context) string { return environment } -func startBlockchainListener(cfg config.Config) { - fmt.Println("Client Path ", cfg.Client.IPCPath) - blockchain := geth.NewGethBlockchain(cfg.Client.IPCPath) - loggingObserver := observers.BlockchainLoggingObserver{} - connectString := config.DbConnectionString(cfg.Database) - db, err := sqlx.Connect("postgres", connectString) - if err != nil { - log.Fatalf("Error connecting to DB: %v\n", err) - } - repository := repositories.NewPostgres(db) - dbObserver := observers.NewBlockchainDbObserver(repository) - listener := blockchain_listener.NewBlockchainListener(blockchain, []core.BlockchainObserver{ - loggingObserver, - dbObserver, - }) - listener.Start() -} - func tasks(p *do.Project) { p.Task("run", nil, func(context *do.Context) { environment := parseEnvironment(context) - cfg := config.NewConfig(environment) - startBlockchainListener(cfg) + context.Start(`go run main.go --environment={{.environment}}`, + do.M{"environment": environment, "$in": "cmd/run"}) }) p.Task("migrate", nil, func(context *do.Context) { diff --git a/cmd/run/main.go b/cmd/run/main.go new file mode 100644 index 00000000..57e3159e --- /dev/null +++ b/cmd/run/main.go @@ -0,0 +1,38 @@ +package main + +import ( + "fmt" + "log" + + "flag" + + "github.com/8thlight/vulcanizedb/blockchain_listener" + "github.com/8thlight/vulcanizedb/config" + "github.com/8thlight/vulcanizedb/core" + "github.com/8thlight/vulcanizedb/geth" + "github.com/8thlight/vulcanizedb/observers" + "github.com/8thlight/vulcanizedb/repositories" + "github.com/jmoiron/sqlx" +) + +func main() { + environment := flag.String("environment", "", "Environment name") + flag.Parse() + cfg := config.NewConfig(*environment) + + fmt.Println("Client Path ", cfg.Client.IPCPath) + blockchain := geth.NewGethBlockchain(cfg.Client.IPCPath) + loggingObserver := observers.BlockchainLoggingObserver{} + connectString := config.DbConnectionString(cfg.Database) + db, err := sqlx.Connect("postgres", connectString) + if err != nil { + log.Fatalf("Error connecting to DB: %v\n", err) + } + repository := repositories.NewPostgres(db) + dbObserver := observers.NewBlockchainDbObserver(repository) + listener := blockchain_listener.NewBlockchainListener(blockchain, []core.BlockchainObserver{ + loggingObserver, + dbObserver, + }) + listener.Start() +}