-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The goal of contextstore is to simplify context recovery when working with modules like Crypto and Hasher. Currently, using these modules requires creating a new protobuf type each time the user wants to verify a signature or compute a hash. This is associated with a lot of boilerplate code. ContextStore allows saving the context locally in the module and only sending an automatically generated id in a standard ContextStoreOrigin protobuf.
- Loading branch information
Showing
7 changed files
with
619 additions
and
353 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package contextstore | ||
|
||
// ContextStore can be used to store arbitrary data under an automatically deterministically generated unique id. | ||
type ContextStore[T any] interface { | ||
Store(t T) ItemID | ||
Recover(id ItemID) T | ||
Dispose(id ItemID) | ||
RecoverAndDispose(id ItemID) T | ||
} | ||
|
||
// ItemID is used to uniquely identify entries of the ContextStore. | ||
type ItemID uint64 | ||
|
||
// Pb returns the protobuf representation of ItemID. | ||
func (i ItemID) Pb() uint64 { | ||
return uint64(i) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package contextstore | ||
|
||
import ( | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
func TestContextStore_SimpleTest(t *testing.T) { | ||
cs := NewSequentialContextStore[string]() | ||
helloID := cs.Store("Hello") | ||
worldID := cs.Store("World") | ||
|
||
assert.Equal(t, "World", cs.Recover(worldID)) | ||
assert.Equal(t, "Hello", cs.Recover(helloID)) | ||
|
||
cs.Dispose(worldID) | ||
assert.Panics(t, func() { | ||
cs.Recover(worldID) | ||
}) | ||
|
||
assert.Equal(t, "Hello", cs.RecoverAndDispose(helloID)) | ||
assert.Panics(t, func() { | ||
cs.RecoverAndDispose(helloID) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package contextstore | ||
|
||
import ( | ||
"github.com/filecoin-project/mir/pkg/pb/eventpb" | ||
t "github.com/filecoin-project/mir/pkg/types" | ||
) | ||
|
||
// Origin returns a ContextStoreOrigin protobuf containing the given id. | ||
func Origin(itemID ItemID) *eventpb.ContextStoreOrigin { | ||
return &eventpb.ContextStoreOrigin{ItemID: itemID.Pb()} | ||
} | ||
|
||
// SignOrigin returns a SignOrigin protobuf containing moduleID and contextstore.Origin(itemID). | ||
func SignOrigin(moduleID t.ModuleID, itemID ItemID) *eventpb.SignOrigin { | ||
return &eventpb.SignOrigin{ | ||
Module: moduleID.Pb(), | ||
Type: &eventpb.SignOrigin_Contextstore{ | ||
Contextstore: Origin(itemID), | ||
}, | ||
} | ||
} | ||
|
||
// SigVerOrigin returns a SigVerOrigin protobuf containing moduleID and contextstore.Origin(itemID). | ||
func SigVerOrigin(moduleID t.ModuleID, itemID ItemID) *eventpb.SigVerOrigin { | ||
return &eventpb.SigVerOrigin{ | ||
Module: moduleID.Pb(), | ||
Type: &eventpb.SigVerOrigin_Contextstore{ | ||
Contextstore: Origin(itemID), | ||
}, | ||
} | ||
} | ||
|
||
// HashOrigin returns a HashOrigin protobuf containing moduleID and contextstore.Origin(itemID). | ||
func HashOrigin(moduleID t.ModuleID, itemID ItemID) *eventpb.HashOrigin { | ||
return &eventpb.HashOrigin{ | ||
Module: moduleID.Pb(), | ||
Type: &eventpb.HashOrigin_Contextstore{ | ||
Contextstore: Origin(itemID), | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package contextstore | ||
|
||
import "fmt" | ||
|
||
type sequentialContextStoreImpl[T any] struct { | ||
nextID ItemID | ||
storage map[ItemID]T | ||
} | ||
|
||
// NewSequentialContextStore creates an empty ContextStore that can only be accessed sequentially. | ||
func NewSequentialContextStore[T any]() ContextStore[T] { | ||
return &sequentialContextStoreImpl[T]{ | ||
storage: make(map[ItemID]T), | ||
} | ||
} | ||
|
||
// Store stores the given data in the ContextStore and returns a unique id. | ||
// The data can be later recovered or disposed of using this id. | ||
func (s *sequentialContextStoreImpl[T]) Store(t T) ItemID { | ||
id := s.nextID | ||
s.nextID++ | ||
|
||
s.storage[id] = t | ||
return id | ||
} | ||
|
||
// Recover returns the data stored under the provided id. | ||
// Note that the data will continue to exist in the ContextStore. | ||
// In order to dispose of the data, call s.Dispose(id) or s.RecoverAndDispose(id). | ||
func (s *sequentialContextStoreImpl[T]) Recover(id ItemID) T { | ||
item, present := s.storage[id] | ||
if !present { | ||
panic(fmt.Errorf("item with id '%v' is not present in the ContextStore", id)) | ||
} | ||
|
||
return item | ||
} | ||
|
||
// Dispose removes the data from the ContextStore. | ||
func (s *sequentialContextStoreImpl[T]) Dispose(id ItemID) { | ||
delete(s.storage, id) | ||
} | ||
|
||
// RecoverAndDispose returns the data stored under the provided id and removes it from the ContextStore. | ||
func (s *sequentialContextStoreImpl[T]) RecoverAndDispose(id ItemID) T { | ||
t := s.Recover(id) | ||
s.Dispose(id) | ||
return t | ||
} |
Oops, something went wrong.