Skip to content

Commit

Permalink
feat(availda): add DAVerifier and avail bridge contract bindings (#9)
Browse files Browse the repository at this point in the history
* feat(availda): add DAVerifier and avail bridge contract bindings

* chore: forge init

* forge install: forge-std

v1.8.2

* feat(availda): add customer verifier contracts

* feat(availda): deploy and test with sepolia contract

* refactor: clean up typos, methods, files

* refactor: separate client and verifier

- add constant mapping

* add better error response

* chore: fix typo and smol refactor
  • Loading branch information
0xRampey committed May 27, 2024
1 parent d62ad82 commit 3343d98
Show file tree
Hide file tree
Showing 19 changed files with 5,638 additions and 104 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "celestiada/verify/contracts/lib/blobstream-contracts"]
path = celestiada/verify/contracts/lib/blobstream-contracts
url = https://github.com/celestiaorg/blobstream-contracts
[submodule "availda/verify/contracts/lib/forge-std"]
path = availda/verify/contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
79 changes: 52 additions & 27 deletions availda/availda.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,32 +27,26 @@ type AccountNextIndexRPCResponse struct {
Result uint `json:"result"`
}
type DataProofRPCResponse struct {
ID int64 `json:"id"`
Jsonrpc string `json:"jsonrpc"`
Result struct {
DataProof struct {
DataRoot string `json:"dataRoot"`
BlobRoot string `json:"blobRoot"`
BridgeRoot string `json:"bridgeRoot"`
Proof []string `json:"proof"`
NumberOfLeaves int `json:"numberOfLeaves"`
LeafIndex int `json:"leafIndex"`
Leaf string `json:"leaf"`
} `json:"dataProof"`
DataProof `json:"dataProof"`
} `json:"result"`
ID int `json:"id"`
}
type DataProof struct {
Root string `json:"dataRoot"`
BlobRoot string `json:"blobRoot"`
BridgeRoot string `json:"bridgeRoot"`
Proof []string `json:"proof"`
NumberOfLeaves uint32 `json:"numberOfLeaves"`
LeafIndex uint32 `json:"leafIndex"`
Leaf string `json:"leaf"`
LeafIndex int64 `json:"leafIndex"`
NumberOfLeaves int64 `json:"numberOfLeaves"`
Proof []string `json:"proof"`
Roots struct {
BlobRoot string `json:"blobRoot"`
BridgeRoot string `json:"bridgeRoot"`
DataRoot string `json:"dataRoot"`
} `json:"roots"`
}

