Giter Club home page Giter Club logo

ccf_draft's Introduction

On GitHub, I maintain or contribute to projects such as fxamacker/cbor, fxamacker/circlehash, onflow/atree, onflow/ccf, onflow/cadence, onflow/flow-go, etc.

My first open source project was fxamacker/cbor. It is used in projects by Arm Ltd., Cisco, Dapper Labs, EdgeX Foundry, Fraunhofer‑AISEC, Linux Foundation, Microsoft, Mozilla, Tailscale, Teleport, and others.

fxamacker/cbor passed multiple confidential security assessments in 2022. A nonconfidential security assessment (prepared by NCC Group for Microsoft Corporation) includes a subset of fxamacker/cbor v2.4.0 without finding any vulnerabilities.

Most of the code I wrote is closed source (in many languages but mostly multithreaded C++). I'm currently enjoying open source projects and the amazing simplicity of Go.

Some of my open source work is described here.

Design & Implementation

image

onflow/atree: Atree provides scalable arrays and maps. It is used by Cadence in the Flow Blockchain.

Atree segments, encodes, and stores data into chunks of relatively small size. This enables blockchains to only hash and transmit modified chunks (aka payloads) instead of the entire array, map, or large element.

Among other aspects, I designed and implemented a novel hash collision handling method. It is different from published methods such as Cuckoo Hashing, Double Hashing, 2-Choice Hashing, etc.

This new hash collision handling method balances speed, security, storage size, etc. It uses a fast noncryptographic 64-bit hash and if there is a hash collision, it uses deferred and segmented 256-bit cryptographic digest (in 64-bit segments). By default, it uses CircleHash64f and BLAKE3.

Acknowledgements: Atree wouldn't exist without Dieter Shirley making priorities clear and inspiring us, Ramtin M. Seraj leading the R&D and empowering us to innovate, and Bastian Müller improving Atree while leading the integration into Cadence. Many thanks to Supun Setunga for the very complex data migration work and more!

Optimizations

When feasible, my optimizations improve speed, memory, storage, and network use without negative tradeoffs.

onflow/flow-go: Found optimizations by reading unfamiliar source code and proposed them to resolve issue #1750. Very grateful for Ramtin M. Seraj for opening a batch of issues and letting me tackle this one.

PR #1944 (Optimize MTrie Checkpoint for speed, memory, and file size):

  • SPEED: 171x speedup (11.4 hours to 4 minutes) in MTrie traversing/flattening/writing phase (without adding concurrency) which led to a 47x speedup in checkpointing (11.7 hours to 15 mins).
  • MEMORY: -431 GB alloc/op (-54.35%) and -7.6 billion allocs/op (-63.67%)
  • STORAGE: -6.9 GB file size (without using compression yet)

After PR #1944 reduced Mtrie flattening and serialization phase to under 5 minutes (which sometimes took 17 hours on mainnet16), creating a separate MTrie state used most of the remaining duration and memory.

Additional optimizations (add concurrency, add compression, etc.) were moved to separate issue/PR and I switched my focus to related issues like #1747.

UPDATE: About six months later, file size grew from 53GB to 126GB and checkpointing frequency increased to every few hours (instead of about once daily) due to increased transactions and data size. Without PR #1944, checkpointing would be taking over 20-30 hours each time, require more operational RAM, and slowdown the system with increased gc pressure. More info: issue #2286 and PR #2792.

Evaluations and Improvements

fxamacker/circlehash: I created CircleHash64 on weekends after evaluating state-of-the-art fast hashes for work. At the time, I needed a fast hash for short input sizes typically <128 bytes but didn't like existing hashes. I didn't want to reinvent the wheel so I based it on Google Abseil C++ internal hash. CircleHash64 is well-rounded: it balances speed, digest quality, and maintainability.

CircleHash64 has good results in Strict Avalanche Criterion (SAC).

CircleHash64 Abseil C++ SipHash-2-4 xxh64
SAC worst-bit
0-128 byte inputs
(lower % is better)
0.791% 🥇
w/ 99 bytes
0.862%
w/ 67 bytes
0.802%
w/ 75 & 117 bytes
0.817%
w/ 84 bytes

☝️ Using demerphq/smhasher updated to test all input sizes 0-128 bytes (SAC test will take hours longer to run).

CircleHash64 is fast at hashing short inputs with a 64-bit seed

