-
Notifications
You must be signed in to change notification settings - Fork 138
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
Cadence Compact Format (CCF) Specification RC and CCF Codec (fully self-describing mode) #2157
Comments
is this related to previous work done in this area? or is it started from scratch? PS: notion doc is not accessible ( initial requirements ) |
EDIT: clarify answer to remove ambiguity, renamed CCF "design" section to "objectives" and replace wall of text with CCF Abstract Hi @bluesign
The requirements/objectives are related to previous work but design & implementation is from scratch:
Some reasons for CCF replacing previous work (the proposed Cadence Binary Format) are mentioned in onflow/flow-go#3448. E.g., it didn't have all required features (type and data were not separate, so redundant Cadence type info couldn't be eliminated from messages) and it didn't leverage existing data formats. CCF will close all 15 open issues in onflow/cadence related to Cadence Binary Format (CBF). BTW, I just updated text of this epic to add Preliminary Size and Benchmark Comparisons section. CCF's preliminary encoding size and benchmark comparisons are at onflow/flow-go#3593.
The initial requirements in notion is captured by the Objectives section of CCF Specifications, which is a superset of initial requirements doc. For example, it adds early detection of malformed data (so CCF codecs don't need to create Cadence objects when attempting to decode malformed data). See Draft CCF Specification for more details (superset of initial requirements from notion is listed in the Objectives section). For convenience, here's the abstract: AbstractCadence Compact Format (CCF) is a data format designed for compact, efficient, and deterministic encoding of Cadence external values. Cadence is a resource-oriented programming language that introduces new features to smart contract programming. It's used by Flow blockchain and has a syntax inspired by Swift, Kotlin, and Rust. Its use of resource types maps well to the Move language. CCF can be used as a hybrid data format. CCF-based messages can be fully self-describing or partially self-describing. Both are more compact than JSON-based messages. CCF-based protocols can send Cadence metadata just once for all messages of that type. Malformed data can be detected without Cadence metadata and without creating Cadence objects. |
thanks @fxamacker, I read in detail, it is really well designed and solid. |
Thanks @bluesign for taking a look at the draft specs. I updated my reply (it's still long but less so). 😄 More detailed requirements were added to specs and PR #2364 has the CCF codec implementing CCF Specification (RC1). PR #2364 has more up-to-date info, including size & benchmark comparisons using 48,000+ events from a mainnet transaction. |
thanks @fxamacker I just checked the benchmarks, but I feel CCF should be a lot faster. Plugging something like go-json etc, would easily make them similar encoding performances. ( which in those events probably 30-40% time is spent on encoding UFix64 to String for json ) |
Hi @bluesign, Yes, I also think CCF codec can be faster (it will be 😄). There are tradeoffs to get deterministic encoding, compact size, etc. For the first implementation, I'm focused on correctness because CCF is already faster, uses less memory, and produces smaller encoded size than JSON. There are possible optimizations to increase encoding performance. I want to check use cases with Cadence and FVM team before implementing them. Some optimizations may be at CCF level, some at CCF-based protocol level. We'll see. Apples to Apples Speed ComparisonsSpeed comparisons need to account for extra requirements such as deterministic encoding, extra data validation, and smaller encoded data size. JSON-Cadence Data Interchange (JSON-CDC) doesn't sort and isn't deterministic.
As noted earlier, complying with extra requirements such as determinism, sorting, compact size, etc. requires extra processing and memory but CCF is still faster, uses less memory, and produces smaller encoded size. After fuzzing is in place, CCF codec and CCF-based protocols can be optimized for even faster speed if needed. 😄 |
yeah I meant in a good way that there is a big buffer for optimisations. :)
how this can be possible? I don't believe JSON-CDC (encoder) can be non-deterministic, can you explain a bit on that?
this shouldn't be a performance bottleneck, as it is not sorting. second one is benefit to performance.
sort here also confused me too ( but probably related to first question ) Btw: Btw I really love CCF, my comments usually sound a bit grumpy or criticising as English is my second language, I am just trying to understand it deeper. |
Hi @bluesign
Your English is excellent and didn't sound negative at all! 👍
Yes, although this isn't a bottleneck for decoder, the encoder does extra work to avoid encoding redundant Cadence type information and it is a tradeoff for encoding less data.
I agree with @turbolent's comment last year in issue #2165, that "The JSON encoding is not deterministic". The JSON-CDC Specifications doesn't mention "sort". That is an indication that it doesn't fully specify how to encode deterministically (e.g. how encoders must sort dictionaries). JSON-CDC encoder doesn't sort dictionary elements or composite fields. For ordering these, the encoder relies on implementation detail of Cadence (outside of the encoder). For these reasons, we cannot claim JSON-CDC encoding is deterministic. |
Closing this.
Future changes to codec should be fuzzed before being merged. |
Problem
Currently, Cadence external values (such as events) are encoded using JSON-Cadence Data Interchange Format. The JSON-based format is a human-readable text encoding that is verbose, inefficient, and doesn't define deterministic encoding (canonical format).
Proposed Solution
Design and specify Cadence Compact Format (CCF) as a more compact, efficient, and deterministic alternative to the JSON-based format.
We can leverage an existing data format's data model to reduce complexity, cost, and risks to CCF specs and codecs.
Additionally, we can design and implement a CCF codec by using an existing codec (e.g. the same way COSE codec uses CBOR codec under the hood).
For more info about CCF requirements or design considerations, see
Scope
CCF Specifications only specifies Cadence Compact Format.
It is outside the scope of CCF Specifications to specify individual CCF-based formats or protocols (e.g. events).
Introduction
CCF is a data format that allows compact, efficient, and deterministic encoding of Cadence external values.
Cadence external values (e.g. events, transaction arguments, etc.) have been encoded using JSON-CDC, which is inefficient, verbose, and doesn't define deterministic encoding.
The same
FeesDeducted
event on the Flow blockchain can encode to:CCF defines all requirements for deterministic encoding (sort orders, smallest encoded forms, and Cadence-specific requirements) to allow CCF codecs implemented in different programming languages to produce the same deterministic encodings.
Some requirements (such as "Deterministic CCF Encoding Requirements") are defined as optional. Each CCF-based format or protocol can have its specification state how CCF options are used. This allows each protocol to balance tradeoffs such as compatibility, determinism, speed, encoded data size, etc.
CCF uses CBOR and is designed to allow efficient detection and rejection of malformed messages without creating Cadence objects. This allows more costly checks for validity, etc. to be performed only on well-formed messages.
CBOR is an Internet Standard defined by IETF STD 94. CBOR is designed to be relevant for decades and is used by data formats and protocols such as W3C WebAuthn, C-DNS (IETF RFC 8618), COSE (IETF STD 96), CWT (IETF RFC 8392), etc.
Preliminary Benchmark Comparisons (obsolete)
We are not comparing apples to apples. Prior formats (CBF and JSON-Cadence Data Interchange) didn't specify requirements for validity, sorting, etc.
At this time, CCF decoder doesn't include the option to check for "Preferred Serialization" (encoding to smallest size).
These informal and preliminary benchmarks used CCF in fully self-describing mode (see size comparisons above).
TODO
team(s)@SupunS - Review PR Add CCF codec implementing CCF Specification (RC1) #2364.TBD and team(s)@fxamacker - Add more tests until 83% coverage (PR 2364 was opened withgo test -cover
at 77.3%). All non-error code path is covered by tests except for 1 line. Done in PR 2364 rather than as separate item.TBD and team(s)@SupunS & @turbolent - Fuzz test CCF Codec #2377 and run fuzz tests. @supun found several issues while fuzzing 🙌 which we fixed, so this was worthwhile. 🎉Next steps, such as integration and use of CCF for events, transaction arguments, etc. are outside the scope of this epic.
Edits
The text was updated successfully, but these errors were encountered: