Skip to content

Commit

Permalink
Merge pull request ava-labs#68 from ava-labs/geth-plugin
Browse files Browse the repository at this point in the history
Move Geth to a plugin connected at runtime
  • Loading branch information
StephenButtolph authored Apr 16, 2020
2 parents e750d44 + 42baab2 commit e5252c1
Show file tree
Hide file tree
Showing 84 changed files with 6,180 additions and 1,257 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ awscpu
*.ava

db*

*cpu[0-9]*
*mem[0-9]*
*lock[0-9]*
Expand All @@ -46,3 +47,8 @@ bin/
build/

keys/staker.*

!*.go
!*.proto

plugins/
4 changes: 0 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ RUN apt-get update && apt-get install -y libssl-dev libuv1-dev curl cmake

RUN mkdir -p /go/src/github.com/ava-labs

# Because downloading ethereum takes long it is done separately, so that the docker
# layer, when cached can be re-used
RUN go get -t -v github.com/ava-labs/go-ethereum

WORKDIR $GOPATH/src/github.com/ava-labs/
COPY . gecko

Expand Down
15 changes: 13 additions & 2 deletions chains/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,12 @@ func (m *manager) ForceCreateChain(chain ChainParameters) {
}

// Create the chain
vm := vmFactory.New()
vm, err := vmFactory.New()
if err != nil {
m.log.Error("error while creating vm: %s", err)
return
}
// TODO: Shutdown VM if an error occurs

fxs := make([]*common.Fx, len(chain.FxAliases))
for i, fxAlias := range chain.FxAliases {
Expand All @@ -231,10 +236,16 @@ func (m *manager) ForceCreateChain(chain ChainParameters) {
return
}

fx, err := fxFactory.New()
if err != nil {
m.log.Error("error while creating fx: %s", err)
return
}

// Create the fx
fxs[i] = &common.Fx{
ID: fxID,
Fx: fxFactory.New(),
Fx: fx,
}
}

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
268 changes: 268 additions & 0 deletions database/rpcdb/db_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package rpcdb

import (
"fmt"

"golang.org/x/net/context"

"github.com/ava-labs/gecko/database"
"github.com/ava-labs/gecko/database/nodb"
"github.com/ava-labs/gecko/database/rpcdb/proto"
)

var (
errClosed = fmt.Sprintf("rpc error: code = Unknown desc = %s", database.ErrClosed)
errNotFound = fmt.Sprintf("rpc error: code = Unknown desc = %s", database.ErrNotFound)
)

// DatabaseClient is an implementation of database that talks over RPC.
type DatabaseClient struct{ client proto.DatabaseClient }

// NewClient returns a database instance connected to a remote database instance
func NewClient(client proto.DatabaseClient) *DatabaseClient {
return &DatabaseClient{client: client}
}

// Has returns false, nil
func (db *DatabaseClient) Has(key []byte) (bool, error) {
resp, err := db.client.Has(context.Background(), &proto.HasRequest{
Key: key,
})
if err != nil {
return false, updateError(err)
}
return resp.Has, nil
}

// Get returns nil, error
func (db *DatabaseClient) Get(key []byte) ([]byte, error) {
resp, err := db.client.Get(context.Background(), &proto.GetRequest{
Key: key,
})
if err != nil {
return nil, updateError(err)
}
return resp.Value, nil
}

// Put returns nil
func (db *DatabaseClient) Put(key, value []byte) error {
_, err := db.client.Put(context.Background(), &proto.PutRequest{
Key: key,
Value: value,
})
return updateError(err)
}

// Delete returns nil
func (db *DatabaseClient) Delete(key []byte) error {
_, err := db.client.Delete(context.Background(), &proto.DeleteRequest{
Key: key,
})
return updateError(err)
}

// NewBatch returns a new batch
func (db *DatabaseClient) NewBatch() database.Batch { return &batch{db: db} }

// NewIterator implements the Database interface
func (db *DatabaseClient) NewIterator() database.Iterator {
return db.NewIteratorWithStartAndPrefix(nil, nil)
}

// NewIteratorWithStart implements the Database interface
func (db *DatabaseClient) NewIteratorWithStart(start []byte) database.Iterator {
return db.NewIteratorWithStartAndPrefix(start, nil)
}

// NewIteratorWithPrefix implements the Database interface
func (db *DatabaseClient) NewIteratorWithPrefix(prefix []byte) database.Iterator {
return db.NewIteratorWithStartAndPrefix(nil, prefix)
}

