diff --git a/beacon-chain/db/block_operations.go b/beacon-chain/db/block_operations.go index 1a1ef0703..8bf75ca14 100644 --- a/beacon-chain/db/block_operations.go +++ b/beacon-chain/db/block_operations.go @@ -11,6 +11,30 @@ import ( "go.opencensus.io/trace" ) +// VoluntaryExit by root. +// DEPRECATED: Use the kv store in beacon-chain/db/kv instead. +func (db *BeaconDB) VoluntaryExit(ctx context.Context, exitRoot [32]byte) (*ethpb.VoluntaryExit, error) { + return nil, errors.New("unimplemented") +} + +// SaveVoluntaryExit by root. +// DEPRECATED: Use the kv store in beacon-chain/db/kv instead. +func (db *BeaconDB) SaveVoluntaryExit(ctx context.Context, exit *ethpb.VoluntaryExit) error { + return errors.New("unimplemented") +} + +// HasVoluntaryExit by root. +// DEPRECATED: Use the kv store in beacon-chain/db/kv instead. +func (db *BeaconDB) HasVoluntaryExit(ctx context.Context, exitRoot [32]byte) bool { + return false +} + +// DeleteVoluntaryExit by root. +// DEPRECATED: Use the kv store in beacon-chain/db/kv instead. +func (db *BeaconDB) DeleteVoluntaryExit(ctx context.Context, exitRoot [32]byte) error { + return errors.New("unimplemented") +} + // ProposerSlashing retrieval from the db. // DEPRECATED: Use the kv store in beacon-chain/db/kv instead. func (db *BeaconDB) ProposerSlashing(ctx context.Context, slashingRoot [32]byte) (*ethpb.ProposerSlashing, error) { diff --git a/beacon-chain/db/db.go b/beacon-chain/db/db.go index 9f7b9da3d..da9c6f9c5 100644 --- a/beacon-chain/db/db.go +++ b/beacon-chain/db/db.go @@ -64,6 +64,11 @@ type Database interface { HasAttesterSlashing(ctx context.Context, slashingRoot [32]byte) bool DeleteProposerSlashing(ctx context.Context, slashingRoot [32]byte) error DeleteAttesterSlashing(ctx context.Context, slashingRoot [32]byte) error + // Block operations. + VoluntaryExit(ctx context.Context, exitRoot [32]byte) (*ethpb.VoluntaryExit, error) + SaveVoluntaryExit(ctx context.Context, exit *ethpb.VoluntaryExit) error + HasVoluntaryExit(ctx context.Context, exitRoot [32]byte) bool + DeleteVoluntaryExit(ctx context.Context, exitRoot [32]byte) error // Deposit contract related handlers. DepositContractAddress(ctx context.Context) ([]byte, error) SaveDepositContractAddress(ctx context.Context, addr common.Address) error diff --git a/beacon-chain/db/kv/BUILD.bazel b/beacon-chain/db/kv/BUILD.bazel index 8f400763e..de6890b61 100644 --- a/beacon-chain/db/kv/BUILD.bazel +++ b/beacon-chain/db/kv/BUILD.bazel @@ -7,6 +7,7 @@ go_library( "blocks.go", "deposit_contract.go", "kv.go", + "operations.go", "schema.go", "slashings.go", "state.go", @@ -37,6 +38,7 @@ go_test( "blocks_test.go", "deposit_contract_test.go", "kv_test.go", + "operations_test.go", "slashings_test.go", "state_test.go", "validators_test.go", diff --git a/beacon-chain/db/kv/operations.go b/beacon-chain/db/kv/operations.go new file mode 100644 index 000000000..78c4a26a0 --- /dev/null +++ b/beacon-chain/db/kv/operations.go @@ -0,0 +1,70 @@ +package kv + +import ( + "context" + + "github.com/boltdb/bolt" + "github.com/gogo/protobuf/proto" + "github.com/prysmaticlabs/go-ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" + "go.opencensus.io/trace" +) + +// VoluntaryExit retrieval by signing root. +func (k *Store) VoluntaryExit(ctx context.Context, exitRoot [32]byte) (*ethpb.VoluntaryExit, error) { + ctx, span := trace.StartSpan(ctx, "BeaconDB.VoluntaryExit") + defer span.End() + var exit *ethpb.VoluntaryExit + err := k.db.View(func(tx *bolt.Tx) error { + bkt := tx.Bucket(voluntaryExitsBucket) + enc := bkt.Get(exitRoot[:]) + if enc == nil { + return nil + } + exit = ðpb.VoluntaryExit{} + return proto.Unmarshal(enc, exit) + }) + return exit, err +} + +// HasVoluntaryExit verifies if a voluntary exit is stored in the db by its signing root. +func (k *Store) HasVoluntaryExit(ctx context.Context, exitRoot [32]byte) bool { + ctx, span := trace.StartSpan(ctx, "BeaconDB.HasVoluntaryExit") + defer span.End() + exists := false + // #nosec G104. Always returns nil. + k.db.View(func(tx *bolt.Tx) error { + bkt := tx.Bucket(voluntaryExitsBucket) + exists = bkt.Get(exitRoot[:]) != nil + return nil + }) + return exists +} + +// SaveVoluntaryExit to the db by its signing root. +func (k *Store) SaveVoluntaryExit(ctx context.Context, exit *ethpb.VoluntaryExit) error { + ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveVoluntaryExit") + defer span.End() + exitRoot, err := ssz.SigningRoot(exit) + if err != nil { + return err + } + enc, err := proto.Marshal(exit) + if err != nil { + return err + } + return k.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(voluntaryExitsBucket) + return bucket.Put(exitRoot[:], enc) + }) +} + +// DeleteVoluntaryExit clears a voluntary exit from the db by its signing root. +func (k *Store) DeleteVoluntaryExit(ctx context.Context, exitRoot [32]byte) error { + ctx, span := trace.StartSpan(ctx, "BeaconDB.DeleteVoluntaryExit") + defer span.End() + return k.db.Update(func(tx *bolt.Tx) error { + bucket := tx.Bucket(voluntaryExitsBucket) + return bucket.Delete(exitRoot[:]) + }) +} diff --git a/beacon-chain/db/kv/operations_test.go b/beacon-chain/db/kv/operations_test.go new file mode 100644 index 000000000..81eee8a86 --- /dev/null +++ b/beacon-chain/db/kv/operations_test.go @@ -0,0 +1,49 @@ +package kv + +import ( + "context" + "testing" + + "github.com/gogo/protobuf/proto" + "github.com/prysmaticlabs/go-ssz" + ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1" +) + +func TestStore_VoluntaryExits_CRUD(t *testing.T) { + db := setupDB(t) + defer teardownDB(t, db) + ctx := context.Background() + exit := ðpb.VoluntaryExit{ + Epoch: 5, + } + exitRoot, err := ssz.SigningRoot(exit) + if err != nil { + t.Fatal(err) + } + retrieved, err := db.VoluntaryExit(ctx, exitRoot) + if err != nil { + t.Fatal(err) + } + if retrieved != nil { + t.Errorf("Expected nil voluntary exit, received %v", retrieved) + } + if err := db.SaveVoluntaryExit(ctx, exit); err != nil { + t.Fatal(err) + } + if !db.HasVoluntaryExit(ctx, exitRoot) { + t.Error("Expected voluntary exit to exist in the db") + } + retrieved, err = db.VoluntaryExit(ctx, exitRoot) + if err != nil { + t.Fatal(err) + } + if !proto.Equal(exit, retrieved) { + t.Errorf("Wanted %v, received %v", exit, retrieved) + } + if err := db.DeleteVoluntaryExit(ctx, exitRoot); err != nil { + t.Fatal(err) + } + if db.HasVoluntaryExit(ctx, exitRoot) { + t.Error("Expected voluntary exit to have been deleted from the db") + } +}