type DAClient struct {
config Config
Config Config
API *gsrpc.SubstrateAPI
Meta *types.Metadata
AppID int
Expand All @@ -66,12 +60,12 @@ type DAClient struct {
// Returns a newly initalised Avail DA client
func New(configPath string) (*DAClient, error) {
a := DAClient{}
err := a.config.GetConfig(configPath)
err := a.Config.GetConfig(configPath)
if err != nil {
return nil, fmt.Errorf("cannot get config", err)
}

a.API, err = gsrpc.NewSubstrateAPI(a.config.WsRpcURL)
a.API, err = gsrpc.NewSubstrateAPI(a.Config.WsRpcURL)
if err != nil {
// log.Error("cannot get api:%w", zap.Error(err))
return nil, fmt.Errorf("cannot get api", err)
Expand All @@ -86,8 +80,8 @@ func New(configPath string) (*DAClient, error) {
a.AppID = 0

// if app id is greater than 0 then it must be created before submitting data
if a.config.AppID != 0 {
a.AppID = a.config.AppID
if a.Config.AppID != 0 {
a.AppID = a.Config.AppID
}

a.GenesisHash, err = a.API.RPC.Chain.GetBlockHash(0)
Expand All @@ -102,7 +96,7 @@ func New(configPath string) (*DAClient, error) {
return nil, fmt.Errorf("cannot get runtime version", err)
}

a.KeyringPair, err = signature.KeyringPairFromSecret(a.config.Seed, 42)
a.KeyringPair, err = signature.KeyringPairFromSecret(a.Config.Seed, 42)
if err != nil {
// log.Error("cannot get keyring pair:%w", zap.Error(err))
return nil, fmt.Errorf("cannot get keyring pair", err)
Expand Down Expand Up @@ -167,7 +161,7 @@ func (a *DAClient) Submit(ctx context.Context, daBlobs []da.Blob, gasPrice float
}

defer sub.Unsubscribe()
timeout := time.After(time.Duration(a.config.Timeout) * time.Second)
timeout := time.After(time.Duration(a.Config.Timeout) * time.Second)
var blockHash types.Hash
out:
for {
Expand Down Expand Up @@ -223,7 +217,7 @@ out:
eBytes = []byte(strings.Trim(string(eBytes), "\""))
if string(extBytes) == string(eBytes) {
extIndex = idx
resp, err := http.Post(a.config.HttpApiURL, "application/json",
resp, err := http.Post(a.Config.HttpApiURL, "application/json",
strings.NewReader(fmt.Sprintf("{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"kate_queryDataProofV2\",\"params\":[%d, \"%#x\"]}", idx+1, blockHash))) //nolint: noctx
if err != nil {
break
Expand All @@ -249,7 +243,7 @@ out:
}
dataProof := dataProofResp.Result.DataProof
// NOTE: Substrate's BlockNumber type is an alias for u32 type, which is uint32
blobID := makeID(uint32(block.Block.Header.Number), extIndex)
blobID := MakeID(uint32(block.Block.Header.Number), extIndex)
blobIDs := make([]da.ID, 1)
blobIDs[0] = blobID

Expand Down Expand Up @@ -286,6 +280,36 @@ func (a *DAClient) Commit(ctx context.Context, daBlobs []da.Blob) ([]da.Commitme
return nil, nil
}

// GetProofs returns the proofs for the given IDs
func (a *DAClient) GetProof(ctx context.Context, blockHeight uint32, extIdx int) (DataProofRPCResponse, error) {
var dataProofResp DataProofRPCResponse
blockHash, err := a.API.RPC.Chain.GetBlockHash(uint64(blockHeight))
if err != nil {
return dataProofResp, fmt.Errorf("cannot get block hash:%w", err)
}
resp, err := http.Post(a.Config.HttpApiURL, "application/json",
strings.NewReader(fmt.Sprintf("{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"kate_queryDataProof\",\"params\":[%d, \"%#x\"]}", extIdx, blockHash)))

if err != nil {
return dataProofResp, fmt.Errorf("cannot get data proof:%w", err)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return dataProofResp, fmt.Errorf("cannot read data:%w", err)
}
err = resp.Body.Close()
if err != nil {
return dataProofResp, fmt.Errorf("cannot close body:%w", err)
}
fmt.Println("raw proof data", string(data))
err = json.Unmarshal(data, &dataProofResp)
if err != nil {
return dataProofResp, fmt.Errorf("cannot unmarshal data:%w", err)
}
fmt.Println("dataProofResp", dataProofResp)
return dataProofResp, nil
}

// Validate validates Commitments against the corresponding Proofs. This should be possible without retrieving the Blobs.
func (c *DAClient) Validate(ctx context.Context, ids []da.ID, daProofs []da.Proof) ([]bool, error) {
// TODO: Need to implement this
Expand All @@ -305,7 +329,7 @@ func (b BatchDAData) IsEmpty() bool {

func (a *DAClient) GetAccountNextIndex() (types.UCompact, error) {
// TODO: Add context to the request
resp, err := http.Post(a.config.HttpApiURL, "application/json", strings.NewReader(fmt.Sprintf("{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"system_accountNextIndex\",\"params\":[\"%v\"]}", a.KeyringPair.Address))) //nolint: noctx
resp, err := http.Post(a.Config.HttpApiURL, "application/json", strings.NewReader(fmt.Sprintf("{\"id\":1,\"jsonrpc\":\"2.0\",\"method\":\"system_accountNextIndex\",\"params\":[\"%v\"]}", a.KeyringPair.Address))) //nolint: noctx
if err != nil {
return types.NewUCompactFromUInt(0), fmt.Errorf("cannot post account next index request", err)
}
Expand All @@ -325,7 +349,7 @@ func (a *DAClient) GetAccountNextIndex() (types.UCompact, error) {
}

// makeID creates a unique ID to reference a blob on Avail
func makeID(blockHeight uint32, extIndex int) da.ID {
func MakeID(blockHeight uint32, extIndex int) da.ID {
// Serialise height and leaf index to binary
heightLen := 4
heightBytes := make([]byte, heightLen)
Expand Down Expand Up @@ -353,6 +377,7 @@ type Config struct {
DestinationDomain int `json:"destination_domain"`
DestinationAddress string `json:"destination_address"`
Timeout int `json:"timeout"`
Network string `json:"network"`
}

func (c *Config) GetConfig(configFileName string) error {
Expand Down
3,170 changes: 3,170 additions & 0 deletions availda/verify/bindings/AvailBridge/AvailBridge.go

Large diffs are not rendered by default.

Loading

0 comments on commit 3343d98

Please sign in to comment.