// NewIteratorWithStartAndPrefix returns a new empty iterator
func (db *DatabaseClient) NewIteratorWithStartAndPrefix(start, prefix []byte) database.Iterator {
resp, err := db.client.NewIteratorWithStartAndPrefix(context.Background(), &proto.NewIteratorWithStartAndPrefixRequest{
Start: start,
Prefix: prefix,
})
if err != nil {
return &nodb.Iterator{Err: updateError(err)}
}
return &iterator{
db: db,
id: resp.Id,
}
}

// Stat returns an error
func (db *DatabaseClient) Stat(property string) (string, error) {
resp, err := db.client.Stat(context.Background(), &proto.StatRequest{
Property: property,
})
if err != nil {
return "", updateError(err)
}
return resp.Stat, nil
}

// Compact returns nil
func (db *DatabaseClient) Compact(start, limit []byte) error {
_, err := db.client.Compact(context.Background(), &proto.CompactRequest{
Start: start,
Limit: limit,
})
return updateError(err)
}

// Close returns nil
func (db *DatabaseClient) Close() error {
_, err := db.client.Close(context.Background(), &proto.CloseRequest{})
return updateError(err)
}

type keyValue struct {
key []byte
value []byte
delete bool
}

type batch struct {
db *DatabaseClient
writes []keyValue
size int
}

func (b *batch) Put(key, value []byte) error {
b.writes = append(b.writes, keyValue{copyBytes(key), copyBytes(value), false})
b.size += len(value)
return nil
}

func (b *batch) Delete(key []byte) error {
b.writes = append(b.writes, keyValue{copyBytes(key), nil, true})
b.size++
return nil
}

func (b *batch) ValueSize() int { return b.size }

func (b *batch) Write() error {
request := &proto.WriteBatchRequest{}

keySet := make(map[string]struct{}, len(b.writes))
for i := len(b.writes) - 1; i >= 0; i-- {
kv := b.writes[i]
key := string(kv.key)
if _, overwritten := keySet[key]; overwritten {
continue
}
keySet[key] = struct{}{}

if kv.delete {
request.Deletes = append(request.Deletes, &proto.DeleteRequest{
Key: kv.key,
})
} else {
request.Puts = append(request.Puts, &proto.PutRequest{
Key: kv.key,
Value: kv.value,
})
}
}

_, err := b.db.client.WriteBatch(context.Background(), request)
return updateError(err)
}

func (b *batch) Reset() {
b.writes = b.writes[:0]
b.size = 0
}

func (b *batch) Replay(w database.KeyValueWriter) error {
for _, keyvalue := range b.writes {
if keyvalue.delete {
if err := w.Delete(keyvalue.key); err != nil {
return err
}
} else if err := w.Put(keyvalue.key, keyvalue.value); err != nil {
return err
}
}
return nil
}

func (b *batch) Inner() database.Batch { return b }

type iterator struct {
db *DatabaseClient
id uint64
key []byte
value []byte
err error
}

// Next returns false
func (it *iterator) Next() bool {
resp, err := it.db.client.IteratorNext(context.Background(), &proto.IteratorNextRequest{
Id: it.id,
})
if err != nil {
it.err = err
return false
}
it.key = resp.Key
it.value = resp.Value
return resp.FoundNext
}

// Error returns any errors
func (it *iterator) Error() error {
if it.err != nil {
return it.err
}

_, err := it.db.client.IteratorError(context.Background(), &proto.IteratorErrorRequest{
Id: it.id,
})
it.err = updateError(err)
return it.err
}

// Key returns nil
func (it *iterator) Key() []byte { return it.key }

// Value returns nil
func (it *iterator) Value() []byte { return it.value }

// Release does nothing
func (it *iterator) Release() {
it.db.client.IteratorRelease(context.Background(), &proto.IteratorReleaseRequest{
Id: it.id,
})
}

func copyBytes(bytes []byte) []byte {
copiedBytes := make([]byte, len(bytes))
copy(copiedBytes, bytes)
return copiedBytes
}

func updateError(err error) error {
if err == nil {
return nil
}

switch err.Error() {
case errClosed:
return database.ErrClosed
case errNotFound:
return database.ErrNotFound
default:
return err
}
}
Loading

0 comments on commit e5252c1

Please sign in to comment.