-
Notifications
You must be signed in to change notification settings - Fork 170
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
frc(0069): change v2 piece multihashes to enable arbitrarily sized data #808
Changes from all commits
0b7c6cb
31ca3dd
16c5193
345a9bd
55f2958
9d8f249
d931caa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -12,7 +12,7 @@ created: 2023-07-26 | |||||||||||||||||
|
||||||||||||||||||
## Simple Summary | ||||||||||||||||||
|
||||||||||||||||||
Introduces an alternative CID representation for the FR32 padded sha256-trunc254-padded binary merkle trees used in Filecoin Piece Commitments (i.e. CommP). In it we use the [Raw codec](https://github.com/multiformats/multicodec/blob/566eaf857a9d20573d3910221db7b34d98e8a0fc/table.csv#L41) and a new [sha2-256-trunc254-padded-binary-tree multihash (or piece multihash)](https://link.tld) rather than the [Fil-commitment-unsealed codec](https://github.com/multiformats/multicodec/blob/566eaf857a9d20573d3910221db7b34d98e8a0fc/table.csv#L517) and the [sha2-256-trunc254-padded multihash](https://github.com/multiformats/multicodec/blob/566eaf857a9d20573d3910221db7b34d98e8a0fc/table.csv#L149). | ||||||||||||||||||
Introduces an alternative CID representation for the FR32 padded sha256-trunc254-padded binary merkle trees used in Filecoin Piece Commitments (i.e. CommP). In it we use the [Raw codec](https://github.com/multiformats/multicodec/blob/566eaf857a9d20573d3910221db7b34d98e8a0fc/table.csv#L41) and a new [sha2-256-trunc254-padded-binary-tree multihash (or piece multihash)](https://github.com/multiformats/multicodec/pull/331) rather than the [Fil-commitment-unsealed codec](https://github.com/multiformats/multicodec/blob/566eaf857a9d20573d3910221db7b34d98e8a0fc/table.csv#L517) and the [sha2-256-trunc254-padded multihash](https://github.com/multiformats/multicodec/blob/566eaf857a9d20573d3910221db7b34d98e8a0fc/table.csv#L149). | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm ok with this. Any objections? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not eager to change lib names but ok if it's a must. publishing packages with last name triggered npm's spam filter so I had to email etc... I suspect same will happen with this name also. |
||||||||||||||||||
|
||||||||||||||||||
|
||||||||||||||||||
## Abstract | ||||||||||||||||||
|
@@ -24,7 +24,7 @@ For example, in much of the relevant portions of the Filecoin spec and lotus' Go | |||||||||||||||||
|
||||||||||||||||||
This makes it much more natural to work with new concepts like [Deal Aggregates](https://pkg.go.dev/github.com/filecoin-project/[email protected]/datasegment#NewAggregate), as proposed in [FRC-0058](https://github.com/filecoin-project/FIPs/blob/7e499523c9c7ed2c48c6a36967f7f011cee1fefd/FRCs/frc-0058.md). | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit, but the use of the word "concepts" in the above sentence could also benefit from specification. Is it possible to do so? Perhaps "unstructured", "variably sized" or "large" data, etc., whatever is/may be accurate. |
||||||||||||||||||
|
||||||||||||||||||
To resolve this we introduce a new multihash type [fr32-sha2-256-trunc254-padded-binary-tree multihash](https://link.tld) which combines the root hash with the tree height (which in the full and balanced binary trees used in Piece commitments is equivalent to size). | ||||||||||||||||||
To resolve this we introduce a new multihash type [fr32-sha2-256-trunc254-padded-binary-tree multihash](https://github.com/multiformats/multicodec/pull/331) which combines the root hash with the tree height and the amount of padding of the data with zeros such that the result is a full and balanced binary tree after the fr32 padding is applied. If this multihash were to be used to reference the full piece as understood by the Filecoin on-chain consensus mechanism, this would involve the special case where a padding of zero is used. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm failing to understand the last sentence, what is that special case ? I think it would be a good idea if this was clear to someone like me who's not well versed in filecoin on-chain consensus mechanism or we simple have not mentioned it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was the earlier text better, or both confusing? Basically the idea is:
Suggestions welcome though There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps a fun fact: Switching from a v1 piece CID to a v2 one (i.e. assuming zero padding) results in a piece CID that is exactly the same size.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe?
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ribasushi I think you meant "hash payload" and not "hashed payload" right ? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this is true, yet misleading. It is true you can translate There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I meant
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adding comment here about line 21: it should mention |
||||||||||||||||||
|
||||||||||||||||||
## Specification | ||||||||||||||||||
|
||||||||||||||||||
|
@@ -36,11 +36,25 @@ A CIDv1 requires a: | |||||||||||||||||
|
||||||||||||||||||
The core component introduce in this specification is a new multihash type fr32-sha2-256-trunc254-padded-binary-tree multihash. | ||||||||||||||||||
|
||||||||||||||||||
The multihash code for this type is 0x1011 as identifier in the [multicodec code table](https://link.tld). | ||||||||||||||||||
The multihash code for this type is 0x1011 as identified in the [multicodec code table](https://github.com/multiformats/multicodec/pull/331). | ||||||||||||||||||
|
||||||||||||||||||
The digest for the multihash is 33 bytes. The first byte defines the height of the tree. For example if the first byte is 0 the tree is a single 32-byte leaf. Similarly, if the first byte is 30 then the tree is 30 levels deep which, since the leaves must be 32 bytes, represents a piece of size 32*2^30 bytes = 32GiB. | ||||||||||||||||||
The digest for the multihash is a variable number of bytes. | ||||||||||||||||||
|
||||||||||||||||||
Note that the data processed by this hash function must be of size `N = 2^i * 127/128` where `i` is any positive integer >=7 and <=255. This means that the minimum hashable amount of data is 127 bytes. | ||||||||||||||||||
It can be roughly described as `uvarint padding | uint8 height | 32 byte root data` where `|` means concatenation. | ||||||||||||||||||
|
||||||||||||||||||
- The first bytes are a [uvarint](https://github.com/multiformats/unsigned-varint) of the number of bytes needed to pad the underlying data such that after FR32 padding it will be a full binary tree | ||||||||||||||||||
- If the data is < 127 bytes then it is padded to 127 bytes. For example, if the data is of size 12 the padding will be `127-12 = 115` | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the "why" here necessary? I'm fine with it, but it's not strictly needed right? Nothing changes for us here if it was decided that fr32 allows padding up the last byte if the data isn't a multiple of 127 since this spec insists that it does. Is the "why" here a placeholder for claiming that ground since there's no fr32 spec beyond the couple lines on specs.filecoin.io and those don't mention 127 bytes at all?
Comment on lines
+45
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For what it's worth I think formula should be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I agree that the mathier version is more natural here. |
||||||||||||||||||
- For example, if the data is of size 254 (i.e. 2^i * 127/128, where i is a positive integer >= 7) then this will be 0 | ||||||||||||||||||
- For example, if the data is of size 256 then the padding is `508-256=252` | ||||||||||||||||||
- Note: because the unsigned-varint spec currently has a maximum representable size of 2^63-1 (and 9 bytes to represent the varint) this puts a cap on the maximum size of data representable by this multihash as well | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While we don't strictly need to follow the unsigned-varint spec here and have a maximum size it seems like a pretty reasonable thing to do. Any disagreement? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we deal with such large payloads so we're probably ok, but probably good to confirm with @ribasushi if that could be an issue elsewhere There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If your PieceCid describes something larger than 63 bits ( 8 EiB ), then the "actual payload size" becomes meaningless anyway, and you are in world with padding of |
||||||||||||||||||
- Note: because this is padding data it must be less than the size of the underlying data (with the exception of data less than 127 bytes which is always padded up to 127 bytes) | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given the |
||||||||||||||||||
- The next byte defines the height of the tree | ||||||||||||||||||
- For example if the first byte is 0 the tree is a single 32-byte node | ||||||||||||||||||
|
||||||||||||||||||
- Similarly, if the first byte is 30 then the tree is 30 levels deep which, since the leaves must be 32 bytes, represents a piece of size 32*2^30 bytes = 32GiB. | ||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only the leaf nodes matter here. If the intermediate nodes were bigger than leaf nodes (e.g. if they'd included one extra byte flagging them as intermediate nodes 🙃) the data size would be unchanged. |
||||||||||||||||||
- The last 32 bytes are the value at the root of the binary tree | ||||||||||||||||||
|
||||||||||||||||||
Note: This structure is such that the last 33 bytes of the multihash are `uint 8 height | 32 byte root data` which is the data that the proofs underlying Filecoin consensus can attest to (i.e. the proofs don't know how much of the padding is padding vs zeros that are part of the user data). | ||||||||||||||||||
|
||||||||||||||||||
### Raw codec | ||||||||||||||||||
|
||||||||||||||||||
|
@@ -63,11 +77,21 @@ A tuple of (v1 Piece CID, Piece size) can be converted into a valid v2 Piece CID | |||||||||||||||||
|
||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Making a note about line 69: |
||||||||||||||||||
## Test Cases | ||||||||||||||||||
|
||||||||||||||||||
Take data of size 127*4 bytes where the first 127 bytes are 0, the next 127 are 1, the next 127 are 2, and the last 127 are 3. The v1 piece CID of this data would be `baga6ea4seaqes3nobte6ezpp4wqan2age2s5yxcatzotcvobhgcmv5wi2xh5mbi`. The multihash-based piece CID would be `bafkzcibbarew3lqmzhrgl37fuadoqbrguxofyqe6luyvlqjzqtfpnsgvz7lak`. With a base16 multibase this would be `f015591202104496dae0cc9e265efe5a006e80626a5dc5c409e5d3155c13984caf6c8d5cfd605` or equivalently (`(multibase = f) | (CIDv1 prefix = 0x01) | (Raw codec = 0x55) | (fr32-sha2-256-trunc254-padded-binary-tree multihash encoded varint = 0x9120) | (length of digest = 0x21) | (tree height = 0x04) | (underlying hash digest = 496...605)`) | ||||||||||||||||||
Take data of size 127*4 bytes where the first 127 bytes are 0, the next 127 are 1, the next 127 are 2, and the last 127 are 3. The v1 piece CID of this data would be `baga6ea4seaqes3nobte6ezpp4wqan2age2s5yxcatzotcvobhgcmv5wi2xh5mbi`. The multihash-based piece CID would be `bafkzcibcaaces3nobte6ezpp4wqan2age2s5yxcatzotcvobhgcmv5wi2xh5mbi`. With a base16 multibase this would be `f01559120220004496dae0cc9e265efe5a006e80626a5dc5c409e5d3155c13984caf6c8d5cfd605` or equivalently (`(multibase = f) | (CIDv1 prefix = 0x01) | (Raw codec = 0x55) | (fr32-sha2-256-trunc254-padded-binary-tree multihash encoded varint = 0x9120) | (length of digest = 0x22) | (amount of data padding = 0x00) | (tree height = 0x04) | (underlying hash digest = 496...605)`) | ||||||||||||||||||
Take payload of size 0 bytes. There MUST be `127` bytes of padding. The v2 piece CID MUST be `bafkzcibcp4bdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy`. | ||||||||||||||||||
|
||||||||||||||||||
Take payload of 127 bytes where all bytes are 0. There MUST be `0` bytes of padding. The hight MUST be `2`. The v2 piece CID MUST be `bafkzcibcaabdomn3tgwgrh3g532zopskstnbrd2n3sxfqbze7rxt7vqn7veigmy`. | ||||||||||||||||||
|
||||||||||||||||||
aschmahmann marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
Take payload of 128 bytes where all bytes are 0. There MUST be `126` bytes of padding. The height MUST be `3`. The v2 piece CID MUST be `bafkzcibcpybwiktap34inmaex4wbs6cghlq5i2j2yd2bb2zndn5ep7ralzphkdy` | ||||||||||||||||||
Given the piece CID v1 of the empty 32 GiB piece (i.e. 32 * 2^30 * 127/128 bytes of zeros)`baga6ea4seaqao7s73y24kcutaosvacpdjgfe5pw76ooefnyqw4ynr3d2y6x2mpq` the corresponding mutlihash piece CID would be `bafkzcibcaapao7s73y24kcutaosvacpdjgfe5pw76ooefnyqw4ynr3d2y6x2mpq` | ||||||||||||||||||
|
||||||||||||||||||
Given the piece CID v1 of the empty 64 GiB piece (i.e. 64 * 2^30 * 127/128 bytes of zeros)`baga6ea4seaqomqafu276g53zko4k23xzh4h4uecjwicbmvhsuqi7o4bhthhm4aq` the corresponding piece mutlihash piece CID would be `bafkzcibcaap6mqafu276g53zko4k23xzh4h4uecjwicbmvhsuqi7o4bhthhm4aq` | ||||||||||||||||||
|
||||||||||||||||||
Take data of size 127*8 bytes where the first where the first 127 bytes are 0, the next 127 are 1, the next 127 are 2, the next 127 are 3 and the remaining `127*4` bytes are 0. There is no padding so the v1 piece CID would be `baga6ea4seaqn42av3szurbbscwuu3zjssvfwbpsvbjf6y3tukvlgl2nf5rha6pa` and the v2 would be `bafkzcibcauan42av3szurbbscwuu3zjssvfwbpsvbjf6y3tukvlgl2nf5rha6pa`. | ||||||||||||||||||
|
||||||||||||||||||
Given the piece CID v1 of the empty 32 GiB piece `baga6ea4seaqao7s73y24kcutaosvacpdjgfe5pw76ooefnyqw4ynr3d2y6x2mpq` the corresponding mutlihash piece CID would be `bafkzcibbdydx4x66gxcqveyduviaty2jrjhl5x7ttrbloefxgdmoy6whv6td4` | ||||||||||||||||||
Take data of size 128*4 bytes where the first where the first 127 bytes are 0, the next 127 are 1, the next 127 are 2, the next 127 are 3 and the remaining 4 bytes are 0. There is `504` bytes of padding needed and so the v1 piece CID is `baga6ea4seaqn42av3szurbbscwuu3zjssvfwbpsvbjf6y3tukvlgl2nf5rha6pa` (notice it's the same as above) and the v2 is `bafkzcibd7abqlxticxolgseegik2stpfgkkuwyf6kufex3doorkvmzpjuxwe4dz4`. | ||||||||||||||||||
|
||||||||||||||||||
Given the piece CID v1 of the empty 64 GiB piece `baga6ea4seaqomqafu276g53zko4k23xzh4h4uecjwicbmvhsuqi7o4bhthhm4aq` the corresponding piece mutlihash piece CID would be `bafkzcibbd7teabngx7rxo6ktxcww56j7b7fbasnsaqlfj4vech3xaj4zz3hae` | ||||||||||||||||||
Take the data above and append one more zero (i.e. 127 0s, 127 1s, 127 2s, 127 3s, 5 0s). There are `503` bytes of padding needed and so the v1 piece CID is `baga6ea4seaqn42av3szurbbscwuu3zjssvfwbpsvbjf6y3tukvlgl2nf5rha6pa` (notice it's the same as above) and the v2 is `bafkzcibd64bqlxticxolgseegik2stpfgkkuwyf6kufex3doorkvmzpjuxwe4dz4`. | ||||||||||||||||||
|
||||||||||||||||||
## Security Considerations | ||||||||||||||||||
Does not impact core Filecoin security. | ||||||||||||||||||
|
@@ -82,7 +106,7 @@ This also enables the use of IPFS-based tooling for moving around Pieces, with t | |||||||||||||||||
|
||||||||||||||||||
## Implementation | ||||||||||||||||||
|
||||||||||||||||||
- There is a Go implementation in a [fork of go-fil-commcid](https://github.com/filecoin-project/go-fil-commcid/pull/5) which can get merged [upstream](https://github.com/filecoin-project/go-fil-commcid) upon acceptance of the FRC. | ||||||||||||||||||
- There is a Go implementation in a [fork of go-fil-commcid](https://github.com/filecoin-project/go-fil-commcid/pull/6) which can get merged [upstream](https://github.com/filecoin-project/go-fil-commcid) upon acceptance of the FRC. | ||||||||||||||||||
- There is a JavaScript implementation in https://github.com/web3-storage/data-segment/ | ||||||||||||||||||
|
||||||||||||||||||
## Copyright | ||||||||||||||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Regardless of which version of the Simple Summary is merged by the author, can we add a few extra words about why this alternative CID representation is being introduced? What functionality or improvement does it support?