CircleHash64
(seeded)
XXH3
(seeded)
XXH64
(w/o seed)
SipHash
(seeded)
4 bytes 1.34 GB/s 1.21 GB/s 0.877 GB/s 0.361 GB/s
8 bytes 2.70 GB/s 2.41 GB/s 1.68 GB/s 0.642 GB/s
16 bytes 5.48 GB/s 5.21 GB/s 2.94 GB/s 1.03 GB/s
32 bytes 8.01 GB/s 7.08 GB/s 3.33 GB/s 1.46 GB/s
64 bytes 10.3 GB/s 9.33 GB/s 5.47 GB/s 1.83 GB/s
128 bytes 12.8 GB/s 11.6 GB/s 8.22 GB/s 2.09 GB/s
192 bytes 14.2 GB/s 9.86 GB/s 9.71 GB/s 2.17 GB/s
256 bytes 15.0 GB/s 8.19 GB/s 10.2 GB/s 2.22 GB/s
  • Using Go 1.17.7, darwin_amd64, i7-1068NG7 CPU
  • Results from go test -bench=. -count=20 and benchstat
  • Fastest XXH64 in Go+Assembly doesn't support seed

CircleHash64 doesn't have big GB/s drops in throughput as input size gets larger. Other CircleHash variants are faster for larger input sizes and a bit slower for short inputs (not yet published).

Implement IETF Internet Standards (RFC 8949 & RFC 7049)

fxamacker/cbor: I designed and implemented a secure CBOR codec after reading RFC 7049. During implementation, I helped review the draft leading to RFC 8949. The CBOR codec rejects malformed CBOR data and has an option to detect duplicate map keys. It doesn't crash when decoding bad CBOR data.

Decoding 9 or 10 bytes of malformed CBOR data shouldn't exhaust memory. For example,
[]byte{0x9B, 0x00, 0x00, 0x42, 0xFA, 0x42, 0xFA, 0x42, 0xFA, 0x42}

Decode bad 10 bytes to interface{} Decode bad 10 bytes to []byte
fxamacker/cbor
1.0-2.3
49.44 ns/op, 24 B/op, 2 allocs/op* 51.93 ns/op, 32 B/op, 2 allocs/op*
ugorji/go 1.2.6 ⚠️ 45021 ns/op, 262852 B/op, 7 allocs/op 💥 runtime: out of memory: cannot allocate
ugorji/go 1.1-1.1.7 💥 runtime: out of memory: cannot allocate 💥 runtime: out of memory: cannot allocate

*Speed and memory are for latest codec version listed in the row (compiled with Go 1.17.5).

fxamacker/cbor CBOR safety settings include: MaxNestedLevels, MaxArrayElements, MaxMapPairs, and IndefLength.

Professional Background

I try to balance competing factors such as speed, security, usability, and maintainability based on each project's priorities.

Most recently, I accepted an offer I received on April 13, 2021 from Dapper Labs. I had been working for them as an independent contractor for about two weeks to help optimize Cadence storage layer and to create a streaming mode branch of fxamacker/cbor. On my first day as a contractor, I created issue 738 and the Cadence team was very welcoming and productive to work with. I subsequently opened 100+ issues and 100+ PRs at work in 2021.

My prior experience before Dapper Labs includes co-founding & bootstrapping enterprise software company, and working as an IT consultant.

  • My smallest consulting client - a startup. I assisted with prototyping which helped secure their next round of funding.
  • My largest consulting client - an S&P 500 company with almost 50,000 employees. I evaluated (as part of a large team) various technologies to be selected for their new global stack for deployment to over 100 countries.
  • My largest software licensing+subscription+support client - a company with over 3,000 employees in the US that deployed my data security system to all their US-based offices and factories. The tamper-resistant system used 4 types of servers to distribute and enforce security policies across multiple timezones for various client software. The system was designed to repair and update itself with bugfixes without introducing downtime. I was only one of two people to ever have access to the source code: just two of us conceived, designed, implemented, tested, and maintained the system. Our system beat enterprise solutions from well-funded large competitors year after year during customer evaluations which included testing employee-attempted data theft. It was not approved for export or use outside the US.

Developing commercial software provided the advantage of choosing the most appropriate language and framework for each part of the system because the customers didn't know what programming languages, tools, or frameworks were used.

ccf_draft's People

