From 894d1045a8fb363846571d6639651abfccb0b687 Mon Sep 17 00:00:00 2001 From: prampey Date: Mon, 22 Apr 2024 17:03:40 -0500 Subject: [PATCH] feat(daash): add human-readable verison og BlobID --- availda/availda.go | 56 ++++++++++++++++------------------------- celestiada/celestia.go | 6 ++--- cmd/blob-server/main.go | 22 +++------------- daash.go | 52 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 55 deletions(-) diff --git a/availda/availda.go b/availda/availda.go index 3f767a8..697c5db 100644 --- a/availda/availda.go +++ b/availda/availda.go @@ -254,13 +254,13 @@ out: // Get returns Blob for each given ID, or an error. func (a *DAClient) Get(ctx context.Context, ids []da.ID) ([]da.Blob, error) { // TODO: We are dealing with single blobs for now. We will need to handle multiple blobs in the future. - blockHeight, extHash := SplitID(ids[0]) - data, err := a.GetData(uint64(blockHeight), extHash) + ext, err := a.GetExtrinsic(ids[0]) if err != nil { - return nil, fmt.Errorf("cannot get data", err) + return nil, fmt.Errorf("cannot get extrinsic", err) } - log.Println("📥 received data:%+v", zap.Any("data", data)) - return []da.Blob{data}, nil + blobData := ext.Method.Args[2:] + log.Println("📥 received data:%+v", zap.Any("data", blobData)) + return []da.Blob{blobData}, nil } // GetIDs returns IDs of all Blobs located in DA at given height. @@ -325,38 +325,13 @@ func makeID(blockHeight uint32, extIndex int) da.ID { } // SplitID returns the block height and leaf index from a unique ID -func SplitID(id da.ID) (uint32, string) { +func SplitID(id da.ID) (uint32, uint32) { heightLen := 4 heightBytes := id[:heightLen] - extHashBytes := id[heightLen:] + extIdxBytes := id[heightLen:] blockHeight := binary.LittleEndian.Uint32(heightBytes) - return blockHeight, string(extHashBytes) -} - -func (a *DAClient) GetData(blockNumber uint64, extHash string) ([]byte, error) { - blockHash, err := a.API.RPC.Chain.GetBlockHash(blockNumber) - if err != nil { - return nil, fmt.Errorf("cannot get block hash", err) - } - - block, err := a.API.RPC.Chain.GetBlock(blockHash) - if err != nil { - return nil, fmt.Errorf("cannot get block", err) - } - - var data []byte - for _, ext := range block.Block.Extrinsics { - extBytes, err := json.Marshal(ext) - if err != nil { - return nil, fmt.Errorf("cannot marshal extrinsic", err) - } - if string(extBytes) == extHash { - data = ext.Method.Args[2:] - break - } - } - - return data, nil + extIdx := binary.LittleEndian.Uint32(extIdxBytes) + return blockHeight, extIdx } type Config struct { @@ -388,3 +363,16 @@ func (c *Config) GetConfig(configFileName string) error { return nil } + +func (a *DAClient) GetExtrinsic(id da.ID) (types.Extrinsic, error) { + blockHeight, extIdx := SplitID(id) + blockHash, err := a.API.RPC.Chain.GetBlockHash(uint64(blockHeight)) + if err != nil { + log.Fatalf("cannot get block hash:%w", err) + } + block, err := a.API.RPC.Chain.GetBlock(blockHash) + if err != nil { + log.Fatalf("cannot get block:%w", err) + } + return block.Block.Extrinsics[extIdx], nil +} diff --git a/celestiada/celestia.go b/celestiada/celestia.go index 0e75835..9b3854c 100644 --- a/celestiada/celestia.go +++ b/celestiada/celestia.go @@ -64,7 +64,7 @@ func (c *DAClient) MaxBlobSize(ctx context.Context) (uint64, error) { func (c *DAClient) Get(ctx context.Context, ids []da.ID) ([]da.Blob, error) { var blobs []da.Blob for _, id := range ids { - height, commitment := splitID(id) + height, commitment := SplitID(id) blob, err := c.client.Blob.Get(ctx, height, c.Namespace, commitment) if err != nil { return nil, err @@ -171,7 +171,7 @@ func (c *DAClient) Validate(ctx context.Context, ids []da.ID, daProofs []da.Proo proofs = append(proofs, proof) } for i, id := range ids { - height, commitment := splitID(id) + height, commitment := SplitID(id) // TODO(tzdybal): for some reason, if proof doesn't match commitment, API returns (false, "blob: invalid proof") // but analysis of the code in celestia-node implies this should never happen - maybe it's caused by openrpc? // there is no way of gently handling errors here, but returned value is fine for us @@ -193,7 +193,7 @@ func makeID(height uint64, commitment da.Commitment) da.ID { return id } -func splitID(id da.ID) (uint64, da.Commitment) { +func SplitID(id da.ID) (uint64, da.Commitment) { if len(id) <= heightLen { return 0, nil } diff --git a/cmd/blob-server/main.go b/cmd/blob-server/main.go index 11e6700..0a6c83d 100644 --- a/cmd/blob-server/main.go +++ b/cmd/blob-server/main.go @@ -15,8 +15,6 @@ import ( "github.com/gin-gonic/gin" "github.com/rollkit/go-da" "github.com/stackrlabs/go-daash" - "github.com/stackrlabs/go-daash/availda" - "github.com/stackrlabs/go-daash/celestiada" ) // Constants @@ -151,21 +149,6 @@ func generateJobID() string { return randomHexString } -func getSuccessLink(daClient da.DA, ids []da.ID) string { - switch daClient := daClient.(type) { - case *celestiada.DAClient: - namespace := daClient.Namespace.String() - // remove 2 leading zero of namespace - namespace = namespace[2:] - return fmt.Sprintf("https://mocha-4.celenium.io/namespace/%s", namespace) - case *availda.DAClient: - _, extHash := availda.SplitID(ids[0]) - return fmt.Sprintf("https://goldberg.avail.tools/#/extrinsics/decode/%s", extHash) - default: - return "" - } -} - func run(ctx context.Context, b *BlobServer, job Job) { var jobStatus map[string]any ids, proofs, err := postToDA(ctx, job.Data, b.Daasher.Clients[job.Layer]) @@ -175,7 +158,10 @@ func run(ctx context.Context, b *BlobServer, job Job) { "error": err, } } else { - successLink := getSuccessLink(b.Daasher.Clients[job.Layer], ids) + successLink, err := daash.GetExplorerLink(b.Daasher.Clients[job.Layer], ids) + if err != nil { + log.Fatalf("cannot get explorer link: %v", err) + } jobStatus = gin.H{ "status": "Blob daashed and posted to " + string(job.Layer) + " 🏃", "ids": ids, diff --git a/daash.go b/daash.go index 3acf401..1c839d8 100644 --- a/daash.go +++ b/daash.go @@ -2,8 +2,10 @@ package daash import ( "context" + "encoding/json" "fmt" "log" + "strings" "time" "github.com/cenkalti/backoff" @@ -96,3 +98,53 @@ func (d *DABuilder) InitClients(ctx context.Context, layers []DALayer, availConf } return d, nil } + +func GetHumanReadableID(id da.ID, daLayer DALayer) any { + switch daLayer { + case Avail: + blockHeight, extIdx := availda.SplitID(id) + return struct { + BlockHeight uint32 `json:"blockHeight"` + ExtIdx uint32 `json:"extIdx"` + }{ + BlockHeight: blockHeight, + ExtIdx: extIdx, + } + case Celestia: + blockHeight, commitment := celestiada.SplitID(id) + return struct { + BlockHeight uint64 `json:"blockHeight"` + Commitment da.Commitment `json:"commitment"` + }{ + BlockHeight: blockHeight, + Commitment: commitment, + } + default: + return "" + } +} + +func GetExplorerLink(client da.DA, ids []da.ID) (string, error) { + switch daClient := client.(type) { + case *celestiada.DAClient: + namespace := daClient.Namespace.String() + // remove 2 leading zero of namespace + namespace = namespace[2:] + return fmt.Sprintf("https://mocha-4.celenium.io/namespace/%s", namespace), nil + case *availda.DAClient: + ext, err := daClient.GetExtrinsic(ids[0]) + if err != nil { + return "", err + } + extBytes, err := json.Marshal(ext) + if err != nil { + return "", err + } + // Strip string of any leading or following quotes + extString := strings.Trim(string(extBytes), "\"") + fmt.Println(extString) + return fmt.Sprintf("https://goldberg.avail.tools/#/extrinsics/decode/%s", extString), nil + default: + return "", nil + } +}