Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DRAFT: Chunk-wise service event verification - ChunkIndexed[ServiceEvent] #6730

Draft
wants to merge 3 commits into
base: feature/efm-recovery
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions model/flow/chunk.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,17 @@ func init() {
}

type ChunkBody struct {
// TODO(jord): what about service event chunk?
CollectionIndex uint

// execution info
StartState StateCommitment // start state when starting executing this chunk
EventCollection Identifier // Events generated by executing results
BlockID Identifier // Block id of the execution result this chunk belongs to
StartState StateCommitment // start state when starting executing this chunk
// EventCollection is the Merkle root commitment for the events emitted in this chunk.
// It commits to the order and content of all events. It also commits to the indices of
// any service events emitted relative to all service events emitted in the overall block.
// See [EventsMerkleRootHash] for details.
EventCollection Identifier
BlockID Identifier // Block id of the execution result this chunk belongs to

// Computation consumption info
TotalComputationUsed uint64 // total amount of computation used by running all txs in this chunk
Expand Down
1 change: 1 addition & 0 deletions model/flow/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ func (el EventsList) ByteSize() int {

// EventsMerkleRootHash calculates the root hash of events inserted into a
// merkle trie with the hash of event as the key and encoded event as value
// TODO(jord): update to include service events
func EventsMerkleRootHash(el EventsList) (Identifier, error) {
tree, err := merkle.NewTree(IdentifierLen)
if err != nil {
Expand Down
61 changes: 58 additions & 3 deletions model/flow/service_event.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
"github.com/fxamacker/cbor/v2"
"github.com/vmihailenco/msgpack/v4"

"github.com/onflow/flow-go-sdk"

cborcodec "github.com/onflow/flow-go/model/encoding/cbor"
)

Expand Down Expand Up @@ -37,7 +39,49 @@
// encoding and decoding.
type ServiceEvent struct {
Type ServiceEventType
Event interface{}
Event any // TODO replace with typedServiceEvent type?
}

type ChunkIndexed[T any] struct {
// always set to true - used to differentiate from other types
// needed only while we support both ServiceEvent and ChunkIndexed[ServiceEvent]
__isChunkIndexed__ bool
ChunkIndex uint
Event T
}

func makeChunkIndexed[T any](event T, index uint) ChunkIndexed[T] {
return ChunkIndexed[T]{
__isChunkIndexed__: true,
ChunkIndex: index,
Event: event,
}
}

//func (c ChunkIndexed[T]) ID() Identifier {
// return c.Event.ID()
//}
//
//func (c ChunkIndexed[T]) isSpecificServiceEvent() {}

func ToChunkIndexedServiceEventList(chunkIndex uint, events ServiceEventList) ServiceEventList {
for i := range events {
events[i] = ServiceEvent{
Type: events[i].Type,
Event: makeChunkIndexed(events[i], chunkIndex),
}
}
return events
}

type typedServiceEvent interface {

Check failure on line 77 in model/flow/service_event.go

View workflow job for this annotation

GitHub Actions / Lint (./)

type `typedServiceEvent` is unused (unused)
// isSpecificServiceEvent is used to signal that a type is a specific ServiceEvent.
isSpecificServiceEvent()
IDEntity // all service events must be hashable
}

func (se *ServiceEvent) ID() flow.Identifier {
panic("")
}

// ServiceEventList is a handy container to enable comparisons
Expand Down Expand Up @@ -148,14 +192,25 @@
func unmarshalWrapped[E any](b []byte, marshaller marshallerImpl) (*E, error) {
wrapper := struct {
Type ServiceEventType
Event E
Event ChunkIndexed[E]
}{}
err := marshaller.unmarshalFunc(b, &wrapper)
if err != nil {
return nil, err
}
if wrapper.Event.__isChunkIndexed__ {
return &wrapper.Event.Event, nil
}

return &wrapper.Event, nil
priorVersionWrapper := struct {
Type ServiceEventType
Event E
}{}
err = marshaller.unmarshalFunc(b, &priorVersionWrapper)
if err != nil {
return nil, err
}
return &priorVersionWrapper.Event, nil
}

// UnmarshalWithType unmarshals the service event and returns it as a wrapped ServiceEvent type.
Expand Down
1 change: 1 addition & 0 deletions model/flow/service_event_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@ func TestEncodeDecode(t *testing.T) {
}

// ServiceEventCapable is an interface to convert a specific event type to a generic ServiceEvent type.
// TODO
type ServiceEventCapable interface {
ServiceEvent() flow.ServiceEvent
}
Expand Down
Loading