Skip to content

Commit

Permalink
Merge pull request #12 from gagliardetto/gsfa-index
Browse files Browse the repository at this point in the history
Gsfa index
  • Loading branch information
linuskendall authored Jun 27, 2023
2 parents f91feda + cf83745 commit a2e0774
Show file tree
Hide file tree
Showing 58 changed files with 10,477 additions and 12 deletions.
14 changes: 14 additions & 0 deletions car-dag-traverser.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,20 @@ func fileExists(path string) (bool, error) {
return true, nil
}

func dirExists(path string) (bool, error) {
info, err := os.Stat(path)
if os.IsNotExist(err) {
return false, nil
}
if err != nil {
return false, err
}
if !info.IsDir() {
return false, fmt.Errorf("path %s is not a directory", path)
}
return true, nil
}

func openCarReaderWithCidIndex(carPath string, indexFilePath string) (*SimpleIterator, error) {
// Check if the CAR file exists:
exists, err := fileExists(carPath)
Expand Down
117 changes: 117 additions & 0 deletions cmd-rpc-server-car-getSignaturesForAddress.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package main

import (
"context"
"encoding/json"

"github.com/gagliardetto/solana-go"
"github.com/rpcpool/yellowstone-faithful/gsfa/offsetstore"
"github.com/sourcegraph/jsonrpc2"
"k8s.io/klog/v2"
)

type GetSignaturesForAddressParams struct {
Address solana.PublicKey `json:"address"`
Limit int `json:"limit"`
// TODO: add more params
}

func parseGetSignaturesForAddressParams(raw *json.RawMessage) (*GetSignaturesForAddressParams, error) {
var params []any
if err := json.Unmarshal(*raw, &params); err != nil {
klog.Errorf("failed to unmarshal params: %v", err)
return nil, err
}
sigRaw, ok := params[0].(string)
if !ok {
klog.Errorf("first argument must be a string")
return nil, nil
}

out := &GetSignaturesForAddressParams{}
pk, err := solana.PublicKeyFromBase58(sigRaw)
if err != nil {
klog.Errorf("failed to parse pubkey from base58: %v", err)
return nil, err
}
out.Address = pk

if len(params) > 1 {
// the second param should be a map[string]interface{}
// with the optional params
if m, ok := params[1].(map[string]interface{}); ok {
if limit, ok := m["limit"]; ok {
if limit, ok := limit.(float64); ok {
out.Limit = int(limit)
}
}
}
}
if out.Limit <= 0 || out.Limit > 1000 {
// default limit
out.Limit = 1000
}
return out, nil
}

func (ser *rpcServer) getSignaturesForAddress(ctx context.Context, conn *requestContext, req *jsonrpc2.Request) {
if ser.gsfaReader == nil {
klog.Errorf("gsfaReader is nil")
conn.ReplyWithError(
ctx,
req.ID,
&jsonrpc2.Error{
Code: jsonrpc2.CodeInternalError,
Message: "getSignaturesForAddress method is not enabled",
})
return
}

params, err := parseGetSignaturesForAddressParams(req.Params)
if err != nil {
klog.Errorf("failed to parse params: %v", err)
conn.ReplyWithError(
ctx,
req.ID,
&jsonrpc2.Error{
Code: jsonrpc2.CodeInvalidParams,
Message: "Invalid params",
})
return
}
pk := params.Address
limit := params.Limit

sigs, err := ser.gsfaReader.Get(context.Background(), pk, limit)
if err != nil {
if offsetstore.IsNotFound(err) {
klog.Infof("No signatures found for address: %s", pk)
conn.ReplyWithError(
ctx,
req.ID,
&jsonrpc2.Error{
Code: jsonrpc2.CodeInternalError,
Message: "Not found",
})
return
}
}

// The response is an array of objects: [{signature: string}]
response := make([]map[string]string, len(sigs))
for i, sig := range sigs {
response[i] = map[string]string{
"signature": sig.String(),
}
}

// reply with the data
err = conn.ReplyNoMod(
ctx,
req.ID,
response,
)
if err != nil {
klog.Errorf("failed to reply: %v", err)
}
}
39 changes: 38 additions & 1 deletion cmd-rpc-server-car.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/patrickmn/go-cache"
"github.com/rpcpool/yellowstone-faithful/compactindex"
"github.com/rpcpool/yellowstone-faithful/compactindex36"
"github.com/rpcpool/yellowstone-faithful/gsfa"
"github.com/rpcpool/yellowstone-faithful/ipld/ipldbindcode"
"github.com/rpcpool/yellowstone-faithful/iplddecoders"
solanatxmetaparsers "github.com/rpcpool/yellowstone-faithful/solana-tx-meta-parsers"
Expand All @@ -38,7 +39,7 @@ func newCmd_rpcServerCar() *cli.Command {
return &cli.Command{
Name: "rpc-server-car",
Description: "Start a Solana JSON RPC that exposes getTransaction and getBlock",
ArgsUsage: "<car-filepath-or-url> <cid-to-offset-index-filepath-or-url> <slot-to-cid-index-filepath-or-url> <sig-to-cid-index-filepath-or-url>",
ArgsUsage: "<car-filepath-or-url> <cid-to-offset-index-filepath-or-url> <slot-to-cid-index-filepath-or-url> <sig-to-cid-index-filepath-or-url> <gsfa-index-dir>",
Before: func(c *cli.Context) error {
return nil
},
Expand Down Expand Up @@ -106,6 +107,16 @@ func newCmd_rpcServerCar() *cli.Command {
return fmt.Errorf("failed to open CAR file: %w", err)
}

var gsfaIndex *gsfa.GsfaReader
gsfaIndexDir := c.Args().Get(4)
if gsfaIndexDir != "" {
gsfaIndex, err = gsfa.NewGsfaReader(gsfaIndexDir)
if err != nil {
return fmt.Errorf("failed to open gsfa index: %w", err)
}
defer gsfaIndex.Close()
}

return createAndStartRPCServer_withCar(
c.Context,
listenOn,
Expand All @@ -114,6 +125,7 @@ func newCmd_rpcServerCar() *cli.Command {
cidToOffsetIndex,
slotToCidIndex,
sigToCidIndex,
gsfaIndex,
)
},
}
Expand Down Expand Up @@ -293,13 +305,15 @@ func createAndStartRPCServer_withCar(
cidToOffsetIndex *compactindex.DB,
slotToCidIndex *compactindex36.DB,
sigToCidIndex *compactindex36.DB,
gsfaReader *gsfa.GsfaReader,
) error {
handler := &rpcServer{
localCarReader: carReader,
remoteCarReader: remoteCarReader,
cidToOffsetIndex: cidToOffsetIndex,
slotToCidIndex: slotToCidIndex,
sigToCidIndex: sigToCidIndex,
gsfaReader: gsfaReader,
}

h := newRPCHandler_fast(handler)
Expand All @@ -315,11 +329,13 @@ func createAndStartRPCServer_lassie(
lassieWr *lassieWrapper,
slotToCidIndex *compactindex36.DB,
sigToCidIndex *compactindex36.DB,
gsfaReader *gsfa.GsfaReader,
) error {
handler := &rpcServer{
lassieFetcher: lassieWr,
slotToCidIndex: slotToCidIndex,
sigToCidIndex: sigToCidIndex,
gsfaReader: gsfaReader,
}

h := newRPCHandler_fast(handler)
Expand All @@ -336,6 +352,7 @@ type rpcServer struct {
cidToOffsetIndex *compactindex.DB
slotToCidIndex *compactindex36.DB
sigToCidIndex *compactindex36.DB
gsfaReader *gsfa.GsfaReader
}

type requestContext struct {
Expand Down Expand Up @@ -430,6 +447,24 @@ func (c *requestContext) Reply(
return err
}

func (c *requestContext) ReplyNoMod(
ctx context.Context,
id jsonrpc2.ID,
result interface{},
) error {
resRaw, err := jsoniter.ConfigCompatibleWithStandardLibrary.Marshal(result)
if err != nil {
return err
}
raw := json.RawMessage(resRaw)
resp := &jsonrpc2.Response{
ID: id,
Result: &raw,
}
replyJSON(c.ctx, http.StatusOK, resp)
return err
}

func (s *rpcServer) GetNodeByCid(ctx context.Context, wantedCid cid.Cid) ([]byte, error) {
if s.lassieFetcher != nil {
// Fetch the node from lassie.
Expand Down Expand Up @@ -684,6 +719,8 @@ func (ser *rpcServer) Handle(ctx context.Context, conn *requestContext, req *jso
ser.getBlock(ctx, conn, req)
case "getTransaction":
ser.getTransaction(ctx, conn, req)
case "getSignaturesForAddress":
ser.getSignaturesForAddress(ctx, conn, req)
default:
conn.ReplyWithError(
ctx,
Expand Down
14 changes: 13 additions & 1 deletion cmd-rpc-server-filecoin.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"

"github.com/rpcpool/yellowstone-faithful/compactindex36"
"github.com/rpcpool/yellowstone-faithful/gsfa"
"github.com/urfave/cli/v2"
)

Expand All @@ -12,7 +13,7 @@ func newCmd_rpcServerFilecoin() *cli.Command {
return &cli.Command{
Name: "rpc-server-filecoin",
Description: "Start a Solana JSON RPC that exposes getTransaction and getBlock",
ArgsUsage: "<slot-to-cid-index-filepath-or-url> <sig-to-cid-index-filepath-or-url>",
ArgsUsage: "<slot-to-cid-index-filepath-or-url> <sig-to-cid-index-filepath-or-url> <gsfa-index-dir>",
Before: func(c *cli.Context) error {
return nil
},
Expand Down Expand Up @@ -61,12 +62,23 @@ func newCmd_rpcServerFilecoin() *cli.Command {
return fmt.Errorf("newLassieWrapper: %w", err)
}

var gsfaIndex *gsfa.GsfaReader
gsfaIndexDir := c.Args().Get(4)
if gsfaIndexDir != "" {
gsfaIndex, err = gsfa.NewGsfaReader(gsfaIndexDir)
if err != nil {
return fmt.Errorf("failed to open gsfa index: %w", err)
}
defer gsfaIndex.Close()
}

return createAndStartRPCServer_lassie(
c.Context,
listenOn,
ls,
slotToCidIndex,
sigToCidIndex,
gsfaIndex,
)
},
}
Expand Down
Loading

0 comments on commit a2e0774

Please sign in to comment.