-
Notifications
You must be signed in to change notification settings - Fork 21
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
state: update SubmitPayForBlob api; api: add BlobAPI (#11)
## Overview This PR adds `type Blob`, adds `BlobAPI` and updates the API for `SubmitPayForBlob` to the latest version of celestia-node. Fixes #10 ## Checklist <!-- Please complete the checklist to ensure that the PR is ready to be reviewed. IMPORTANT: PRs should be left in Draft until the below checklist is completed. --> - [x] New and updated code has appropriate documentation - [x] New and updated code has new and/or updated testing - [x] Required CI checks are passing - [x] Visual proof for any user facing features like CLI or documentation updates - [x] Linked issues closed with keywords
- Loading branch information
Showing
13 changed files
with
849 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package appconsts | ||
|
||
import ( | ||
"math" | ||
|
||
"github.com/celestiaorg/rsmt2d" | ||
) | ||
|
||
// These constants were originally sourced from: | ||
// https://github.com/celestiaorg/celestia-specs/blob/master/src/specs/consensus.md#constants | ||
// | ||
// They can not change throughout the lifetime of a network. | ||
const ( | ||
// NamespaceVersionSize is the size of a namespace version in bytes. | ||
NamespaceVersionSize = 1 | ||
// NamespaceVersionMaxValue is the maximum value a namespace version can be. | ||
// This const must be updated if NamespaceVersionSize is changed. | ||
NamespaceVersionMaxValue = math.MaxUint8 | ||
|
||
// NamespaceIDSize is the size of a namespace ID in bytes. | ||
NamespaceIDSize = 28 | ||
|
||
// NamespaceSize is the size of a namespace (version + ID) in bytes. | ||
NamespaceSize = NamespaceVersionSize + NamespaceIDSize | ||
|
||
// ShareSize is the size of a share in bytes. | ||
ShareSize = 512 | ||
|
||
// ShareInfoBytes is the number of bytes reserved for information. The info | ||
// byte contains the share version and a sequence start idicator. | ||
ShareInfoBytes = 1 | ||
|
||
// SequenceLenBytes is the number of bytes reserved for the sequence length | ||
// that is present in the first share of a sequence. | ||
SequenceLenBytes = 4 | ||
|
||
// ShareVersionZero is the first share version format. | ||
ShareVersionZero = uint8(0) | ||
|
||
// DefaultShareVersion is the defacto share version. Use this if you are | ||
// unsure of which version to use. | ||
DefaultShareVersion = ShareVersionZero | ||
|
||
// CompactShareReservedBytes is the number of bytes reserved for the location of | ||
// the first unit (transaction, ISR) in a compact share. | ||
CompactShareReservedBytes = 4 | ||
|
||
// FirstCompactShareContentSize is the number of bytes usable for data in | ||
// the first compact share of a sequence. | ||
FirstCompactShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes - SequenceLenBytes - CompactShareReservedBytes | ||
|
||
// ContinuationCompactShareContentSize is the number of bytes usable for | ||
// data in a continuation compact share of a sequence. | ||
ContinuationCompactShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes - CompactShareReservedBytes | ||
|
||
// FirstSparseShareContentSize is the number of bytes usable for data in the | ||
// first sparse share of a sequence. | ||
FirstSparseShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes - SequenceLenBytes | ||
|
||
// ContinuationSparseShareContentSize is the number of bytes usable for data | ||
// in a continuation sparse share of a sequence. | ||
ContinuationSparseShareContentSize = ShareSize - NamespaceSize - ShareInfoBytes | ||
|
||
// MinSquareSize is the smallest original square width. | ||
MinSquareSize = 1 | ||
|
||
// MinshareCount is the minimum number of shares allowed in the original | ||
// data square. | ||
MinShareCount = MinSquareSize * MinSquareSize | ||
|
||
// MaxShareVersion is the maximum value a share version can be. | ||
MaxShareVersion = 127 | ||
) | ||
|
||
var ( | ||
// DefaultCodec is the default codec creator used for data erasure. | ||
DefaultCodec = rsmt2d.NewLeoRSCodec | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package appconsts | ||
|
||
import "time" | ||
|
||
// The following defaults correspond to initial parameters of the network that can be changed, not via app versions | ||
// but other means such as on-chain governance, or the nodes local config | ||
const ( | ||
// DefaultGovMaxSquareSize is the default value for the governance modifiable | ||
// max square size. | ||
DefaultGovMaxSquareSize = 64 | ||
|
||
// DefaultMaxBytes is the default value for the governance modifiable | ||
// maximum number of bytes allowed in a valid block. | ||
DefaultMaxBytes = DefaultGovMaxSquareSize * DefaultGovMaxSquareSize * ContinuationSparseShareContentSize | ||
|
||
// DefaultGasPerBlobByte is the default gas cost deducted per byte of blob | ||
// included in a PayForBlobs txn | ||
DefaultGasPerBlobByte = 8 | ||
|
||
// DefaultMinGasPrice is the default min gas price that gets set in the app.toml file. | ||
// The min gas price acts as a filter. Transactions below that limit will not pass | ||
// a nodes `CheckTx` and thus not be proposed by that node. | ||
DefaultMinGasPrice = 0.1 | ||
|
||
// DefaultUnbondingTime is the default time a validator must wait | ||
// to unbond in a proof of stake system. Any validator within this | ||
// time can be subject to slashing under conditions of misbehavior. | ||
DefaultUnbondingTime = 3 * 7 * 24 * time.Hour | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package blob | ||
|
||
import ( | ||
"bytes" | ||
"encoding/json" | ||
"errors" | ||
"fmt" | ||
|
||
"github.com/celestiaorg/nmt" | ||
|
||
"github.com/rollkit/celestia-openrpc/types/appconsts" | ||
"github.com/rollkit/celestia-openrpc/types/share" | ||
) | ||
|
||
const ( | ||
// NMTIgnoreMaxNamespace is currently used value for IgnoreMaxNamespace option in NMT. | ||
// IgnoreMaxNamespace defines whether the largest possible Namespace MAX_NID should be 'ignored'. | ||
// If set to true, this allows for shorter proofs in particular use-cases. | ||
NMTIgnoreMaxNamespace = true | ||
) | ||
|
||
var ( | ||
ErrBlobNotFound = errors.New("blob: not found") | ||
ErrInvalidProof = errors.New("blob: invalid proof") | ||
) | ||
|
||
// Commitment is a Merkle Root of the subtree built from shares of the Blob. | ||
// It is computed by splitting the blob into shares and building the Merkle subtree to be included | ||
// after Submit. | ||
type Commitment []byte | ||
|
||
func (com Commitment) String() string { | ||
return string(com) | ||
} | ||
|
||
// Equal ensures that commitments are the same | ||
func (com Commitment) Equal(c Commitment) bool { | ||
return bytes.Equal(com, c) | ||
} | ||
|
||
// Proof is a collection of nmt.Proofs that verifies the inclusion of the data. | ||
type Proof []*nmt.Proof | ||
|
||
func (p Proof) Len() int { return len(p) } | ||
|
||
type jsonProof struct { | ||
Start int `json:"start"` | ||
End int `json:"end"` | ||
Nodes [][]byte `json:"nodes"` | ||
} | ||
|
||
func (p *Proof) MarshalJSON() ([]byte, error) { | ||
proofs := make([]jsonProof, 0, p.Len()) | ||
for _, pp := range *p { | ||
proofs = append(proofs, jsonProof{ | ||
Start: pp.Start(), | ||
End: pp.End(), | ||
Nodes: pp.Nodes(), | ||
}) | ||
} | ||
|
||
return json.Marshal(proofs) | ||
} | ||
|
||
func (p *Proof) UnmarshalJSON(data []byte) error { | ||
var proofs []jsonProof | ||
err := json.Unmarshal(data, &proofs) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
nmtProofs := make([]*nmt.Proof, len(proofs)) | ||
for i, jProof := range proofs { | ||
nmtProof := nmt.NewInclusionProof(jProof.Start, jProof.End, jProof.Nodes, NMTIgnoreMaxNamespace) | ||
nmtProofs[i] = &nmtProof | ||
} | ||
|
||
*p = nmtProofs | ||
return nil | ||
} | ||
|
||
// Blob represents any application-specific binary data that anyone can submit to Celestia. | ||
type Blob struct { | ||
Namespace []byte `protobuf:"bytes,1,opt,name=namespace,proto3" json:"namespace,omitempty"` | ||
Data []byte `protobuf:"bytes,2,opt,name=data,proto3" json:"data,omitempty"` | ||
ShareVersion uint32 `protobuf:"varint,3,opt,name=share_version,json=shareVersion,proto3" json:"share_version,omitempty"` | ||
NamespaceVersion uint32 `protobuf:"varint,4,opt,name=namespace_version,json=namespaceVersion,proto3" json:"namespace_version,omitempty"` | ||
Commitment []byte `protobuf:"bytes,5,opt,name=commitment,proto3" json:"commitment,omitempty"` | ||
} | ||
|
||
// NewBlobV0 constructs a new blob from the provided Namespace and data. | ||
// The blob will be formatted as v0 shares. | ||
func NewBlobV0(namespace share.Namespace, data []byte) (*Blob, error) { | ||
return NewBlob(appconsts.ShareVersionZero, namespace, data) | ||
} | ||
|
||
// NewBlob constructs a new blob from the provided Namespace, data and share version. | ||
func NewBlob(shareVersion uint8, namespace share.Namespace, data []byte) (*Blob, error) { | ||
if len(data) == 0 || len(data) > appconsts.DefaultMaxBytes { | ||
return nil, fmt.Errorf("blob data must be > 0 && <= %d, but it was %d bytes", appconsts.DefaultMaxBytes, len(data)) | ||
} | ||
if err := namespace.ValidateForBlob(); err != nil { | ||
return nil, err | ||
} | ||
|
||
return &Blob{ | ||
Namespace: namespace, | ||
Data: data, | ||
ShareVersion: uint32(shareVersion), | ||
NamespaceVersion: 0, | ||
Commitment: []byte{}, | ||
}, nil | ||
} | ||
|
||
type jsonBlob struct { | ||
Namespace share.Namespace `json:"namespace"` | ||
Data []byte `json:"data"` | ||
ShareVersion uint32 `json:"share_version"` | ||
Commitment Commitment `json:"commitment"` | ||
} | ||
|
||
func (b *Blob) MarshalJSON() ([]byte, error) { | ||
blob := &jsonBlob{ | ||
Namespace: b.Namespace, | ||
Data: b.Data, | ||
ShareVersion: b.ShareVersion, | ||
Commitment: b.Commitment, | ||
} | ||
return json.Marshal(blob) | ||
} | ||
|
||
func (b *Blob) UnmarshalJSON(data []byte) error { | ||
var blob jsonBlob | ||
err := json.Unmarshal(data, &blob) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
b.NamespaceVersion = uint32(blob.Namespace.Version()) | ||
b.Data = blob.Data | ||
b.ShareVersion = blob.ShareVersion | ||
b.Commitment = blob.Commitment | ||
b.Namespace = blob.Namespace | ||
return nil | ||
} |
Oops, something went wrong.