Contributors

fxamacker avatar turbolent avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

ccf_draft's Issues

Add more types and reassign CBOR tag numbers in CDDL

The following improvements were identified by reading Cadence Core Contracts with CCF specs and codec in mind.

More types need to be added in CDDL:

  • struct interface type
  • resource interface type
  • contract interface type
  • reference type
  • restricted type

Reassign tag numbers to reserve some tag numbers in each (sub)group.

Add interface types as options to ccf-composite-type-message. This is more extensible than using simple type at the cost of encoding a little more data.

Add reference and restricted types as options to inline-type.

Add support for function value.

Refactor CDDL to separate type objects from type value objects for readability and cleaner implementation.

Remove unnecessary cadence-type-id

Problem

In JSON-CDC, sometimes cadence-type-id was encoded when it was just a "stringification" of other encoded data and not necessary to encode.

In CCF, we don't need to keep this inefficiency for the sake of compatibility.

Thanks @turbolent for spotting this! 👍

Proposed Solution

Remove the inefficiency by removing unnecessary cadence-type-id from

  • restricted-type-value
  • restricted-type
  • function-value

README has outdated status and introduction can be improved

The current status and timeline is outdated. Also, the introduction can be improved by copying this Introduction section from the CCF specification:

Introduction

Cadence external values (e.g. transaction arguments, events, etc.) have been encoded using JSON-Cadence Data Interchange format, which is human-readable, verbose, and doesn't define deterministic encoding.

CCF is a binary data format that allows more compact, efficient, and deterministic encoding of Cadence external values. Consequently, the CCF codec in Cadence is faster, uses less memory, encodes deterministically, and produces smaller messages than the JSON-CDC codec.

A real FeesDeducted event can encode to:

  • 298 bytes in JSON-CDC (minified).
  • 118 bytes in CCF (fully self-describing mode).
  • ~20 bytes in CCF (partially self-describing mode) with 12 bytes for data and ~8 bytes for type id (counter, hash, etc.)

Unlike prior formats, 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 deterministically produce identical messages.

For security, CCF was designed to allow efficient detection and rejection of malformed messages without creating Cadence objects. This allows more costly checks (e.g. validity) to be performed only on well-formed messages.

CCF leverages vendor-neutral Internet Standards such as CBOR (RFC 8949), which is designed to be relevant for decades.

Update Security Considerations

Mention decoding limits can be stricter for untrusted inputs and less strict for trusted inputs. For example, CBOR limits such as MaxArrayElements, MaxMapPairs, and MaxNestedLevels can be set differently for decoders processing trusted and untrusted inputs. CCF-based protocols can also specify different limits to balance tradeoffs.

The main tradeoff for decoder limits:

  • too high will allow memory exhaustion attacks, etc. to succeed.
  • too low will create the possibility of being unable to decode a non-malicious message that exceeds limits.
    NOTE: Encoders usually don't enforce limits because it's much simpler and more efficient for apps to enforce it.

Example Limit for Max Array Elements

A GRPC limit of 20 MB can support (at most) a 20,000,000 element array (for an unrealistic message with zero-overhead and 1 byte elements).

In practice, it would take many thousands of non-malicious CCF messages (like average-sized events) to reach a 20 MB GRPC limit, so it doesn't make sense to allow more than 20,000,000 elements for each array within a single CCF message.

This update to CCF specs can be done after opening PR to add CCF Codec to onflow/cadence and before CCF Specs RC2.

Update specs for composite-type-value.initializers

Some changes to specs are required:

  • Update composite-type-value.initializers from "one or many" to "zero or one" since only one initializer is supported and sorting is hard for multiple initializers.

  • Remove deterministic sorting requirement for composite-type-value.initializers since only one initializer is supported and initializer parameters have natural sorting and shouldn't be changed.

Thanks @turbolent for great discussion and suggesting this today!

Update outdated benchmarks in README

Benchmarks are from initial proof-of-concept CCF codec. We should update benchmarks and comparisons with a reminder that we are not comparing apples to apples.

Prior formats (CBF and JSON-Cadence Data Interchange) didn't specify requirements for validity, sorting, etc.

Sorting data, deterministic encoding, etc. are not free.

Add section about canonical encoding

For example, make it clear that CCF-based protocols and data formats must use a deterministic sequence when encoding more than one Cadence composite type.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.