ava state prefixdb

This commit is contained in:
Collin Montag 2020-05-28 10:36:00 -04:00
parent 60668c3a91
commit 198accdea7
4 changed files with 37 additions and 71 deletions

View File

@ -80,11 +80,6 @@ func (s *prefixedState) Funds(id ids.ID) ([]ids.ID, error) {
return s.state.IDs(uniqueID(id, fundsID, s.funds))
}
// SetFunds saves the mapping from address to utxo IDs to storage.
func (s *prefixedState) SetFunds(id ids.ID, idSlice []ids.ID) error {
return s.state.SetIDs(uniqueID(id, fundsID, s.funds), idSlice)
}
// SpendUTXO consumes the provided utxo.
func (s *prefixedState) SpendUTXO(utxoID ids.ID) error {
utxo, err := s.UTXO(utxoID)
@ -106,11 +101,7 @@ func (s *prefixedState) SpendUTXO(utxoID ids.ID) error {
func (s *prefixedState) removeUTXO(addrs [][]byte, utxoID ids.ID) error {
for _, addr := range addrs {
addrID := ids.NewID(hashing.ComputeHash256Array(addr))
utxos := ids.Set{}
funds, _ := s.Funds(addrID)
utxos.Add(funds...)
utxos.Remove(utxoID)
if err := s.SetFunds(addrID, utxos.List()); err != nil {
if err := s.state.RemoveID(addrID, utxoID); err != nil {
return err
}
}
@ -135,11 +126,7 @@ func (s *prefixedState) FundUTXO(utxo *ava.UTXO) error {
func (s *prefixedState) addUTXO(addrs [][]byte, utxoID ids.ID) error {
for _, addr := range addrs {
addrID := ids.NewID(hashing.ComputeHash256Array(addr))
utxos := ids.Set{}
funds, _ := s.Funds(addrID)
utxos.Add(funds...)
utxos.Add(utxoID)
if err := s.SetFunds(addrID, utxos.List()); err != nil {
if err := s.state.AddID(addrID, utxoID); err != nil {
return err
}
}

View File

@ -27,13 +27,15 @@ func TestStateIDs(t *testing.T) {
id1 := ids.NewID([32]byte{0xff, 0})
id2 := ids.NewID([32]byte{0xff, 0})
if _, err := state.IDs(ids.Empty); err == nil {
t.Fatalf("Should have errored when reading ids")
if _, err := state.IDs(ids.Empty); err != nil {
t.Fatal(err)
}
expected := []ids.ID{id0, id1}
if err := state.SetIDs(ids.Empty, expected); err != nil {
t.Fatal(err)
for _, id := range expected {
if err := state.AddID(ids.Empty, id); err != nil {
t.Fatal(err)
}
}
result, err := state.IDs(ids.Empty)
@ -53,8 +55,10 @@ func TestStateIDs(t *testing.T) {
}
expected = []ids.ID{id1, id2}
if err := state.SetIDs(ids.Empty, expected); err != nil {
t.Fatal(err)
for _, id := range expected {
if err := state.AddID(ids.Empty, id); err != nil {
t.Fatal(err)
}
}
result, err = state.IDs(ids.Empty)
@ -115,14 +119,10 @@ func TestStateIDs(t *testing.T) {
t.Fatalf("Should have returned the %s status", choices.Accepted)
}
if err := state.SetIDs(ids.Empty, []ids.ID{ids.ID{}}); err == nil {
if err := state.AddID(ids.Empty, ids.ID{}); err == nil {
t.Fatalf("Should have errored during serialization")
}
if err := state.SetIDs(ids.Empty, []ids.ID{}); err != nil {
t.Fatal(err)
}
if _, err := state.IDs(ids.Empty); err == nil {
t.Fatalf("Should have errored when reading ids")
}
@ -153,7 +153,7 @@ func TestStateStatuses(t *testing.T) {
t.Fatalf("Should have returned the %s status", choices.Accepted)
}
if err := state.SetIDs(ids.Empty, []ids.ID{ids.Empty}); err != nil {
if err := state.AddID(ids.Empty, ids.Empty); err != nil {
t.Fatal(err)
}
if _, err := state.Status(ids.Empty); err == nil {

View File

@ -97,11 +97,7 @@ func (s *chainState) setStatus(id ids.ID, status choices.Status) error {
func (s *chainState) removeUTXO(addrs [][]byte, utxoID ids.ID) error {
for _, addr := range addrs {
addrID := ids.NewID(hashing.ComputeHash256Array(addr))
utxos := ids.Set{}
funds, _ := s.Funds(addrID)
utxos.Add(funds...)
utxos.Remove(utxoID)
if err := s.setFunds(addrID, utxos.List()); err != nil {
if err := s.RemoveID(addrID, utxoID); err != nil {
return err
}
}
@ -111,21 +107,13 @@ func (s *chainState) removeUTXO(addrs [][]byte, utxoID ids.ID) error {
func (s *chainState) addUTXO(addrs [][]byte, utxoID ids.ID) error {
for _, addr := range addrs {
addrID := ids.NewID(hashing.ComputeHash256Array(addr))
utxos := ids.Set{}
funds, _ := s.Funds(addrID)
utxos.Add(funds...)
utxos.Add(utxoID)
if err := s.setFunds(addrID, utxos.List()); err != nil {
if err := s.AddID(addrID, utxoID); err != nil {
return err
}
}
return nil
}
func (s *chainState) setFunds(id ids.ID, idSlice []ids.ID) error {
return s.SetIDs(UniqueID(id, s.fundsIDPrefix, s.fundsID), idSlice)
}
// PrefixedState wraps a state object. By prefixing the state, there will
// be no collisions between different types of objects that have the same hash.
type PrefixedState struct {

View File

@ -8,6 +8,7 @@ import (
"github.com/ava-labs/gecko/cache"
"github.com/ava-labs/gecko/database"
"github.com/ava-labs/gecko/database/prefixdb"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow/choices"
"github.com/ava-labs/gecko/vms/components/codec"
@ -116,39 +117,29 @@ func (s *State) SetStatus(id ids.ID, status choices.Status) error {
// IDs returns a slice of IDs from storage
func (s *State) IDs(id ids.ID) ([]ids.ID, error) {
if idsIntf, found := s.Cache.Get(id); found {
if idSlice, ok := idsIntf.([]ids.ID); ok {
return idSlice, nil
}
return nil, errCacheTypeMismatch
}
bytes, err := s.DB.Get(id.Bytes())
if err != nil {
return nil, err
}
idSlice := []ids.ID(nil)
if err := s.Codec.Unmarshal(bytes, &idSlice); err != nil {
return nil, err
}
iter := prefixdb.New(id.Bytes(), s.DB).NewIterator()
defer iter.Release()
s.Cache.Put(id, idSlice)
for iter.Next() {
keyID, err := ids.ToID(iter.Key())
if err != nil {
return nil, err
}
idSlice = append(idSlice, keyID)
}
return idSlice, nil
}
// SetIDs saves a slice of IDs to the database.
func (s *State) SetIDs(id ids.ID, idSlice []ids.ID) error {
if len(idSlice) == 0 {
s.Cache.Evict(id)
return s.DB.Delete(id.Bytes())
}
bytes, err := s.Codec.Marshal(idSlice)
if err != nil {
return err
}
s.Cache.Put(id, idSlice)
return s.DB.Put(id.Bytes(), bytes)
// AddID saves an ID to the prefixed database
func (s *State) AddID(id ids.ID, key ids.ID) error {
db := prefixdb.New(id.Bytes(), s.DB)
return db.Put(key.Bytes(), nil)
}
// RemoveID removes an ID from the prefixed database
func (s *State) RemoveID(id ids.ID, key ids.ID) error {
db := prefixdb.New(id.Bytes(), s.DB)
return db.Delete(key.Bytes())
}