-
Notifications
You must be signed in to change notification settings - Fork 298
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
adr: Data Availability Module and Components #414
Conversation
`Put` in push schema takes all the shares of an extended square, encodes every share along with a `(col;row)` coordinate | ||
together with `DataHash` and publishes them to the `/celestia` topic. |
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.
I hope you don't mind the question: doesn't this introduce a DoS attack vector? because you can only validate if shares match a header on a row or column basis (if you have the DAHeader at hand, otherwise you need enough shares to reconstruct the whole block until you can be sure). @adlerjohn raised the concern that with presumably really large blocks this could cause problems.
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.
doesn't this introduce a DoS attack vector?
@liamsi, Note that there is no difference between spamming shares and rows/cols, as you can generate dummy data and spam the network for both with any amount. The only way to mitigate that is to use peer scoring. I'll describe how we can use this soon.
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.
Note that there is no difference between spamming shares and rows/cols, as you can generate dummy data and spam the network for both with any amount
Yeah, but it makes a difference how much data you must read before you can actually go and score a peer accordingly. In the case of rows you could after one garbage row, in the case of shares (and only having the data root) you'd need to see all shares first. But good point. And that scoring system looks interesting. In tendermint you can just mark peers as "bad" as far as I remember.
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.
@liamsi, It is true in case we use DAHeader, but later on we want to have DataHash only, and in such a case you will get the same situation as with share granularity.
DAHeader is essentially an inner node, so the question is - do we need to broadcast inner nodes?
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.
DAHeader is essentially an inner node, so the question is - do we need to broadcast inner nodes?
While that statement is true, I still see the DAHeader as a special case of inner nodes. We might want to broadcast the DAHeader but not all other inner nodes. I need to think about this.
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.
Chipping in here to note requiring 1/4 of the EDS (i.e. an ODS worth of shares) to be downloaded without verification will be a DoS vector. Not a RAM resource exhaustion, but a network bandwidth exhaustion.
@Wondertan when you say "and publishes them," are shares published individually, or an entire block? From what you wrote in this comment thread, it looks like individual shares, for which Merkle proofs are downloaded? Not sure.
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.
Chipping in here to note requiring 1/4 of the EDS (i.e. an ODS worth of shares) to be downloaded without verification will be a DoS vector. Not a RAM resource exhaustion, but a network bandwidth exhaustion.
@adlerjohn, It is, until you do verification, penalize spamming peer, stopping further communications with him, thus preventing DoS.
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.
when you say "and publishes them," are shares published individually, or an entire block?
@adlerjohn, individually
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.
If we can't verify the block until we fully received or recovered it, then there is no difference between sending it fully or by shares or by other pieces in terms of verification. However, sending shares in a batch could save more bandwidth, as we can append DataHash to batch instead of per share.
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.
The batch size can be maxed out to max PubSub message size. The default is 1mb and I am not aware of any rationale behind that. Indeed, there should be the most optimal message size for our use case.
Currently, `DAHeader` and block's `Data` are defined in `ll-core/types`. However, with modularity in mind and plan for | ||
DA to be used outside of `ll-core`, e.g. in `optimint`, it now make sense to move them to new `da` package. |
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.
Reiterating what I've mentioned in our call, it's non-obvious the lower-level APIs defined here need to be modular (e.g. the interfaces below).
Optimint is a good point but the abstractions there will be much more general.
Moving the DA logic out of the types package into a separate one (maybe even into a separate repo later) is a good point though. The networking-related methods don't belong in the types package 👌🏼
Though moving out the DAHeader
or the block's Data
out of the types package will be inconsistent with the other core types but maybe there are good reasons for that.
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.
+1 on moving out the DA logic. Also +1 on not moving out the Data
especially, as it's purely a detail of LazyLedger. The DAHeader
is a bit trickier, as it straddles both domains. Could the DAHeader
not be present in both ll-core
and da
?
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.
Could the DAHeader not be present in both ll-core and da
It can be removed entirely in general. But for now, I would just move it to DA lib and make ll-core
to depend on it and use DAHeader defined there.
// The goal of this interface is to become general enough to later abstract over other DA schemas, e.g. Kate comms, | ||
// along with different networking schemas. |
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.
This is not a goal we currently pursue. While it doesn't harm and the interface looks simple enough we don't need to plan ahead for a case that won't cleary become relevant in the next months (maybe years).
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.
I'll remove Kate comms form there.
} | ||
``` | ||
|
||
// TODO: Add to specs as well |
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.
I would just make an issue in the specs referencing this PR and the parameter choices instead of having this TODO.
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.
That's a self reminder to do so
### Package | ||
Data Availability related logic is place in `lazyledger-core/p2p/ipld`. The name and location was good for original | ||
purpose, as that's a p2p stuff that uses IPLD in it's core. However, currently it makes sense to generalize and rename | ||
the package to `da`(short for DataAvailability) or even move it in it's own repository, what could be done later with |
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.
nit
the package to `da`(short for DataAvailability) or even move it in it's own repository, what could be done later with | |
the package to `da`(short for DataAvailability) or even move it in its own repository, what could be done later with |
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.
Lastly, before making this PR ready, I will go through all the grammar and orthography.
Currently, `DAHeader` and block's `Data` are defined in `ll-core/types`. However, with modularity in mind and plan for | ||
DA to be used outside of `ll-core`, e.g. in `optimint`, it now make sense to move them to new `da` package. |
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.
+1 on moving out the DA logic. Also +1 on not moving out the Data
especially, as it's purely a detail of LazyLedger. The DAHeader
is a bit trickier, as it straddles both domains. Could the DAHeader
not be present in both ll-core
and da
?
// Put serializes Data, computes DAHeader and makes it available over the network. | ||
Put(context.Context, *types.Block) (*types.DataAvailabilityHeader, error) | ||
|
||
// Get efficiently retrieves block's Data using given DAHeader from the network. | ||
Get(context.Context, *types.DataAvailabilityHeader) (*types.Data, error) |
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.
In line with the above comment, it seems like a better abstraction to only use a DA header here, and not deal with blocks or block data. Instead, leave the latter 2 to ll-core.
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.
Yep, that's an early draft for the interface I had a few weeks ago. It's final form is still not clear for me
* `provideValidity=24h` - lifespan of a providing record. | ||
* `kBucketSize=20` - configures bucket size of the kademlia routing table. | ||
* `resiliency=3` - the number of peers closest to a target that must have responded in order for a given DHT query to | ||
complete. | ||
* `alpha=32` - configures the number of concurrent requests for a given DHT query. | ||
* `protocolPrefix="/celestia"` - protocol prefix to distinguish our DHT network |
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.
Is there a rationale for parameter choices?
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.
From what I can tell, these are mostly the current ipfs defaults (besides the protocolPrefix and I'm not sure about the resilience param). I'm sure Hlib just wrote them down to have something explicitly mentioned here to work with (which is good).
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.
I also increased alpha
`Put` in push schema takes all the shares of an extended square, encodes every share along with a `(col;row)` coordinate | ||
together with `DataHash` and publishes them to the `/celestia` topic. |
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.
Chipping in here to note requiring 1/4 of the EDS (i.e. an ODS worth of shares) to be downloaded without verification will be a DoS vector. Not a RAM resource exhaustion, but a network bandwidth exhaustion.
@Wondertan when you say "and publishes them," are shares published individually, or an entire block? From what you wrote in this comment thread, it looks like individual shares, for which Merkle proofs are downloaded? Not sure.
@Wondertan how do we want to proceed with this? Most of it is no longer relevant for this repo. If you want, we can still merge it as a draft to reference it in celestia-node later. Alternatively, we can close it and reconsider and finalize some of it as part of the lower level details in https://github.com/celestiaorg/celestia-node (I prefer the latter; feel free to reopen if you disagree). |
I agree. Although I would like to finish that at some point, so let's keep the branch. |
WIP