forked from rollkit/rollkit
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3ae761f
commit 869ddff
Showing
5 changed files
with
367 additions
and
7 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
package avail | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
Check failure on line 7 in da/avail/avail.go GitHub Actions / lint / golangci-lint
|
||
"net/http" | ||
"strings" | ||
|
||
ds "github.com/ipfs/go-datastore" | ||
"github.com/rollkit/rollkit/da" | ||
"github.com/rollkit/rollkit/da/avail/datasubmit" | ||
"github.com/rollkit/rollkit/log" | ||
"github.com/rollkit/rollkit/types" | ||
) | ||
|
||
type Config struct { | ||
BaseURL string `json:"base_url"` | ||
Seed string `json:"seed"` | ||
ApiURL string `json:"api_url"` | ||
AppID int `json:"app_id"` | ||
confidence float64 `json:"confidence"` | ||
Check failure on line 23 in da/avail/avail.go GitHub Actions / lint / golangci-lint
|
||
} | ||
|
||
type DataAvailabilityLayerClient struct { | ||
namespace types.NamespaceID | ||
config Config | ||
logger log.Logger | ||
} | ||
|
||
type Confidence struct { | ||
Block uint32 `json:"block"` | ||
Confidence float64 `json:"confidence"` | ||
SerialisedConfidence *string `json:"serialised_confidence,omitempty"` | ||
} | ||
|
||
type AppData struct { | ||
Block uint32 `json:"block"` | ||
Extrinsics []string `json:"extrinsics"` | ||
} | ||
|
||
var _ da.DataAvailabilityLayerClient = &DataAvailabilityLayerClient{} | ||
var _ da.BlockRetriever = &DataAvailabilityLayerClient{} | ||
|
||
// Init initializes DataAvailabilityLayerClient instance. | ||
func (c *DataAvailabilityLayerClient) Init(namespaceID types.NamespaceID, config []byte, kvStore ds.Datastore, logger log.Logger) error { | ||
c.logger = logger | ||
|
||
if len(config) > 0 { | ||
return json.Unmarshal(config, &c.config) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// Start prepares DataAvailabilityLayerClient to work. | ||
func (c *DataAvailabilityLayerClient) Start() error { | ||
|
||
c.logger.Info("starting avail Data Availability Layer Client", "baseURL", c.config.ApiURL) | ||
|
||
return nil | ||
} | ||
|
||
// Stop stops DataAvailabilityLayerClient. | ||
func (c *DataAvailabilityLayerClient) Stop() error { | ||
|
||
c.logger.Info("stopping Avail Data Availability Layer Client") | ||
|
||
return nil | ||
} | ||
|
||
// SubmitBlock submits a block to DA layer. | ||
func (c *DataAvailabilityLayerClient) SubmitBlocks(ctx context.Context, blocks []*types.Block) da.ResultSubmitBlocks { | ||
|
||
for _, block := range blocks { | ||
data, err := block.MarshalBinary() | ||
if err != nil { | ||
return da.ResultSubmitBlocks{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
err = datasubmit.SubmitData(c.config.ApiURL, c.config.Seed, c.config.AppID, data) | ||
|
||
if err != nil { | ||
return da.ResultSubmitBlocks{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
} | ||
|
||
return da.ResultSubmitBlocks{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusSuccess, | ||
Message: "data submitted succesfully", | ||
DAHeight: 1, | ||
}, | ||
} | ||
|
||
} | ||
|
||
// CheckBlockAvailability queries DA layer to check data availability of block. | ||
func (c *DataAvailabilityLayerClient) CheckBlockAvailability(ctx context.Context, dataLayerHeight uint64) da.ResultCheckBlock { | ||
|
||
blockNumber := dataLayerHeight | ||
confidenceURL := fmt.Sprintf(c.config.BaseURL+"/confidence/%d", blockNumber) | ||
|
||
response, err := http.Get(confidenceURL) | ||
|
||
if err != nil { | ||
return da.ResultCheckBlock{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
|
||
responseData, err := ioutil.ReadAll(response.Body) | ||
if err != nil { | ||
return da.ResultCheckBlock{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
|
||
var confidenceObject Confidence | ||
err = json.Unmarshal(responseData, &confidenceObject) | ||
if err != nil { | ||
return da.ResultCheckBlock{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
|
||
return da.ResultCheckBlock{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusSuccess, | ||
DAHeight: uint64(confidenceObject.Block), | ||
}, | ||
DataAvailable: confidenceObject.Confidence > float64(c.config.confidence), | ||
} | ||
} | ||
|
||
//RetrieveBlocks gets the block from DA layer. | ||
|
||
func (c *DataAvailabilityLayerClient) RetrieveBlocks(ctx context.Context, dataLayerHeight uint64) da.ResultRetrieveBlocks { | ||
|
||
blocks := []*types.Block{} | ||
|
||
blockNumber := dataLayerHeight | ||
|
||
appDataURL := fmt.Sprintf(c.config.BaseURL+"/appdata/%d?decode=true", blockNumber) | ||
|
||
response, err := http.Get(appDataURL) | ||
if err != nil { | ||
return da.ResultRetrieveBlocks{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
|
||
responseData, err := ioutil.ReadAll(response.Body) | ||
if err != nil { | ||
return da.ResultRetrieveBlocks{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
|
||
var appDataObject AppData | ||
err = json.Unmarshal(responseData, &appDataObject) | ||
if err != nil { | ||
return da.ResultRetrieveBlocks{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusError, | ||
Message: err.Error(), | ||
}, | ||
} | ||
} | ||
|
||
txnsByteArray := []byte{} | ||
for _, extrinsic := range appDataObject.Extrinsics { | ||
txnsByteArray = append(txnsByteArray, []byte(extrinsic)...) | ||
} | ||
|
||
block := &types.Block{ | ||
SignedHeader: types.SignedHeader{ | ||
Header: types.Header{ | ||
BaseHeader: types.BaseHeader{ | ||
Height: blockNumber, | ||
}, | ||
AggregatorsHash: make([]byte, 32), | ||
}}, | ||
Data: types.Data{ | ||
Txs: types.Txs{txnsByteArray}, | ||
IntermediateStateRoots: types.IntermediateStateRoots{ | ||
RawRootsList: nil, | ||
}, | ||
}, | ||
} | ||
|
||
blocks = append(blocks, block) | ||
|
||
return da.ResultRetrieveBlocks{ | ||
BaseResult: da.BaseResult{ | ||
Code: da.StatusSuccess, | ||
DAHeight: uint64(appDataObject.Block), | ||
Message: "block data: " + strings.Join(appDataObject.Extrinsics, " "), | ||
}, | ||
Blocks: blocks, | ||
} | ||
} |
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,89 @@ | ||
package datasubmit | ||
|
||
import ( | ||
"errors" | ||
|
||
gsrpc "github.com/centrifuge/go-substrate-rpc-client/v4" | ||
"github.com/centrifuge/go-substrate-rpc-client/v4/signature" | ||
"github.com/centrifuge/go-substrate-rpc-client/v4/types" | ||
) | ||
|
||
// submit data submits the extrinsic through substrate api | ||
func SubmitData(apiURL string, seed string, appID int, data []byte) error { | ||
api, err := gsrpc.NewSubstrateAPI(apiURL) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
meta, err := api.RPC.State.GetMetadataLatest() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
//if app id is greater than 0 then it must be created before submitting data | ||
err = errors.New("AppID cant be 0") | ||
if appID == 0 { | ||
return err | ||
} | ||
|
||
c, err := types.NewCall(meta, "DataAvailability.submit_data", data) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
//Create the extrinsic | ||
ext := types.NewExtrinsic(c) | ||
|
||
genesisHash, err := api.RPC.Chain.GetBlockHash(0) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
rv, err := api.RPC.State.GetRuntimeVersionLatest() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
keyringPair, err := signature.KeyringPairFromSecret(seed, 42) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
key, err := types.CreateStorageKey(meta, "System", "Account", keyringPair.PublicKey) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
var accountInfo types.AccountInfo | ||
ok, err := api.RPC.State.GetStorageLatest(key, &accountInfo) | ||
if err != nil || !ok { | ||
return err | ||
} | ||
|
||
nonce := uint32(accountInfo.Nonce) | ||
o := types.SignatureOptions{ | ||
BlockHash: genesisHash, | ||
Era: types.ExtrinsicEra{IsMortalEra: false}, | ||
GenesisHash: genesisHash, | ||
Nonce: types.NewUCompactFromUInt(uint64(nonce)), | ||
SpecVersion: rv.SpecVersion, | ||
Tip: types.NewUCompactFromUInt(0), | ||
AppID: types.NewUCompactFromUInt(uint64(appID)), | ||
TransactionVersion: rv.TransactionVersion, | ||
} | ||
|
||
// Sign the transaction using Alice's default account | ||
err = ext.Sign(keyringPair, o) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Send the extrinsic | ||
_, err = api.RPC.Author.SubmitExtrinsic(ext) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
|
||
} |
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
Oops, something went wrong.