Remove Kafka, Clickhouse-related tools

To be readded when we find a maintainer.

#frühjahrsputz
This commit is contained in:
Richard Patel 2023-04-10 11:13:17 +02:00 committed by ripatel-jump
parent 8f27f10358
commit 382e723242
37 changed files with 3 additions and 3605 deletions

View File

@ -1,261 +0,0 @@
package main
import (
"context"
"flag"
"fmt"
"net/http"
_ "net/http/pprof"
"strings"
"sync"
"time"
"github.com/gagliardetto/solana-go/rpc/ws"
"github.com/golang/protobuf/proto"
"github.com/twmb/franz-go/pkg/kgo"
"go.firedancer.io/radiance/pkg/envfile"
"go.firedancer.io/radiance/pkg/kafka"
"go.firedancer.io/radiance/pkg/leaderschedule"
envv1 "go.firedancer.io/radiance/proto/env/v1"
networkv1 "go.firedancer.io/radiance/proto/network/v1"
"k8s.io/klog/v2"
)
var (
flagEnv = flag.String("env", ".env.prototxt", "Env file (.prototxt)")
flagOnly = flag.String("only", "", "Only watch specified nodes (comma-separated)")
flagType = flag.String("type", "", "Only print specific types to log")
flagKafka = flag.Bool("kafka", false, "Enable Kafka publishing")
flagKafkaTopic = flag.String("kafkaTopic", "slot_status", "Kafka topic suffix to publish to")
flagDebugAddr = flag.String("debugAddr", "localhost:6060", "pprof/metrics listen address")
)
func init() {
klog.InitFlags(nil)
flag.Parse()
}
/*
I0612 20:37:10.076826 916547 slot.go:111] val1.ffm1: slot=137326466 type=firstShredReceived delta=7ms parent=0
I0612 20:37:10.428919 916547 slot.go:111] val1.ffm1: slot=137326466 type=completed delta=7ms parent=0
I0612 20:37:10.687256 916547 slot.go:111] val1.ffm1: slot=137326466 type=createdBank delta=4ms parent=137326465
I0612 20:37:10.691104 916547 slot.go:136] val1.ffm1: slot=137326466 root=137326431 parent=137326465
I0612 20:37:11.232413 916547 slot.go:111] val1.ffm1: slot=137326466 type=frozen delta=8ms parent=0
I0612 20:37:12.480333 916547 slot.go:111] val1.ffm1: slot=137326466 type=optimisticConfirmation delta=8ms parent=0
I0612 20:37:43.279139 916547 slot.go:111] val1.ffm1: slot=137326466 type=root delta=9ms parent=0
I0612 20:37:43.805364 916547 slot.go:111] val1.ffm1: slot=137326466 type=root delta=8ms parent=0
*/
func main() {
env, err := envfile.Load(*flagEnv)
if err != nil {
klog.Fatalf("Failed to load env file: %v", err)
}
nodes := env.GetNodes()
if len(nodes) == 0 {
klog.Fatalf("No nodes found in env file")
}
go func() {
klog.Error(http.ListenAndServe(*flagDebugAddr, nil))
}()
nodes = envfile.FilterNodes(nodes, envfile.ParseOnlyFlag(*flagOnly))
if len(nodes) == 0 {
klog.Exitf("No nodes in environment or all nodes filtered")
}
klog.Infof("Watching %d nodes", len(nodes))
ctx := context.Background()
highest := &sync.Map{}
sched := &leaderschedule.Tracker{}
go sched.Run(ctx, env.Nodes)
var kcl *kgo.Client
var topic string
if *flagKafka {
if *flagKafkaTopic == "" {
klog.Exitf("Kafka enabled but no topic specified")
}
topic = strings.Join([]string{env.Kafka.TopicPrefix, *flagKafkaTopic}, ".")
klog.Infof("Publishing to topic %s", topic)
kcl, err = kafka.NewClientFromEnv(env.Kafka)
if err != nil {
klog.Exitf("Failed to create kafka client: %v", err)
}
}
for _, node := range nodes {
node := node
go func() {
for {
if err := watchSlotUpdates(ctx, node, highest, sched, kcl, topic); err != nil {
klog.Errorf("watchSlotUpdates on node %s, reconnecting: %v", node.Name, err)
}
time.Sleep(time.Second * 5)
}
}()
if *flagType == "" {
go func() {
for {
if err := watchSlots(ctx, node); err != nil {
klog.Errorf("watchSlots on node %s, reconnecting: %v", node.Name, err)
}
time.Sleep(time.Second * 5)
}
}()
}
}
select {}
}
func watchSlotUpdates(ctx context.Context, node *envv1.RPCNode, highest *sync.Map, sched *leaderschedule.Tracker, kcl *kgo.Client, topic string) error {
timeout, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
c, err := ws.Connect(timeout, node.Ws)
if err != nil {
return fmt.Errorf("connect: %w", err)
}
sub, err := c.SlotsUpdatesSubscribe()
if err != nil {
return fmt.Errorf("subscribe: %w", err)
}
for {
m, err := sub.Recv()
if err != nil {
return fmt.Errorf("recv: %w", err)
}
ts := m.Timestamp.Time()
delay := time.Since(ts)
sched.Update(m.Slot)
var first time.Time
if m.Type == ws.SlotsUpdatesFirstShredReceived {
value, _ := highest.LoadOrStore(m.Slot, ts)
first = value.(time.Time)
} else {
value, ok := highest.Load(m.Slot)
if ok {
first = value.(time.Time)
}
}
if m.Type == ws.SlotsUpdatesRoot {
highest.Delete(m.Slot)
}
var prop int64
if !first.IsZero() {
prop = ts.Sub(first).Milliseconds()
} else {
prop = -1
}
if *flagType != "" && string(m.Type) != *flagType {
continue
}
leader := sched.Get(m.Slot)
if kcl != nil {
var stats *networkv1.TxStats
if m.Type == ws.SlotsUpdatesFrozen {
stats = &networkv1.TxStats{
NumTransactionEntries: m.Stats.NumTransactionEntries,
NumSuccessfulTransactions: m.Stats.NumSuccessfulTransactions,
NumFailedTransactions: m.Stats.NumFailedTransactions,
MaxTransactionsPerEntry: m.Stats.MaxTransactionsPerEntry,
}
}
st := &networkv1.SlotStatus{
Slot: m.Slot,
Timestamp: uint64(ts.UnixMilli()),
Delay: uint64(delay.Milliseconds()),
Type: convertUpdateType(m.Type),
Parent: m.Parent,
Stats: stats,
Err: "", // TODO
Leader: leader.String(),
Source: node.Name,
}
// Fixed-length proto encoding
buf := proto.NewBuffer([]byte{})
if err := buf.EncodeMessage(st); err != nil {
panic(err)
}
r := &kgo.Record{Topic: topic, Value: buf.Bytes()}
kcl.Produce(ctx, r, func(_ *kgo.Record, err error) {
if err != nil {
klog.Warningf("failed to publish message to %s: %v", topic, err)
}
})
}
klog.V(1).Infof("%s: slot=%d type=%s delay=%dms prop=%dms parent=%d stats=%v leader=%s",
node.Name, m.Slot, m.Type, delay.Milliseconds(), prop, m.Parent, m.Stats, leader)
}
}
func convertUpdateType(t ws.SlotsUpdatesType) networkv1.SlotStatus_UpdateType {
switch t {
case ws.SlotsUpdatesFirstShredReceived:
return networkv1.SlotStatus_UPDATE_TYPE_FIRST_SHRED_RECEIVED
case ws.SlotsUpdatesCompleted:
return networkv1.SlotStatus_UPDATE_TYPE_COMPLETED
case ws.SlotsUpdatesCreatedBank:
return networkv1.SlotStatus_UPDATE_TYPE_CREATED_BANK
case ws.SlotsUpdatesFrozen:
return networkv1.SlotStatus_UPDATE_TYPE_FROZEN
case ws.SlotsUpdatesDead:
return networkv1.SlotStatus_UPDATE_TYPE_DEAD
case ws.SlotsUpdatesOptimisticConfirmation:
return networkv1.SlotStatus_UPDATE_TYPE_OPTIMISTIC_CONFIRMATION
case ws.SlotsUpdatesRoot:
return networkv1.SlotStatus_UPDATE_TYPE_ROOT
default:
panic("unknown slot update type " + t)
}
}
func watchSlots(ctx context.Context, node *envv1.RPCNode) error {
timeout, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
c, err := ws.Connect(timeout, node.Ws)
if err != nil {
return fmt.Errorf("connect: %w", err)
}
sub, err := c.SlotSubscribe()
if err != nil {
return fmt.Errorf("subscribe: %w", err)
}
for {
m, err := sub.Recv()
if err != nil {
return fmt.Errorf("recv: %w", err)
}
klog.V(1).Infof("%s: slot=%d root=%d parent=%d",
node.Name, m.Slot, m.Root, m.Parent)
}
}

View File

@ -1,143 +0,0 @@
package main
import (
"context"
"encoding/json"
"errors"
"flag"
"fmt"
"os"
"sync"
"time"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
"github.com/gagliardetto/solana-go/rpc/jsonrpc"
"k8s.io/klog/v2"
)
const localRPC = "http://localhost:8899"
var (
flagAddr = flag.String("addr", localRPC, "RPC address")
flagCount = flag.Bool("count", true, "Print the number of transactions")
flagAfter = flag.Uint64("after", 0, "Only print transactions after this slot")
voteAcc = flag.String("voteAcc", "Certusm1sa411sMpV9FPqU5dXAYhmmhygvxJ23S6hJ24", "Vote account address")
workers = flag.Uint("workers", 10, "Worker threads")
)
type logLine struct {
TS time.Time
Slot uint64
NumTx int
}
func main() {
flag.Parse()
r := rpc.New(*flagAddr)
our, err := solana.PublicKeyFromBase58(*voteAcc)
if err != nil {
klog.Fatalf("Failed to parse vote account: %v", err)
}
klog.Infof("Our vote account: %v", our)
epr, err := r.GetEpochInfo(context.Background(), rpc.CommitmentConfirmed)
if err != nil {
klog.Exitf("GetEpochSchedule: %v", err)
}
if epr == nil {
klog.Exitf("GetEpochInfo: empty response")
}
epoch := *epr
offset := epoch.AbsoluteSlot - epoch.SlotIndex
klog.Infof("Epoch: %v, SlotIndex: %v, AbsoluteSlot: %v, Offset: %v", epoch.Epoch, epoch.SlotIndex, epoch.AbsoluteSlot, offset)
resp, err := r.GetLeaderScheduleWithOpts(context.Background(), &rpc.GetLeaderScheduleOpts{
Epoch: &epoch.AbsoluteSlot,
Identity: &our,
})
if err != nil {
klog.Exitf("GetLeaderSchedule: %v", err)
}
if resp == nil {
klog.Exitf("GetLeaderSchedule: empty response")
}
current, err := r.GetSlot(context.Background(), rpc.CommitmentConfirmed)
if err != nil {
klog.Exitf("GetSlot: %v", err)
}
klog.Infof("Current slot: %d", current)
sched := resp
slots := sched[our]
klog.Infof("%d slots for %s", len(slots), our)
work := make(chan uint64)
wg := sync.WaitGroup{}
out := sync.Mutex{}
for i := 0; uint(i) < *workers; i++ {
wg.Add(1)
go func() {
for {
slot := <-work
if slot == 0 {
wg.Done()
return
}
if *flagCount {
block, err := r.GetBlock(context.Background(), slot)
if err != nil {
var rpcErr *jsonrpc.RPCError
if errors.As(err, &rpcErr) && (rpcErr.Code == -32007 /* SLOT_SKIPPED */ || rpcErr.Code == -32004 /* BLOCK_NOT_AVAILABLE */) {
out.Lock()
fmt.Fprintf(os.Stderr, "slot=%d skipped=true\n", slot)
out.Unlock()
continue
}
}
if block == nil {
out.Lock()
fmt.Fprintf(os.Stderr, "slot=%d empty=true\n", slot)
out.Unlock()
continue
}
bt := time.Unix(int64(*block.BlockTime), 0)
out.Lock()
json.NewEncoder(os.Stdout).Encode(logLine{TS: bt, Slot: slot, NumTx: len(block.Transactions)})
out.Unlock()
} else {
fmt.Printf("https://explorer.solana.com/block/%d\n", slot)
}
}
}()
}
for _, slot := range slots {
slot := slot + offset
if *flagAfter > 0 && slot < *flagAfter {
continue
}
if slot > current {
break
}
work <- slot
}
close(work)
wg.Wait()
}

View File

@ -1,170 +0,0 @@
package main
import (
"context"
"encoding/hex"
"encoding/json"
"flag"
"fmt"
"math/rand"
"os"
"syscall"
"time"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
"github.com/gagliardetto/solana-go/rpc/ws"
"github.com/gagliardetto/solana-go/text"
envv1 "go.firedancer.io/radiance/proto/env/v1"
"k8s.io/klog/v2"
)
var (
flagPingerLog = flag.String("pinger_log", "", "JSON log file for pinger")
)
const (
confirmPollInterval = time.Second * 5
confirmRetries = 10
)
type pingData struct {
Slot uint64 `json:"slot"`
Ts time.Time `json:"ts"`
}
type logEntry struct {
Slot uint64 `json:"slot"`
SendDelay time.Duration `json:"send_delay"`
Ts time.Time `json:"ts"`
Signature solana.Signature `json:"signature"`
Leader solana.PublicKey `json:"leader"`
Confirmed bool `json:"confirmed"`
ConfirmedSlot uint64 `json:"confirmed_slot,omitempty"`
SlotDelay *int `json:"slot_delay,omitempty"`
TimeDelay time.Duration `json:"time_delay,omitempty"`
Timeout time.Duration `json:"timeout,omitempty"`
}
func buildTransaction(slot uint64, now time.Time, blockhash solana.Hash, feePayer solana.PublicKey) *solana.Transaction {
payload := &pingData{Slot: slot, Ts: now}
b, err := json.Marshal(payload)
if err != nil {
panic(err)
}
ins := solana.NewInstruction(solana.MemoProgramID, solana.AccountMetaSlice{}, b)
tx, err := solana.NewTransaction(
[]solana.Instruction{ins}, blockhash, solana.TransactionPayer(feePayer))
if err != nil {
panic(err)
}
return tx
}
func sendPing(ctx context.Context, m *ws.SlotsUpdatesResult, b solana.Hash, signer solana.PrivateKey, g *rpc.GetClusterNodesResult, nodes []*envv1.RPCNode, c map[string]*rpc.Client) {
tx := buildTransaction(m.Slot, time.Now(), b, signer.PublicKey())
sigs, err := tx.Sign(func(key solana.PublicKey) *solana.PrivateKey {
if key != signer.PublicKey() {
panic("no private key for unknown signer " + key.String())
}
return &signer
})
if err != nil {
panic(err)
}
if klog.V(2).Enabled() {
tx.EncodeTree(text.NewTreeEncoder(os.Stdout, "Ping memo"))
}
txb, err := tx.MarshalBinary()
if err != nil {
panic(err)
}
klog.Infof("Sending tx %s", sigs[0].String())
klog.V(2).Infof("tx: %s", hex.EncodeToString(txb))
sendUDP(*g.TPU, txb, 20)
go waitForConfirmation(ctx, m, nodes, c, sigs, g)
}
func waitForConfirmation(ctx context.Context, m *ws.SlotsUpdatesResult, nodes []*envv1.RPCNode, c map[string]*rpc.Client, sigs []solana.Signature, g *rpc.GetClusterNodesResult) {
for i := 0; i < confirmRetries; i++ {
select {
case <-ctx.Done():
return
case <-time.After(confirmPollInterval):
// pick random node to query status
node := nodes[rand.Intn(len(nodes))]
st, err := c[node.Name].GetSignatureStatuses(ctx, false, sigs[0])
if err != nil {
klog.Errorf("Failed to fetch signature status: %v", err)
continue
}
for _, s := range st.Value {
if s == nil || s.ConfirmationStatus != rpc.ConfirmationStatusConfirmed {
continue
}
delay := int(s.Slot) - int(m.Slot)
klog.Infof("%s confirmed in slot %d (offset %d)", sigs[0], s.Slot, delay)
if *flagPingerLog != "" {
log(logEntry{
Slot: m.Slot,
SendDelay: time.Duration(0),
Ts: time.Now(),
Signature: sigs[0],
Leader: g.Pubkey,
Confirmed: true,
ConfirmedSlot: s.Slot,
SlotDelay: &delay,
TimeDelay: 0, // TODO - we need precise slot timings for this first
})
return
}
}
}
}
klog.Infof("%s failed to confirm after %v",
sigs[0].String(), confirmPollInterval*confirmRetries)
if *flagPingerLog != "" {
log(logEntry{
Slot: m.Slot,
SendDelay: time.Duration(0),
Ts: time.Now(),
Signature: sigs[0],
Leader: g.Pubkey,
Confirmed: false,
Timeout: confirmPollInterval * confirmRetries,
})
}
}
func log(entry logEntry) {
f, err := os.OpenFile(*flagPingerLog, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
klog.Errorf("failed to open %s: %v", *flagPingerLog, err)
return
}
defer f.Close()
if err := syscall.Flock(int(f.Fd()), syscall.LOCK_EX); err != nil {
panic(fmt.Sprintf("failed to lock %s: %v", *flagPingerLog, err))
}
if err := json.NewEncoder(f).Encode(entry); err != nil {
klog.Errorf("failed to write to %s: %v", *flagPingerLog, err)
}
if err := syscall.Flock(int(f.Fd()), syscall.LOCK_UN); err != nil {
panic(fmt.Sprintf("failed to unlock %s: %v", *flagPingerLog, err))
}
}

View File

@ -1,31 +0,0 @@
package main
import (
"fmt"
"net"
"k8s.io/klog/v2"
)
func sendUDP(addr string, txb []byte, count int) {
// Send UDP packet to TPU
conn, err := net.Dial("udp", addr)
if err != nil {
// if we fail to open a UDP socket, something has gone really wrong
klog.Exitf("failed to dial %s: %v", addr, err)
return
}
defer conn.Close()
tn := 0
for i := 0; i < count; i++ {
n, err := conn.Write(txb)
if err != nil {
klog.Errorf("failed to write to %s: %v", addr, err)
}
if n != len(txb) {
panic(fmt.Errorf("wrote %d bytes, expected %d", n, len(txb)))
}
tn += n
}
klog.V(2).Infof("sent %d bytes to %s", tn, addr)
}

View File

@ -1,17 +0,0 @@
package main
import (
"os"
"path"
"github.com/gagliardetto/solana-go"
)
func loadLocalSigner() (solana.PrivateKey, error) {
home, err := os.UserHomeDir()
if err != nil {
panic(err)
}
key := path.Join(home, ".config/solana/id.json")
return solana.PrivateKeyFromSolanaKeygenFile(key)
}

View File

@ -1,154 +0,0 @@
package main
import (
"context"
"flag"
"fmt"
"net/http"
_ "net/http/pprof"
"sync/atomic"
"time"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
"github.com/gagliardetto/solana-go/rpc/ws"
"go.firedancer.io/radiance/pkg/blockhash"
"go.firedancer.io/radiance/pkg/clusternodes"
"go.firedancer.io/radiance/pkg/envfile"
"go.firedancer.io/radiance/pkg/leaderschedule"
envv1 "go.firedancer.io/radiance/proto/env/v1"
"k8s.io/klog/v2"
)
var (
flagEnv = flag.String("env", ".env.prototxt", "Env file (.prototxt)")
flagOnly = flag.String("only", "", "Only watch specified nodes (comma-separated)")
flagPinger = flag.Bool("pinger", false, "Enable pinger")
flagDebugAddr = flag.String("debugAddr", "localhost:6060", "pprof/metrics listen address")
)
func init() {
klog.InitFlags(nil)
flag.Parse()
}
func main() {
env, err := envfile.Load(*flagEnv)
if err != nil {
klog.Fatalf("Failed to load env file: %v", err)
}
nodes := env.GetNodes()
if len(nodes) == 0 {
klog.Fatalf("No nodes found in env file")
}
go func() {
klog.Error(http.ListenAndServe(*flagDebugAddr, nil))
}()
nodes = envfile.FilterNodes(nodes, envfile.ParseOnlyFlag(*flagOnly))
if len(nodes) == 0 {
klog.Exitf("No nodes in environment or all nodes filtered")
}
klog.Infof("Watching %d nodes", len(nodes))
ctx := context.Background()
// Leader schedule helper
sched := &leaderschedule.Tracker{}
go sched.Run(ctx, env.Nodes)
// Gossip helper
gossip := clusternodes.New(nodes)
go gossip.Run(ctx, time.Minute)
// Blockhash helper
bh := blockhash.New(nodes)
go bh.Run(ctx, time.Second)
// Load signing key
signer, err := loadLocalSigner()
if err != nil {
klog.Exitf("Failed to load signing : %v", err)
}
// Cache RPC clients
c := make(map[string]*rpc.Client)
for _, node := range nodes {
c[node.Name] = rpc.New(node.Http)
}
var highest uint64
for _, node := range nodes {
node := node
go func() {
for {
if err := watchSlotUpdates(ctx, node, nodes, sched, gossip, bh, signer, c, &highest); err != nil {
klog.Errorf("watchSlotUpdates on node %s, reconnecting: %v", node.Name, err)
}
time.Sleep(time.Second * 5)
}
}()
}
select {}
}
func watchSlotUpdates(ctx context.Context, node *envv1.RPCNode, nodes []*envv1.RPCNode, sched *leaderschedule.Tracker, gossip *clusternodes.Tracker, bh *blockhash.Tracker, signer solana.PrivateKey, c map[string]*rpc.Client, highest *uint64) error {
timeout, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
cw, err := ws.Connect(timeout, node.Ws)
if err != nil {
return fmt.Errorf("connect: %w", err)
}
sub, err := cw.SlotsUpdatesSubscribe()
if err != nil {
return fmt.Errorf("subscribe: %w", err)
}
for {
m, err := sub.Recv()
if err != nil {
return fmt.Errorf("recv: %w", err)
}
sched.Update(m.Slot)
var lastBlockhash solana.Hash
if m.Type == ws.SlotsUpdatesFirstShredReceived {
klog.V(1).Infof("%s: first shred received for slot %d", node.Name, m.Slot)
if m.Slot > atomic.LoadUint64(highest) {
atomic.StoreUint64(highest, m.Slot)
klog.Infof("%s: highest slot is now %d", node.Name, m.Slot)
leader, ok := sched.TryGet(m.Slot)
if !ok {
klog.Infof("could not fetch leader for slot %d", m.Slot)
continue
}
g := gossip.GetByPubkey(leader)
if g == nil || g.TPU == nil {
klog.Infof("could not fetch gossip entry for leader %s", leader)
continue
}
klog.Infof("current leader: %s, tpu: %s", leader, *g.TPU)
b := bh.MostRecent()
if b != lastBlockhash {
klog.Infof("new blockhash: %s", b)
lastBlockhash = b
}
if *flagPinger {
sendPing(ctx, m, b, signer, g, nodes, c)
}
}
}
}
}

View File

@ -1,24 +0,0 @@
# solrays
An RPC proxy that exports call latency of a Solana RPC node.
## Metrics
- `solrays_forwarded_duration_seconds` - an histogram of the duration of the calls forwarded to the Solana RPC node, per call.
- `solrays_requests_total` - Count of total requests per call.
- `solrays_request_errors_total` - Count of total requests that failed, e.g. malformed request or proxy can't reach the Solana RPC node.
- `solrays_requests_status_total` - Count of response HTTP status codes, per status code.
## Run
```
:; _bin/solrays -h
```
Key flags are:
- `backend` - the Solana RPC endpoint to proxy and monitor. Defaults to `http://localhost:8899`).
- `listen` - address where the RPC metrics and Go profiler endpoints are exposed.
- `tlsHostname` - the optional hostname for this service. Implicitly enables HTTPS.
- `tlsProd` - if HTTPS is enabled, select whether the x509 artifacts are provisioned by the production or the testing Let's Encrypt
public ACME service. Defaults to `false`, meaning the testing service will be used.

View File

@ -1,150 +0,0 @@
package main
import (
"context"
"flag"
"net"
"net/http"
_ "net/http/pprof"
"os"
"os/signal"
"path"
"syscall"
"time"
"github.com/coreos/go-systemd/v22/activation"
"github.com/prometheus/client_golang/prometheus/promhttp"
metrics "github.com/slok/go-http-metrics/metrics/prometheus"
"github.com/slok/go-http-metrics/middleware"
"github.com/slok/go-http-metrics/middleware/std"
"golang.org/x/crypto/acme"
"golang.org/x/crypto/acme/autocert"
"k8s.io/klog/v2"
"go.firedancer.io/radiance/pkg/util"
)
var (
backendAddr = flag.String("backend", "http://127.0.0.1:8899", "Backend RPC URI to proxy to")
debugAddr = flag.String("listen", "[::1]:6060", "pprof and metrics server address")
tlsHostname = flag.String("tlsHostname", "", "When set, serve TLS using Let's Encrypt using the hostname in question")
tlsProd = flag.Bool("tlsProd", false, "Use the production Let's Encrypt environment")
cacheDir = flag.String("cacheDir", "solrays-data", "Cache directory")
)
func init() {
klog.CopyStandardLogTo("INFO")
klog.InitFlags(nil)
flag.Parse()
}
func getSDListeners() []net.Listener {
// We use systemd socket activation for (almost) zero downtime deployment -
// systemd will keep the socket open even while we restart the process
// (plus, it allows us to bind to port 80).
//
// Read more: https://vincent.bernat.ch/en/blog/2018-systemd-golang-socket-activation
listeners, err := activation.Listeners()
if err != nil {
klog.Fatalf("cannot retrieve listeners: %s", err)
}
if len(listeners) != 1 {
klog.Fatalf("unexpected number of sockets passed by systemd (%d != 1)", len(listeners))
}
return listeners
}
func shutdownHandler(server *http.Server) chan struct{} {
done := make(chan struct{})
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
go func() {
<-quit
klog.Info("server is shutting down")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
server.SetKeepAlivesEnabled(false)
if err := server.Shutdown(ctx); err != nil {
klog.Exitf("cannot gracefully shut down the server: %s", err)
}
close(done)
}()
return done
}
func main() {
listeners := getSDListeners()
// Metrics recording middleware
mdlw := middleware.New(middleware.Config{
Recorder: metrics.NewRecorder(metrics.Config{}),
})
mux := http.NewServeMux()
mux.Handle("/", newHandler())
mux.HandleFunc("/health", func(w http.ResponseWriter, req *http.Request) {
klog.V(1).Infof("[%s] %s %s %v", req.RemoteAddr, req.Method, req.URL, req.Header)
w.Write([]byte("ok"))
})
wrapped := std.Handler("default", mdlw, mux)
server := &http.Server{
Handler: wrapped,
ReadTimeout: readTimeout,
WriteTimeout: requestTimeout,
}
// Setup TLS if an hostname has been specified.
if *tlsHostname != "" {
// Proceed only if a valid hostname has been specified.
if util.IsValidHostname(*tlsHostname) {
klog.Fatalf("tlsHostname [%s] is an invalid hostname, exiting", *tlsHostname)
}
klog.Infof("provisioning Let's Encrypt certificate for %s", *tlsHostname)
var acmeApi string
if *tlsProd {
klog.Infof("using production Let's Encrypt server")
acmeApi = autocert.DefaultACMEDirectory
} else {
klog.Infof("using staging Let's Encrypt server")
acmeApi = "https://acme-staging-v02.api.letsencrypt.org/directory"
}
certManager := autocert.Manager{
Prompt: autocert.AcceptTOS,
HostPolicy: autocert.HostWhitelist(*tlsHostname),
Cache: autocert.DirCache(path.Join(*cacheDir, "autocert")),
Client: &acme.Client{DirectoryURL: acmeApi},
}
server.TLSConfig = certManager.TLSConfig()
klog.Info("certificate provisioning configured")
}
// Graceful shutdown
done := shutdownHandler(server)
go func() {
http.Handle("/metrics", promhttp.Handler())
klog.Infof("debug server listening on %s", *debugAddr)
klog.Exit(http.ListenAndServe(*debugAddr, nil))
}()
if *tlsHostname != "" {
klog.Infof("main server listening with TLS on %s", listeners[0].Addr())
klog.Exit(server.ServeTLS(listeners[0], "", ""))
} else {
klog.Infof("main server listening on %s", listeners[0].Addr())
klog.Exit(server.Serve(listeners[0]))
}
<-done
}

View File

@ -1,162 +0,0 @@
package main
import (
"bytes"
"context"
"encoding/json"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promauto"
"io"
"io/ioutil"
"k8s.io/klog/v2"
"net/http"
"strconv"
"time"
)
type (
rpcRequest struct {
Version string `json:"jsonrpc"`
ID interface{} `json:"id"`
Method string `json:"method"`
Params []interface{} `json:"params"`
}
)
const (
invalidRequestMessage = "Not a valid JSONRPC POST request\n"
maxRequestSize = 1024 * 10 // 10 KiB
// Duration the entire request is allowed to take, including the backend request and response writing.
requestTimeout = 10 * time.Second
// Read timeout for request body and headers.
readTimeout = 2 * time.Second
)
var (
httpDuration = promauto.NewHistogramVec(prometheus.HistogramOpts{
Name: "solrays_forwarded_duration_seconds",
Help: "Duration of HTTP requests that made it to the backend",
}, []string{"method"})
requestsTotal = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "solrays_requests_total",
Help: "Number of requests per method",
}, []string{"method"})
requestErrors = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "solrays_request_errors_total",
Help: "Number of failed requests",
}, []string{"reason"})
backendRequest = promauto.NewCounterVec(prometheus.CounterOpts{
Name: "solrays_requests_status_total",
Help: "Number of backend responses by method and status code",
}, []string{"method", "code"})
)
type handler struct {
client *http.Client
}
func newHandler() handler {
return handler{&http.Client{}}
}
func (h handler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
start := time.Now()
klog.V(2).Infof("[%s] %s %s %v", req.RemoteAddr, req.Method, req.URL, req.Header)
if req.Method == "OPTIONS" {
h.sendCORS(w)
return
}
if req.Method != "POST" {
requestErrors.WithLabelValues("wrong_method").Inc()
http.Error(w, invalidRequestMessage, http.StatusMethodNotAllowed)
return
}
if req.Header.Get("Content-Type") != "application/json" {
requestErrors.WithLabelValues("wrong_content_type").Inc()
http.Error(w, invalidRequestMessage, http.StatusUnsupportedMediaType)
return
}
h.sendCORS(w)
ctx, cancel := context.WithTimeout(req.Context(), requestTimeout)
defer cancel()
// We need to read the entire request in order to decode and parse it.
b, err := ioutil.ReadAll(http.MaxBytesReader(w, req.Body, maxRequestSize))
if err != nil {
requestErrors.WithLabelValues("reading_body").Inc()
http.Error(w, "Error reading request body", http.StatusRequestTimeout)
klog.V(1).Infof("[%s] (+%v) failed to read request body: %v",
req.RemoteAddr, time.Since(start), err)
return
}
klog.V(3).Infof("[%s] raw request: %s", req.RemoteAddr, string(b))
var rpc rpcRequest
if err = json.Unmarshal(b, &rpc); err != nil {
requestErrors.WithLabelValues("decoding_request").Inc()
http.Error(w, "Error decoding request", http.StatusBadRequest)
klog.V(1).Infof("[%s] (+%v) failed to decode request: %v",
req.RemoteAddr, time.Since(start), err)
return
}
klog.V(2).Infof("[%s] (+%v) request: %v", req.RemoteAddr, time.Since(start), rpc)
if _, ok := methodWhitelistMap[rpc.Method]; !ok {
requestErrors.WithLabelValues("invalid_method").Inc()
http.Error(w, "Invalid RPC method", http.StatusBadRequest)
klog.V(1).Infof("[%s] (+%v) called a method not on the whitelist: %s",
req.RemoteAddr, time.Since(start), rpc.Method)
return
}
requestsTotal.WithLabelValues(rpc.Method).Inc()
r, err := http.NewRequestWithContext(ctx, "POST", *backendAddr, bytes.NewBuffer(b))
if err != nil {
panic(err)
}
r.Header = req.Header
reqs := time.Now()
res, err := h.client.Do(r)
if err != nil {
http.Error(w, "Bad Gateway", http.StatusBadGateway)
requestErrors.WithLabelValues("backend_request").Inc()
klog.Warningf("[%s] (+%v) [%s] backend request failed: %v",
req.RemoteAddr, rpc.ID, reqs.Sub(start), err)
return
}
defer res.Body.Close()
backendRequest.WithLabelValues(rpc.Method, strconv.Itoa(res.StatusCode)).Inc()
klog.V(1).Infof("[%s] (+%v) [%s] %s request returned status %d in %v",
req.RemoteAddr, time.Since(start), rpc.ID, rpc.Method, res.StatusCode, time.Since(reqs))
w.WriteHeader(res.StatusCode)
n, err := io.Copy(w, res.Body)
klog.V(1).Infof("[%s] (+%v) [%s] wrote %d bytes", req.RemoteAddr, time.Since(start), rpc.ID, n)
d := time.Since(start)
if err != nil {
klog.V(1).Infof("[%s] (+%v) [%s] failed writing response: %v",
req.RemoteAddr, d, rpc.ID, err)
}
httpDuration.WithLabelValues(rpc.Method).Observe(d.Seconds())
}
func (h handler) sendCORS(w http.ResponseWriter) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "Content-Type")
}

View File

@ -1,80 +0,0 @@
package main
var (
// https://docs.solana.com/developing/clients/jsonrpc-api
methodWhitelist = []string{
// Stable
"getAccountInfo",
"getBalance",
"getBlock",
"getBlockHeight",
"getBlockProduction",
"getBlockCommitment",
"getBlocks",
"getBlocksWithLimit",
"getBlockTime",
"getClusterNodes",
"getEpochInfo",
"getEpochSchedule",
"getFeeForMessage",
"getFirstAvailableBlock",
"getGenesisHash",
"getHealth",
"getHighestSnapshotSlot",
"getIdentity",
"getInflationGovernor",
"getInflationRate",
"getInflationReward",
"getLargestAccounts",
"getLatestBlockhash",
"getLeaderSchedule",
"getMaxRetransmitSlot",
"getMaxShredInsertSlot",
"getMinimumBalanceForRentExemption",
"getMultipleAccounts",
"getProgramAccounts",
"getRecentPerformanceSamples",
"getSignaturesForAddress",
"getSignatureStatuses",
"getSlot",
"getSlotLeader",
"getSlotLeaders",
"getStakeActivation",
"getStakeMinimumDelegation",
"getSupply",
"getTokenAccountBalance",
"getTokenAccountsByDelegate",
"getTokenAccountsByOwner",
"getTokenLargestAccounts",
"getTokenSupply",
"getTransaction",
"getTransactionCount",
"getVersion",
"getVoteAccounts",
"isBlockhashValid",
"minimumLedgerSlot",
"requestAirdrop",
"sendTransaction",
"simulateTransaction",
// Deprecated
"getConfirmedBlock",
"getConfirmedBlocks",
"getConfirmedBlocksWithLimit",
"getConfirmedSignaturesForAddress2",
"getConfirmedTransaction",
"getFeeCalculatorForBlockhash",
"getFeeRateGovernor",
"getFees",
"getRecentBlockhash",
"getSnapshotSlot",
}
methodWhitelistMap = make(map[string]bool)
)
func init() {
for _, v := range methodWhitelist {
methodWhitelistMap[v] = true
}
}

View File

@ -1,63 +0,0 @@
#!/usr/bin/env python3
import os
import requests
RADIANCE_HOST = os.getenv("RADIANCE_HOST")
RADIANCE_USER = os.getenv("RADIANCE_USER")
RADIANCE_PASSWORD = os.getenv("RADIANCE_PASSWORD")
LEADER_STATS = """
SELECT
floor(slot, -3) as slotWindow,
leader,
median(diff) AS medianReplay,
count() AS count
FROM
(
WITH
leader,
minIf(timestamp, type = 'firstShredReceived') AS tsReceived,
minIf(timestamp, type = 'completed') AS tsCompleted
SELECT
source,
slot,
leader,
toUnixTimestamp64Milli(tsCompleted) - toUnixTimestamp64Milli(tsReceived) AS diff
FROM slot_status
WHERE toDate(timestamp) = today() - 5
GROUP BY
slot,
leader,
source
HAVING diff > 0
)
GROUP BY slotWindow, leader
ORDER BY median(diff)"""
class RadianceClient():
def __init__(self, host, user, password):
self.host = host
self.user = user
self.password = password
self.session = requests.session()
self.session.user_agent = "radiance-client/v0.1"
self.session.auth = (self.user, self.password)
def query(self, query):
r = self.session.post(self.host, data=query + "\nFORMAT JSON")
if r.status_code != 200:
raise Exception("Failed to get leader stats: {}".format(r.text))
return r.json()['data']
def get_leader_stats(self):
return self.query(LEADER_STATS)
if __name__ == '__main__':
import json
c = RadianceClient(RADIANCE_HOST, RADIANCE_USER, RADIANCE_PASSWORD)
r = c.get_leader_stats()
print(json.dumps(r, indent=2))

View File

@ -1 +0,0 @@
out

View File

@ -1 +0,0 @@
SELECT max(slot) FROM slot_status WHERE toDate(timestamp) = today()

View File

View File

@ -1,13 +0,0 @@
SELECT slot,
timestamp,
runningDifference(toUnixTimestamp64Milli(timestamp)) AS deltaMs,
bar(deltaMs, 0, 10000, 10) AS deltaMsB,
type
FROM (
SELECT *
FROM slot_status
WHERE (slot = 138604605)
AND (source = 'val4.ffm1')
ORDER BY timestamp ASC,
type ASC
)

View File

@ -1,9 +0,0 @@
WITH CAST(timestamp, 'Nullable(DateTime)') AS ts
SELECT
slot,
minIf(ts, type = 'firstShredReceived') AS first,
minIf(ts, type = 'completed') AS completed,
minIf(ts, type = 'optimisticConfirmation') AS confirmed
FROM slot_status
GROUP BY slot
ORDER BY slot ASC

View File

@ -1,4 +0,0 @@
select leader, avg(stats.num_successful_transactions + assumeNotNull(stats.num_failed_transactions)) as avgTxs
from slot_status
group by leader
order by avgTxs desc

View File

@ -1,7 +0,0 @@
SELECT
slot,
max(assumeNotNull(stats.num_successful_transactions)) + max(assumeNotNull(stats.num_failed_transactions)) AS maxTxs
FROM slot_status
WHERE type = 'frozen'
GROUP BY slot
ORDER BY slot

View File

@ -1,29 +0,0 @@
SELECT
winner,
count(),
bar(count(), 1, 10000, 20)
FROM
(
SELECT
slot,
any(source) AS winner
FROM
(
SELECT
source,
slot,
minIf(timestamp, type = 'completed') AS firstCompleted
FROM slot_status
WHERE toDate(timestamp) = today()
GROUP BY
source,
slot
ORDER BY
slot ASC,
firstCompleted ASC
)
GROUP BY slot
ORDER BY slot ASC
)
GROUP BY winner
ORDER BY count() DESC

View File

@ -1,60 +0,0 @@
CREATE TABLE heimdall_queue
(
bankSlot UInt64,
bankID UInt64,
bankParentHash String,
feePayer String,
signature String,
program String,
"timings.serialize_us" UInt64,
"timings.create_vm_us" UInt64,
"timings.execute_us" UInt64,
"timings.deserialize_us" UInt64,
"timings.get_or_create_executor_us" UInt64,
"timings.changed_account_count" UInt64,
"timings.total_account_count" UInt64,
"timings.total_data_size" UInt64,
"timings.data_size_changed" UInt64,
"timings.create_executor_register_syscalls_us" UInt64,
"timings.create_executor_load_elf_us" UInt64,
"timings.create_executor_verify_code_us" UInt64,
"timings.create_executor_jit_compile_us" UInt64
) ENGINE = Kafka()
SETTINGS
kafka_broker_list = '<snip>:30036',
kafka_topic_list = 'certus.radiance.heimdall',
kafka_group_name = 'heimdall-chdev1',
kafka_format = 'Protobuf',
kafka_max_block_size = 1048576,
format_schema = 'heimdall.proto:Observation';
CREATE TABLE IF NOT EXISTS heimdall
(
timestamp DateTime64,
bankSlot UInt64,
bankID UInt64,
bankParentHash String,
feePayer String,
signature String,
program String,
"timings.serialize_us" UInt64,
"timings.create_vm_us" UInt64,
"timings.execute_us" UInt64,
"timings.deserialize_us" UInt64,
"timings.get_or_create_executor_us" UInt64,
"timings.changed_account_count" UInt64,
"timings.total_account_count" UInt64,
"timings.total_data_size" UInt64,
"timings.data_size_changed" UInt64,
"timings.create_executor_register_syscalls_us" UInt64,
"timings.create_executor_load_elf_us" UInt64,
"timings.create_executor_verify_code_us" UInt64,
"timings.create_executor_jit_compile_us" UInt64
) ENGINE = MergeTree()
PARTITION BY toStartOfHour(timestamp)
ORDER BY bankSlot;
CREATE MATERIALIZED VIEW IF NOT EXISTS heimdall_view TO heimdall
AS
SELECT _timestamp_ms AS timestamp, *
FROM heimdall_queue;

View File

@ -1,73 +0,0 @@
CREATE TABLE IF NOT EXISTS slot_status_queue
(
slot UInt64,
timestamp UInt64,
delay UInt64,
type Enum8(
'unspecified' = 0,
'firstShredReceived' = 1,
'completed' = 2,
'createdBank' = 3,
'frozen' = 4,
'dead' = 5,
'optimisticConfirmation' = 6,
'root' = 7
),
source String,
leader String,
parent UInt64,
"stats.num_transaction_entries" Nullable(UInt64),
"stats.num_successful_transactions" Nullable(UInt64),
"stats.num_failed_transactions" Nullable(UInt64),
"stats.max_transactions_per_entry" Nullable(UInt64),
err String
) ENGINE = Kafka()
SETTINGS
kafka_broker_list = '<snip>:30036',
kafka_topic_list = 'certus.radiance.slot_status',
kafka_group_name = 'heimdall-chdev1',
kafka_format = 'Protobuf',
kafka_max_block_size = 32,
format_schema = 'network.proto:SlotStatus';
CREATE TABLE IF NOT EXISTS slot_status
(
slot UInt64,
timestamp DateTime64(3),
delay UInt64,
type Enum8(
'unspecified' = 0,
'firstShredReceived' = 1,
'completed' = 2,
'createdBank' = 3,
'frozen' = 4,
'dead' = 5,
'optimisticConfirmation' = 6,
'root' = 7
),
source String,
leader String,
parent UInt64,
"stats.num_transaction_entries" Nullable(UInt64),
"stats.num_successful_transactions" Nullable(UInt64),
"stats.num_failed_transactions" Nullable(UInt64),
"stats.max_transactions_per_entry" Nullable(UInt64),
err String
) ENGINE = MergeTree()
PARTITION BY toDate(timestamp)
ORDER BY (slot, type, leader);
CREATE MATERIALIZED VIEW IF NOT EXISTS slot_status_view TO slot_status
AS
SELECT fromUnixTimestamp64Milli(timestamp) AS timestamp,
* EXCEPT ( timestamp )
FROM slot_status_queue;

12
go.mod
View File

@ -7,12 +7,10 @@ require (
github.com/LiamHaworth/go-tproxy v0.0.0-20190726054950-ef7efd7f24ed
github.com/VividCortex/ewma v1.2.0
github.com/cespare/xxhash/v2 v2.2.0
github.com/coreos/go-systemd/v22 v22.5.0
github.com/filecoin-project/go-leb128 v0.0.0-20190212224330-8d79a5489543
github.com/gagliardetto/binary v0.7.8
github.com/gagliardetto/solana-go v1.8.3-0.20230302093440-c6043ec381e3
github.com/go-logr/logr v1.2.3
github.com/golang/protobuf v1.5.2
github.com/google/gopacket v1.1.19
github.com/google/nftables v0.1.0
github.com/ipfs/go-cid v0.3.2
@ -32,13 +30,10 @@ require (
github.com/novifinancial/serde-reflection/serde-generate/runtime/golang v0.0.0-20220519162058-e5cd3c3b3f3a
github.com/prometheus/client_golang v1.14.0
github.com/segmentio/textio v1.2.0
github.com/slok/go-http-metrics v0.10.0
github.com/spaolacci/murmur3 v1.1.0
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.2
github.com/twmb/franz-go v1.12.1
github.com/vbauerster/mpb/v8 v8.2.1
golang.org/x/crypto v0.7.0
golang.org/x/sync v0.1.0
golang.org/x/sys v0.6.0
google.golang.org/protobuf v1.29.0
@ -58,7 +53,6 @@ require (
github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blendle/zapdriver v1.3.1 // indirect
github.com/buger/jsonparser v1.1.1 // indirect
github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
github.com/cncf/xds/go v0.0.0-20220520190051-1e77728a1eaa // indirect
@ -75,12 +69,11 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.0 // indirect
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
github.com/gorilla/rpc v1.2.0 // indirect
github.com/gorilla/websocket v1.4.2 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/ipfs/bbloom v0.0.4 // indirect
@ -122,7 +115,6 @@ require (
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.15.0 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pierrec/lz4/v4 v4.1.15 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/polydawn/refmt v0.89.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
@ -132,7 +124,6 @@ require (
github.com/spf13/pflag v1.0.5 // indirect
github.com/streamingfast/logging v0.0.0-20221209193439-bff11742bf4c // indirect
github.com/teris-io/shortid v0.0.0-20220617161101-71ec9f2aa569 // indirect
github.com/twmb/franz-go/pkg/kmsg v1.4.0 // indirect
github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f // indirect
github.com/whyrusleeping/cbor-gen v0.0.0-20230126041949-52956bd4c9aa // indirect
go.mongodb.org/mongo-driver v1.11.2 // indirect
@ -143,6 +134,7 @@ require (
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/ratelimit v0.2.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/exp v0.0.0-20230304125523-9ff063c70017 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect

18
go.sum
View File

@ -99,7 +99,6 @@ github.com/blendle/zapdriver v1.3.1 h1:C3dydBOWYRiOk+B8X9IVZ5IOe+7cl+tGOexN4QqHf
github.com/blendle/zapdriver v1.3.1/go.mod h1:mdXfREi6u5MArG4j9fewC+FGnXaBR+T4Ox4J2u4eHCc=
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0 h1:t/LhUZLVitR1Ow2YOnduCsavhwFUklBMoGVYUCqmCqk=
@ -126,8 +125,6 @@ github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
@ -171,6 +168,7 @@ github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmV
github.com/gagliardetto/binary v0.7.7/go.mod h1:mUuay5LL8wFVnIlecHakSZMvcdqfs+CsotR5n77kyjM=
github.com/gagliardetto/binary v0.7.8 h1:hbIUIP8BWhPm/BIdODxY2Lnv4NlJwNdbtsi1xkhNOec=
github.com/gagliardetto/binary v0.7.8/go.mod h1:Cn70Gnvyk1OWkNJXwVh3oYqSYhKLHJN+C/Wguw3fc3U=
github.com/gagliardetto/gofuzz v1.2.2 h1:XL/8qDMzcgvR4+CyRQW9UGdwPRPMHVJfqQ/uMvSUuQw=
github.com/gagliardetto/gofuzz v1.2.2/go.mod h1:bkH/3hYLZrMLbfYWA0pWzXmi5TTRZnu4pMGZBkqMKvY=
github.com/gagliardetto/solana-go v1.8.3-0.20230302093440-c6043ec381e3 h1:PtvmSQDTpZ1mwN1t7UlCrUhTyEozJhF3ixuO1m0+9q0=
github.com/gagliardetto/solana-go v1.8.3-0.20230302093440-c6043ec381e3/go.mod h1:i+7aAyNDTHG0jK8GZIBSI4OVvDqkt2Qx+LklYclRNG8=
@ -200,7 +198,6 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
@ -289,9 +286,7 @@ github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1Yu
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/rpc v1.2.0 h1:WvvdC2lNeT1SP32zrIce5l0ECBfbAlmrmSBsuc57wfk=
github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36jkTQ=
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
@ -427,7 +422,6 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.9/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
@ -577,8 +571,6 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pierrec/lz4/v4 v4.1.15 h1:MO0/ucJhngq7299dKLwIMtgTfbkoSPF6AoMYDd8Q4q0=
github.com/pierrec/lz4/v4 v4.1.15/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@ -668,8 +660,6 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/slok/go-http-metrics v0.10.0 h1:rh0LaYEKza5eaYRGDXujKrOln57nHBi4TtVhmNEpbgM=
github.com/slok/go-http-metrics v0.10.0/go.mod h1:lFqdaS4kWMfUKCSukjC47PdCeTk+hXDUVm8kLHRqJ38=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
@ -702,7 +692,6 @@ github.com/streamingfast/logging v0.0.0-20221209193439-bff11742bf4c/go.mod h1:Vl
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -729,10 +718,6 @@ github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhV
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/twmb/franz-go v1.12.1 h1:8lWT8q0spL40Nfw6eonJ8OoPGLvF9arvadRRmcSiu9Y=
github.com/twmb/franz-go v1.12.1/go.mod h1:Ofc5tSSUJKLmpRNUYSejUsAZKYAHDHywTS322KWdChQ=
github.com/twmb/franz-go/pkg/kmsg v1.4.0 h1:tbp9hxU6m8qZhQTlpGiaIJOm4BXix5lsuEZ7K00dF0s=
github.com/twmb/franz-go/pkg/kmsg v1.4.0/go.mod h1:SxG/xJKhgPu25SamAq0rrucfp7lbzCpEXOC+vH/ELrY=
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
@ -821,7 +806,6 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=

View File

@ -1,122 +0,0 @@
package blockhash
import (
"context"
"sync"
"time"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
envv1 "go.firedancer.io/radiance/proto/env/v1"
"k8s.io/klog/v2"
)
type Tracker struct {
mu sync.Mutex
byNode map[string]struct {
Blockhash solana.Hash
HighestValidSlot uint64
}
nodes []*envv1.RPCNode
c map[string]*rpc.Client
}
func New(nodes []*envv1.RPCNode) *Tracker {
t := &Tracker{
byNode: make(map[string]struct {
Blockhash solana.Hash
HighestValidSlot uint64
}),
c: make(map[string]*rpc.Client),
nodes: nodes,
}
for _, node := range nodes {
t.c[node.Name] = rpc.New(node.Http)
}
return t
}
func (t *Tracker) MostPopular() solana.Hash {
t.mu.Lock()
defer t.mu.Unlock()
// Return the most frequently occurring value of t.byNode
var mostPopular solana.Hash
var mostPopularCount int
for _, h := range t.byNode {
count := 0
for _, h2 := range t.byNode {
if h.Blockhash.Equals(h2.Blockhash) {
count++
}
}
if count > mostPopularCount {
mostPopular = h.Blockhash
mostPopularCount = count
}
klog.V(2).Infof("%s: %d", h, count)
}
return mostPopular
}
func (t *Tracker) MostRecent() solana.Hash {
t.mu.Lock()
defer t.mu.Unlock()
// Return the blockhash which has the highest valid slot
var mostRecent solana.Hash
var highestValidSlot uint64
for _, h := range t.byNode {
if h.HighestValidSlot > highestValidSlot {
highestValidSlot = h.HighestValidSlot
mostRecent = h.Blockhash
}
}
return mostRecent
}
func (t *Tracker) Run(ctx context.Context, interval time.Duration) {
t.update(ctx)
for {
select {
case <-ctx.Done():
return
case <-time.After(interval):
t.update(ctx)
}
}
}
func (t *Tracker) update(ctx context.Context) {
now := time.Now()
for _, node := range t.nodes {
node := node
go func() {
ctx, cancel := context.WithTimeout(ctx, time.Second*5)
defer cancel()
klog.V(1).Infof("Fetching blockhash from %s", node.Http)
h, err := t.c[node.Name].GetLatestBlockhash(ctx, rpc.CommitmentConfirmed)
if err != nil {
klog.Errorf("%s: failed to request blockhash: %v", node.Name, err)
return
}
klog.V(1).Infof("%s: fetched blockhash %d -> %s in %v",
node.Name, h.Value.LastValidBlockHeight, h.Value.Blockhash, time.Since(now))
t.mu.Lock()
t.byNode[node.Name] = struct {
Blockhash solana.Hash
HighestValidSlot uint64
}{
Blockhash: h.Value.Blockhash,
HighestValidSlot: h.Value.LastValidBlockHeight,
}
t.mu.Unlock()
}()
}
}

View File

@ -1,77 +0,0 @@
package clusternodes
import (
"context"
"math/rand"
"sync"
"time"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
envv1 "go.firedancer.io/radiance/proto/env/v1"
"k8s.io/klog/v2"
)
type Tracker struct {
mu sync.Mutex
current []*rpc.GetClusterNodesResult
byPubkey map[solana.PublicKey]*rpc.GetClusterNodesResult
c map[string]*rpc.Client
nodes []*envv1.RPCNode
}
func New(nodes []*envv1.RPCNode) *Tracker {
c := make(map[string]*rpc.Client)
for _, node := range nodes {
c[node.Name] = rpc.New(node.Http)
}
return &Tracker{
byPubkey: make(map[solana.PublicKey]*rpc.GetClusterNodesResult),
c: c,
nodes: nodes,
}
}
// Run periodically fetches the gossip
func (t *Tracker) Run(ctx context.Context, interval time.Duration) {
t.update(ctx)
for {
select {
case <-ctx.Done():
return
case <-time.After(interval):
t.update(ctx)
}
}
}
func (t *Tracker) update(ctx context.Context) {
now := time.Now()
// Fetch gossip
node := t.nodes[rand.Intn(len(t.nodes))]
c := t.c[node.Name]
klog.Infof("Fetching cluster nodes from %s", node.Http)
out, err := c.GetClusterNodes(ctx)
if err != nil {
klog.Errorf("Failed to update cluster nodes: %v", err)
return
}
klog.Infof("Fetched %d nodes in %v", len(out), time.Since(now))
t.mu.Lock()
t.current = out
for _, n := range out {
t.byPubkey[n.Pubkey] = n
}
t.mu.Unlock()
}
func (t *Tracker) GetByPubkey(pubkey solana.PublicKey) *rpc.GetClusterNodesResult {
t.mu.Lock()
entry := t.byPubkey[pubkey]
t.mu.Unlock()
return entry
}

View File

@ -1,25 +0,0 @@
package envfile
import (
"fmt"
"os"
envv1 "go.firedancer.io/radiance/proto/env/v1"
"google.golang.org/protobuf/encoding/prototext"
)
// Load loads the environment config from the given prototxt file.
func Load(filename string) (*envv1.Env, error) {
b, err := os.ReadFile(filename)
if err != nil {
return nil, fmt.Errorf("failed to read env file: %w", err)
}
var env envv1.Env
err = prototext.Unmarshal(b, &env)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal env file: %w", err)
}
return &env, nil
}

View File

@ -1,31 +0,0 @@
package envfile
import (
"testing"
envv1 "go.firedancer.io/radiance/proto/env/v1"
)
func TestLoadEnvFile(t *testing.T) {
env, err := Load("testdata/env.prototxt")
if err != nil {
t.Fatal(err)
}
if env.Nodes[0].Name != "localhost" {
t.Errorf("Expected node name to be 'localhost', got '%s'", env.Nodes[0].Name)
}
if len(env.Nodes) != 2 {
t.Errorf("Expected 2 node, got %d", len(env.Nodes))
}
if len(env.Kafka.Brokers) != 2 {
t.Errorf("Expected 2 broker, got %d", len(env.Kafka.Brokers))
}
if _, ok := env.Kafka.Encryption.(*envv1.Kafka_TlsEncryption); !ok {
t.Errorf("Expected TLS encryption, got %T", env.Kafka.Encryption)
}
}

View File

@ -1,29 +0,0 @@
package envfile
import (
"strings"
"go.firedancer.io/radiance/proto/env/v1"
)
func ParseOnlyFlag(only string) []string {
if only == "" {
return nil
}
return strings.Split(only, ",")
}
func FilterNodes(nodes []*envv1.RPCNode, only []string) []*envv1.RPCNode {
if len(only) == 0 {
return nodes
}
var filtered []*envv1.RPCNode
for _, node := range nodes {
for _, o := range only {
if node.Name == o {
filtered = append(filtered, node)
}
}
}
return filtered
}

View File

@ -1,25 +0,0 @@
nodes {
name: "localhost"
http: "http://localhost:8899"
ws: "ws://localhost:8900"
tag: "local"
}
nodes {
name: "localhost_2"
http: "http://localhost:8899"
ws: "ws://localhost:8900"
tag: "local"
}
kafka {
brokers: "localhost:9092"
brokers: "localhost:9092"
topic_prefix: "radiance.dev"
sasl_auth: {
username: "radiance"
password: "radiance"
}
tls_encryption: {}
}

View File

@ -1,37 +0,0 @@
package kafka
import (
"crypto/tls"
"net"
"time"
"github.com/twmb/franz-go/pkg/kgo"
"github.com/twmb/franz-go/pkg/sasl/scram"
envv1 "go.firedancer.io/radiance/proto/env/v1"
)
func NewClientFromEnv(env *envv1.Kafka, opts ...kgo.Opt) (*kgo.Client, error) {
opts = append(opts,
kgo.SeedBrokers(env.Brokers...),
)
if s, ok := env.Auth.(*envv1.Kafka_SaslAuth); ok {
m := scram.Auth{
User: s.SaslAuth.Username,
Pass: s.SaslAuth.Password}.AsSha256Mechanism()
opts = append(opts, kgo.SASL(m))
}
if _, ok := env.Encryption.(*envv1.Kafka_TlsEncryption); ok {
tlsDialer := &tls.Dialer{NetDialer: &net.Dialer{Timeout: 10 * time.Second}}
opts = append(opts, kgo.Dialer(tlsDialer.DialContext))
}
cl, err := kgo.NewClient(opts...)
if err != nil {
return nil, err
}
return cl, nil
}

View File

@ -1,220 +0,0 @@
package leaderschedule
import (
"context"
"fmt"
"math/rand"
"sync"
"time"
"github.com/gagliardetto/solana-go"
"github.com/gagliardetto/solana-go/rpc"
envv1 "go.firedancer.io/radiance/proto/env/v1"
"k8s.io/klog/v2"
)
type Tracker struct {
// mu guards max and cur
mu sync.Mutex
// max is the current leader schedule's highest slot
max uint64
// cur is the current highest slot observed on the network
cur uint64
// bySlot maps slots to their leader. Grows indefinitely as epochs progress.
bySlot map[uint64]solana.PublicKey
bySlotMu sync.RWMutex
// slotsPerEpoch is the number of slots per epoch on the network.
// Fetched once via RPC. Used to calculate epoch boundaries.
slotsPerEpoch uint64
// initCh is used to signal that the leader schedule is available.
initCh chan struct{}
// c caches RPC client connections by node name.
c map[string]*rpc.Client
}
const (
// prefetchSlots is the number of slots to prefetch.
prefetchSlots = 1000
)
// FirstSlot returns the epoch number and first slot of the epoch.
func (t *Tracker) FirstSlot(slotInEpoch uint64) (uint64, uint64) {
epoch := slotInEpoch / t.slotsPerEpoch
firstSlot := epoch * t.slotsPerEpoch
return epoch, firstSlot
}
// Update updates the current highest slot. Non-blocking.
func (t *Tracker) Update(slot uint64) {
t.mu.Lock()
defer t.mu.Unlock()
if slot > t.cur {
t.cur = slot
}
}
// Run periodically updates the leader schedule. When the current slot + prefetchSlots
// is greater than the highest slot in the schedule, the schedule is updated.
//
// A random node is picked from nodes to do the request against.
func (t *Tracker) Run(ctx context.Context, nodes []*envv1.RPCNode) {
t.initCh = make(chan struct{})
t.c = make(map[string]*rpc.Client)
for _, node := range nodes {
t.c[node.Name] = rpc.New(node.Http)
}
for {
// Fetch slots per epoch
node := nodes[rand.Intn(len(nodes))]
klog.Infof("Fetching epoch schedule from %s", node.Http)
out, err := t.c[node.Name].GetEpochSchedule(ctx)
if err != nil {
klog.Errorf("get epoch schedule: %w", err)
time.Sleep(time.Second)
continue
}
if out.FirstNormalEpoch != 0 {
panic("first normal epoch should be 0")
}
if out.FirstNormalSlot != 0 {
panic("first normal slot should be 0")
}
if out.LeaderScheduleSlotOffset <= prefetchSlots {
panic("leader schedule slot offset should be greater than prefetch slots")
}
t.slotsPerEpoch = out.SlotsPerEpoch
klog.Infof("Got epoch schedule: slotsPerEpoch=%d", t.slotsPerEpoch)
break
}
for {
select {
case <-ctx.Done():
return
default:
t.mu.Lock()
fetch := false
// If we're less than prefetchSlots slots away from the epoch boundary,
// fetch the new leader schedule.
threshold := t.cur + prefetchSlots
if threshold > t.max && t.cur != 0 {
fetch = true
}
// If we have no current leader schedule, fetch the current one.
var slot uint64
var prefetch bool
if t.max == 0 {
slot = t.cur
} else {
// If we have a leader schedule, prefetch the next one
slot = t.max + 1
prefetch = true
}
t.mu.Unlock()
if fetch {
if prefetch {
klog.Infof("Prefetching leader schedule for cur=%d, threshold=%d, max=%d, slot=%d",
t.cur, threshold, t.max, slot)
if err := t.fetch(ctx, nodes, slot); err != nil {
klog.Errorf("Failed to fetch leader schedule: %v", err)
}
} else {
klog.Infof("Fetching initial leader schedule for cur=%d, threshold=%d, max=%d, slot=%d",
t.cur, threshold, t.max, slot)
if err := t.fetch(ctx, nodes, slot); err != nil {
klog.Errorf("Failed to fetch leader schedule: %v", err)
}
// Signal that the leader schedule is available
close(t.initCh)
}
}
time.Sleep(time.Second)
}
}
}
func (t *Tracker) fetch(ctx context.Context, nodes []*envv1.RPCNode, slot uint64) error {
now := time.Now()
// Pick random node from nodes
node := nodes[rand.Intn(len(nodes))]
klog.Infof("Using node %s", node.Http)
// Fetch the leader schedule
out, err := t.c[node.Name].GetLeaderScheduleWithOpts(ctx, &rpc.GetLeaderScheduleOpts{
Epoch: &slot,
})
if err != nil {
return fmt.Errorf("get leader schedule: %w", err)
}
epoch, firstSlot := t.FirstSlot(slot)
klog.Infof("Fetched epoch schedule from %s in %v", node.Http, time.Since(now))
now = time.Now()
defer klog.V(1).Infof("bySlotMu: %v", time.Since(now))
t.bySlotMu.Lock()
defer t.bySlotMu.Unlock()
if t.bySlot == nil {
t.bySlot = make(map[uint64]solana.PublicKey)
}
// Update the leader schedule
m := uint64(0)
for pk, slots := range out {
for _, s := range slots {
t.bySlot[firstSlot+s] = pk
if firstSlot+s > m {
m = firstSlot + s
}
}
}
t.mu.Lock()
t.max = m
t.mu.Unlock()
klog.Infof("Updated leader schedule for epoch=%d, slot=%d, first=%d, max=%d",
epoch, slot, firstSlot, t.max)
return nil
}
// Get returns the scheduled leader for the given slot.
// It blocks until the leader schedule is available.
func (t *Tracker) Get(slot uint64) solana.PublicKey {
// Block until the leader schedule is available
if t.initCh != nil {
<-t.initCh
}
t.bySlotMu.RLock()
defer t.bySlotMu.RUnlock()
return t.bySlot[slot]
}
// TryGet returns the scheduled leader for the given slot.
// It returns false if the leader schedule is not yet available.
func (t *Tracker) TryGet(slot uint64) (solana.PublicKey, bool) {
t.bySlotMu.RLock()
defer t.bySlotMu.RUnlock()
if t.bySlot == nil {
return solana.PublicKey{}, false
}
return t.bySlot[slot], true
}

595
proto/env/v1/env.pb.go vendored
View File

@ -1,595 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.17.3
// source: proto/env/v1/env.proto
package envv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Env struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Nodes []*RPCNode `protobuf:"bytes,1,rep,name=nodes,proto3" json:"nodes,omitempty"`
Kafka *Kafka `protobuf:"bytes,2,opt,name=kafka,proto3" json:"kafka,omitempty"`
}
func (x *Env) Reset() {
*x = Env{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_env_v1_env_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Env) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Env) ProtoMessage() {}
func (x *Env) ProtoReflect() protoreflect.Message {
mi := &file_proto_env_v1_env_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Env.ProtoReflect.Descriptor instead.
func (*Env) Descriptor() ([]byte, []int) {
return file_proto_env_v1_env_proto_rawDescGZIP(), []int{0}
}
func (x *Env) GetNodes() []*RPCNode {
if x != nil {
return x.Nodes
}
return nil
}
func (x *Env) GetKafka() *Kafka {
if x != nil {
return x.Kafka
}
return nil
}
type RPCNode struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Http string `protobuf:"bytes,2,opt,name=http,proto3" json:"http,omitempty"`
Ws string `protobuf:"bytes,3,opt,name=ws,proto3" json:"ws,omitempty"`
Tag []string `protobuf:"bytes,4,rep,name=tag,proto3" json:"tag,omitempty"`
}
func (x *RPCNode) Reset() {
*x = RPCNode{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_env_v1_env_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *RPCNode) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*RPCNode) ProtoMessage() {}
func (x *RPCNode) ProtoReflect() protoreflect.Message {
mi := &file_proto_env_v1_env_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use RPCNode.ProtoReflect.Descriptor instead.
func (*RPCNode) Descriptor() ([]byte, []int) {
return file_proto_env_v1_env_proto_rawDescGZIP(), []int{1}
}
func (x *RPCNode) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *RPCNode) GetHttp() string {
if x != nil {
return x.Http
}
return ""
}
func (x *RPCNode) GetWs() string {
if x != nil {
return x.Ws
}
return ""
}
func (x *RPCNode) GetTag() []string {
if x != nil {
return x.Tag
}
return nil
}
type Kafka struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// List of seed brokers.
Brokers []string `protobuf:"bytes,1,rep,name=brokers,proto3" json:"brokers,omitempty"`
// Topic prefix (dot notation). The topic name is the prefix + application-specific name.
TopicPrefix string `protobuf:"bytes,2,opt,name=topic_prefix,json=topicPrefix,proto3" json:"topic_prefix,omitempty"`
// Authentication method.
//
// Types that are assignable to Auth:
// *Kafka_NoAuth
// *Kafka_SaslAuth
Auth isKafka_Auth `protobuf_oneof:"auth"`
// Encryption
//
// Types that are assignable to Encryption:
// *Kafka_TlsEncryption
Encryption isKafka_Encryption `protobuf_oneof:"encryption"`
}
func (x *Kafka) Reset() {
*x = Kafka{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_env_v1_env_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Kafka) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Kafka) ProtoMessage() {}
func (x *Kafka) ProtoReflect() protoreflect.Message {
mi := &file_proto_env_v1_env_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Kafka.ProtoReflect.Descriptor instead.
func (*Kafka) Descriptor() ([]byte, []int) {
return file_proto_env_v1_env_proto_rawDescGZIP(), []int{2}
}
func (x *Kafka) GetBrokers() []string {
if x != nil {
return x.Brokers
}
return nil
}
func (x *Kafka) GetTopicPrefix() string {
if x != nil {
return x.TopicPrefix
}
return ""
}
func (m *Kafka) GetAuth() isKafka_Auth {
if m != nil {
return m.Auth
}
return nil
}
func (x *Kafka) GetNoAuth() *Kafka_KafkaNoAuth {
if x, ok := x.GetAuth().(*Kafka_NoAuth); ok {
return x.NoAuth
}
return nil
}
func (x *Kafka) GetSaslAuth() *Kafka_KafkaSASLAuth {
if x, ok := x.GetAuth().(*Kafka_SaslAuth); ok {
return x.SaslAuth
}
return nil
}
func (m *Kafka) GetEncryption() isKafka_Encryption {
if m != nil {
return m.Encryption
}
return nil
}
func (x *Kafka) GetTlsEncryption() *Kafka_KafkaTLSEncryption {
if x, ok := x.GetEncryption().(*Kafka_TlsEncryption); ok {
return x.TlsEncryption
}
return nil
}
type isKafka_Auth interface {
isKafka_Auth()
}
type Kafka_NoAuth struct {
// No authentication.
NoAuth *Kafka_KafkaNoAuth `protobuf:"bytes,3,opt,name=no_auth,json=noAuth,proto3,oneof"`
}
type Kafka_SaslAuth struct {
// SASL authentication.
SaslAuth *Kafka_KafkaSASLAuth `protobuf:"bytes,4,opt,name=sasl_auth,json=saslAuth,proto3,oneof"`
}
func (*Kafka_NoAuth) isKafka_Auth() {}
func (*Kafka_SaslAuth) isKafka_Auth() {}
type isKafka_Encryption interface {
isKafka_Encryption()
}
type Kafka_TlsEncryption struct {
// TLS encryption.
TlsEncryption *Kafka_KafkaTLSEncryption `protobuf:"bytes,6,opt,name=tls_encryption,json=tlsEncryption,proto3,oneof"`
}
func (*Kafka_TlsEncryption) isKafka_Encryption() {}
// SASL SCRAM-SHA-256 authentication.
type Kafka_KafkaSASLAuth struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"`
Password string `protobuf:"bytes,2,opt,name=password,proto3" json:"password,omitempty"`
}
func (x *Kafka_KafkaSASLAuth) Reset() {
*x = Kafka_KafkaSASLAuth{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_env_v1_env_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Kafka_KafkaSASLAuth) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Kafka_KafkaSASLAuth) ProtoMessage() {}
func (x *Kafka_KafkaSASLAuth) ProtoReflect() protoreflect.Message {
mi := &file_proto_env_v1_env_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Kafka_KafkaSASLAuth.ProtoReflect.Descriptor instead.
func (*Kafka_KafkaSASLAuth) Descriptor() ([]byte, []int) {
return file_proto_env_v1_env_proto_rawDescGZIP(), []int{2, 0}
}
func (x *Kafka_KafkaSASLAuth) GetUsername() string {
if x != nil {
return x.Username
}
return ""
}
func (x *Kafka_KafkaSASLAuth) GetPassword() string {
if x != nil {
return x.Password
}
return ""
}
type Kafka_KafkaNoAuth struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Kafka_KafkaNoAuth) Reset() {
*x = Kafka_KafkaNoAuth{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_env_v1_env_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Kafka_KafkaNoAuth) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Kafka_KafkaNoAuth) ProtoMessage() {}
func (x *Kafka_KafkaNoAuth) ProtoReflect() protoreflect.Message {
mi := &file_proto_env_v1_env_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Kafka_KafkaNoAuth.ProtoReflect.Descriptor instead.
func (*Kafka_KafkaNoAuth) Descriptor() ([]byte, []int) {
return file_proto_env_v1_env_proto_rawDescGZIP(), []int{2, 1}
}
// TLS encryption.
type Kafka_KafkaTLSEncryption struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Kafka_KafkaTLSEncryption) Reset() {
*x = Kafka_KafkaTLSEncryption{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_env_v1_env_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Kafka_KafkaTLSEncryption) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Kafka_KafkaTLSEncryption) ProtoMessage() {}
func (x *Kafka_KafkaTLSEncryption) ProtoReflect() protoreflect.Message {
mi := &file_proto_env_v1_env_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Kafka_KafkaTLSEncryption.ProtoReflect.Descriptor instead.
func (*Kafka_KafkaTLSEncryption) Descriptor() ([]byte, []int) {
return file_proto_env_v1_env_proto_rawDescGZIP(), []int{2, 2}
}
var File_proto_env_v1_env_proto protoreflect.FileDescriptor
var file_proto_env_v1_env_proto_rawDesc = []byte{
0x0a, 0x16, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x76, 0x2f, 0x76, 0x31, 0x2f, 0x65,
0x6e, 0x76, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x03, 0x65, 0x6e, 0x76, 0x22, 0x4b, 0x0a,
0x03, 0x45, 0x6e, 0x76, 0x12, 0x22, 0x0a, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x01, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x65, 0x6e, 0x76, 0x2e, 0x52, 0x50, 0x43, 0x4e, 0x6f, 0x64,
0x65, 0x52, 0x05, 0x6e, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x05, 0x6b, 0x61, 0x66, 0x6b,
0x61, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x65, 0x6e, 0x76, 0x2e, 0x4b, 0x61,
0x66, 0x6b, 0x61, 0x52, 0x05, 0x6b, 0x61, 0x66, 0x6b, 0x61, 0x22, 0x53, 0x0a, 0x07, 0x52, 0x50,
0x43, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x74, 0x74,
0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x74, 0x74, 0x70, 0x12, 0x0e, 0x0a,
0x02, 0x77, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x77, 0x73, 0x12, 0x10, 0x0a,
0x03, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x03, 0x74, 0x61, 0x67, 0x22,
0xfc, 0x02, 0x0a, 0x05, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x72, 0x6f,
0x6b, 0x65, 0x72, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x62, 0x72, 0x6f, 0x6b,
0x65, 0x72, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x5f, 0x70, 0x72, 0x65,
0x66, 0x69, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x6f, 0x70, 0x69, 0x63,
0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x31, 0x0a, 0x07, 0x6e, 0x6f, 0x5f, 0x61, 0x75, 0x74,
0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x65, 0x6e, 0x76, 0x2e, 0x4b, 0x61,
0x66, 0x6b, 0x61, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x4e, 0x6f, 0x41, 0x75, 0x74, 0x68, 0x48,
0x00, 0x52, 0x06, 0x6e, 0x6f, 0x41, 0x75, 0x74, 0x68, 0x12, 0x37, 0x0a, 0x09, 0x73, 0x61, 0x73,
0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65,
0x6e, 0x76, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x53, 0x41,
0x53, 0x4c, 0x41, 0x75, 0x74, 0x68, 0x48, 0x00, 0x52, 0x08, 0x73, 0x61, 0x73, 0x6c, 0x41, 0x75,
0x74, 0x68, 0x12, 0x46, 0x0a, 0x0e, 0x74, 0x6c, 0x73, 0x5f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x65, 0x6e, 0x76,
0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x2e, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x54, 0x4c, 0x53, 0x45,
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x01, 0x52, 0x0d, 0x74, 0x6c, 0x73,
0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x47, 0x0a, 0x0d, 0x4b, 0x61,
0x66, 0x6b, 0x61, 0x53, 0x41, 0x53, 0x4c, 0x41, 0x75, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77,
0x6f, 0x72, 0x64, 0x1a, 0x0d, 0x0a, 0x0b, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x4e, 0x6f, 0x41, 0x75,
0x74, 0x68, 0x1a, 0x14, 0x0a, 0x12, 0x4b, 0x61, 0x66, 0x6b, 0x61, 0x54, 0x4c, 0x53, 0x45, 0x6e,
0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x06, 0x0a, 0x04, 0x61, 0x75, 0x74, 0x68,
0x42, 0x0c, 0x0a, 0x0a, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x2d,
0x5a, 0x2b, 0x67, 0x6f, 0x2e, 0x66, 0x69, 0x72, 0x65, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x2e,
0x69, 0x6f, 0x2f, 0x72, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x2f, 0x65, 0x6e, 0x76, 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x76, 0x76, 0x31, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_proto_env_v1_env_proto_rawDescOnce sync.Once
file_proto_env_v1_env_proto_rawDescData = file_proto_env_v1_env_proto_rawDesc
)
func file_proto_env_v1_env_proto_rawDescGZIP() []byte {
file_proto_env_v1_env_proto_rawDescOnce.Do(func() {
file_proto_env_v1_env_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_env_v1_env_proto_rawDescData)
})
return file_proto_env_v1_env_proto_rawDescData
}
var file_proto_env_v1_env_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_proto_env_v1_env_proto_goTypes = []interface{}{
(*Env)(nil), // 0: env.Env
(*RPCNode)(nil), // 1: env.RPCNode
(*Kafka)(nil), // 2: env.Kafka
(*Kafka_KafkaSASLAuth)(nil), // 3: env.Kafka.KafkaSASLAuth
(*Kafka_KafkaNoAuth)(nil), // 4: env.Kafka.KafkaNoAuth
(*Kafka_KafkaTLSEncryption)(nil), // 5: env.Kafka.KafkaTLSEncryption
}
var file_proto_env_v1_env_proto_depIdxs = []int32{
1, // 0: env.Env.nodes:type_name -> env.RPCNode
2, // 1: env.Env.kafka:type_name -> env.Kafka
4, // 2: env.Kafka.no_auth:type_name -> env.Kafka.KafkaNoAuth
3, // 3: env.Kafka.sasl_auth:type_name -> env.Kafka.KafkaSASLAuth
5, // 4: env.Kafka.tls_encryption:type_name -> env.Kafka.KafkaTLSEncryption
5, // [5:5] is the sub-list for method output_type
5, // [5:5] is the sub-list for method input_type
5, // [5:5] is the sub-list for extension type_name
5, // [5:5] is the sub-list for extension extendee
0, // [0:5] is the sub-list for field type_name
}
func init() { file_proto_env_v1_env_proto_init() }
func file_proto_env_v1_env_proto_init() {
if File_proto_env_v1_env_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_proto_env_v1_env_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Env); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_env_v1_env_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*RPCNode); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_env_v1_env_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Kafka); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_env_v1_env_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Kafka_KafkaSASLAuth); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_env_v1_env_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Kafka_KafkaNoAuth); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_env_v1_env_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Kafka_KafkaTLSEncryption); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_proto_env_v1_env_proto_msgTypes[2].OneofWrappers = []interface{}{
(*Kafka_NoAuth)(nil),
(*Kafka_SaslAuth)(nil),
(*Kafka_TlsEncryption)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_env_v1_env_proto_rawDesc,
NumEnums: 0,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_env_v1_env_proto_goTypes,
DependencyIndexes: file_proto_env_v1_env_proto_depIdxs,
MessageInfos: file_proto_env_v1_env_proto_msgTypes,
}.Build()
File_proto_env_v1_env_proto = out.File
file_proto_env_v1_env_proto_rawDesc = nil
file_proto_env_v1_env_proto_goTypes = nil
file_proto_env_v1_env_proto_depIdxs = nil
}

View File

@ -1,52 +0,0 @@
syntax = "proto3";
package env;
option go_package = "go.firedancer.io/radiance/proto/envv1;envv1";
// Package env provides shared environment configuration values.
message Env {
repeated RPCNode nodes = 1;
Kafka kafka = 2;
}
message RPCNode {
string name = 1;
string http = 2;
string ws = 3;
repeated string tag = 4;
}
message Kafka {
// List of seed brokers.
repeated string brokers = 1;
// Topic prefix (dot notation). The topic name is the prefix + application-specific name.
string topic_prefix = 2;
// SASL SCRAM-SHA-256 authentication.
message KafkaSASLAuth {
string username = 1;
string password = 2;
}
message KafkaNoAuth{}
// Authentication method.
oneof auth {
// No authentication.
KafkaNoAuth no_auth = 3;
// SASL authentication.
KafkaSASLAuth sasl_auth = 4;
}
// Encryption
oneof encryption {
// TLS encryption.
KafkaTLSEncryption tls_encryption = 6;
}
// TLS encryption.
message KafkaTLSEncryption {}
}

View File

@ -1,405 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.17.3
// source: proto/heimdall/v1/heimdall.proto
package heimdallv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Observation struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
BankSlot uint64 `protobuf:"varint,1,opt,name=bankSlot,proto3" json:"bankSlot,omitempty"`
BankID uint64 `protobuf:"varint,2,opt,name=bankID,proto3" json:"bankID,omitempty"`
BankParentHash string `protobuf:"bytes,3,opt,name=bankParentHash,proto3" json:"bankParentHash,omitempty"`
FeePayer string `protobuf:"bytes,4,opt,name=feePayer,proto3" json:"feePayer,omitempty"`
Signature string `protobuf:"bytes,5,opt,name=signature,proto3" json:"signature,omitempty"`
Program string `protobuf:"bytes,6,opt,name=program,proto3" json:"program,omitempty"`
Timings *Timings `protobuf:"bytes,7,opt,name=timings,proto3" json:"timings,omitempty"`
}
func (x *Observation) Reset() {
*x = Observation{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_heimdall_v1_heimdall_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Observation) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Observation) ProtoMessage() {}
func (x *Observation) ProtoReflect() protoreflect.Message {
mi := &file_proto_heimdall_v1_heimdall_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Observation.ProtoReflect.Descriptor instead.
func (*Observation) Descriptor() ([]byte, []int) {
return file_proto_heimdall_v1_heimdall_proto_rawDescGZIP(), []int{0}
}
func (x *Observation) GetBankSlot() uint64 {
if x != nil {
return x.BankSlot
}
return 0
}
func (x *Observation) GetBankID() uint64 {
if x != nil {
return x.BankID
}
return 0
}
func (x *Observation) GetBankParentHash() string {
if x != nil {
return x.BankParentHash
}
return ""
}
func (x *Observation) GetFeePayer() string {
if x != nil {
return x.FeePayer
}
return ""
}
func (x *Observation) GetSignature() string {
if x != nil {
return x.Signature
}
return ""
}
func (x *Observation) GetProgram() string {
if x != nil {
return x.Program
}
return ""
}
func (x *Observation) GetTimings() *Timings {
if x != nil {
return x.Timings
}
return nil
}
type Timings struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
SerializeUs uint64 `protobuf:"varint,1,opt,name=serialize_us,json=serializeUs,proto3" json:"serialize_us,omitempty"`
CreateVmUs uint64 `protobuf:"varint,2,opt,name=create_vm_us,json=createVmUs,proto3" json:"create_vm_us,omitempty"`
ExecuteUs uint64 `protobuf:"varint,3,opt,name=execute_us,json=executeUs,proto3" json:"execute_us,omitempty"`
DeserializeUs uint64 `protobuf:"varint,4,opt,name=deserialize_us,json=deserializeUs,proto3" json:"deserialize_us,omitempty"`
GetOrCreateExecutorUs uint64 `protobuf:"varint,5,opt,name=get_or_create_executor_us,json=getOrCreateExecutorUs,proto3" json:"get_or_create_executor_us,omitempty"`
ChangedAccountCount uint64 `protobuf:"varint,6,opt,name=changed_account_count,json=changedAccountCount,proto3" json:"changed_account_count,omitempty"`
TotalAccountCount uint64 `protobuf:"varint,7,opt,name=total_account_count,json=totalAccountCount,proto3" json:"total_account_count,omitempty"`
TotalDataSize uint64 `protobuf:"varint,8,opt,name=total_data_size,json=totalDataSize,proto3" json:"total_data_size,omitempty"`
DataSizeChanged uint64 `protobuf:"varint,9,opt,name=data_size_changed,json=dataSizeChanged,proto3" json:"data_size_changed,omitempty"`
CreateExecutorRegisterSyscallsUs uint64 `protobuf:"varint,10,opt,name=create_executor_register_syscalls_us,json=createExecutorRegisterSyscallsUs,proto3" json:"create_executor_register_syscalls_us,omitempty"`
CreateExecutorLoadElfUs uint64 `protobuf:"varint,11,opt,name=create_executor_load_elf_us,json=createExecutorLoadElfUs,proto3" json:"create_executor_load_elf_us,omitempty"`
CreateExecutorVerifyCodeUs uint64 `protobuf:"varint,12,opt,name=create_executor_verify_code_us,json=createExecutorVerifyCodeUs,proto3" json:"create_executor_verify_code_us,omitempty"`
CreateExecutorJitCompileUs uint64 `protobuf:"varint,13,opt,name=create_executor_jit_compile_us,json=createExecutorJitCompileUs,proto3" json:"create_executor_jit_compile_us,omitempty"`
}
func (x *Timings) Reset() {
*x = Timings{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_heimdall_v1_heimdall_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Timings) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Timings) ProtoMessage() {}
func (x *Timings) ProtoReflect() protoreflect.Message {
mi := &file_proto_heimdall_v1_heimdall_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Timings.ProtoReflect.Descriptor instead.
func (*Timings) Descriptor() ([]byte, []int) {
return file_proto_heimdall_v1_heimdall_proto_rawDescGZIP(), []int{1}
}
func (x *Timings) GetSerializeUs() uint64 {
if x != nil {
return x.SerializeUs
}
return 0
}
func (x *Timings) GetCreateVmUs() uint64 {
if x != nil {
return x.CreateVmUs
}
return 0
}
func (x *Timings) GetExecuteUs() uint64 {
if x != nil {
return x.ExecuteUs
}
return 0
}
func (x *Timings) GetDeserializeUs() uint64 {
if x != nil {
return x.DeserializeUs
}
return 0
}
func (x *Timings) GetGetOrCreateExecutorUs() uint64 {
if x != nil {
return x.GetOrCreateExecutorUs
}
return 0
}
func (x *Timings) GetChangedAccountCount() uint64 {
if x != nil {
return x.ChangedAccountCount
}
return 0
}
func (x *Timings) GetTotalAccountCount() uint64 {
if x != nil {
return x.TotalAccountCount
}
return 0
}
func (x *Timings) GetTotalDataSize() uint64 {
if x != nil {
return x.TotalDataSize
}
return 0
}
func (x *Timings) GetDataSizeChanged() uint64 {
if x != nil {
return x.DataSizeChanged
}
return 0
}
func (x *Timings) GetCreateExecutorRegisterSyscallsUs() uint64 {
if x != nil {
return x.CreateExecutorRegisterSyscallsUs
}
return 0
}
func (x *Timings) GetCreateExecutorLoadElfUs() uint64 {
if x != nil {
return x.CreateExecutorLoadElfUs
}
return 0
}
func (x *Timings) GetCreateExecutorVerifyCodeUs() uint64 {
if x != nil {
return x.CreateExecutorVerifyCodeUs
}
return 0
}
func (x *Timings) GetCreateExecutorJitCompileUs() uint64 {
if x != nil {
return x.CreateExecutorJitCompileUs
}
return 0
}
var File_proto_heimdall_v1_heimdall_proto protoreflect.FileDescriptor
var file_proto_heimdall_v1_heimdall_proto_rawDesc = []byte{
0x0a, 0x20, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x65, 0x69, 0x6d, 0x64, 0x61, 0x6c, 0x6c,
0x2f, 0x76, 0x31, 0x2f, 0x68, 0x65, 0x69, 0x6d, 0x64, 0x61, 0x6c, 0x6c, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x12, 0x08, 0x68, 0x65, 0x69, 0x6d, 0x64, 0x61, 0x6c, 0x6c, 0x22, 0xea, 0x01, 0x0a,
0x0b, 0x4f, 0x62, 0x73, 0x65, 0x72, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08,
0x62, 0x61, 0x6e, 0x6b, 0x53, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08,
0x62, 0x61, 0x6e, 0x6b, 0x53, 0x6c, 0x6f, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x61, 0x6e, 0x6b,
0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x62, 0x61, 0x6e, 0x6b, 0x49, 0x44,
0x12, 0x26, 0x0a, 0x0e, 0x62, 0x61, 0x6e, 0x6b, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x48, 0x61,
0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x62, 0x61, 0x6e, 0x6b, 0x50, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x65, 0x65, 0x50,
0x61, 0x79, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x65, 0x65, 0x50,
0x61, 0x79, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72,
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
0x72, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x18, 0x06, 0x20,
0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x12, 0x2b, 0x0a, 0x07,
0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e,
0x68, 0x65, 0x69, 0x6d, 0x64, 0x61, 0x6c, 0x6c, 0x2e, 0x54, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73,
0x52, 0x07, 0x74, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x9c, 0x05, 0x0a, 0x07, 0x54, 0x69,
0x6d, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69,
0x7a, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x65, 0x72,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x55, 0x73, 0x12, 0x20, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61,
0x74, 0x65, 0x5f, 0x76, 0x6d, 0x5f, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a,
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x56, 0x6d, 0x55, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x78,
0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09,
0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x55, 0x73, 0x12, 0x25, 0x0a, 0x0e, 0x64, 0x65, 0x73,
0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28,
0x04, 0x52, 0x0d, 0x64, 0x65, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x55, 0x73,
0x12, 0x38, 0x0a, 0x19, 0x67, 0x65, 0x74, 0x5f, 0x6f, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74,
0x65, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x75, 0x73, 0x18, 0x05, 0x20,
0x01, 0x28, 0x04, 0x52, 0x15, 0x67, 0x65, 0x74, 0x4f, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x55, 0x73, 0x12, 0x32, 0x0a, 0x15, 0x63, 0x68,
0x61, 0x6e, 0x67, 0x65, 0x64, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x63, 0x6f,
0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x13, 0x63, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x64, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2e,
0x0a, 0x13, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f,
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x74, 0x6f, 0x74,
0x61, 0x6c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x26,
0x0a, 0x0f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x69, 0x7a,
0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x44, 0x61,
0x74, 0x61, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x2a, 0x0a, 0x11, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73,
0x69, 0x7a, 0x65, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28,
0x04, 0x52, 0x0f, 0x64, 0x61, 0x74, 0x61, 0x53, 0x69, 0x7a, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67,
0x65, 0x64, 0x12, 0x4e, 0x0a, 0x24, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, 0x65,
0x63, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x73,
0x79, 0x73, 0x63, 0x61, 0x6c, 0x6c, 0x73, 0x5f, 0x75, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04,
0x52, 0x20, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72,
0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x53, 0x79, 0x73, 0x63, 0x61, 0x6c, 0x6c, 0x73,
0x55, 0x73, 0x12, 0x3c, 0x0a, 0x1b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, 0x65,
0x63, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x65, 0x6c, 0x66, 0x5f, 0x75,
0x73, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45,
0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x4c, 0x6f, 0x61, 0x64, 0x45, 0x6c, 0x66, 0x55, 0x73,
0x12, 0x42, 0x0a, 0x1e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75,
0x74, 0x6f, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x69, 0x66, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f,
0x75, 0x73, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x43, 0x6f,
0x64, 0x65, 0x55, 0x73, 0x12, 0x42, 0x0a, 0x1e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x65,
0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x5f, 0x6a, 0x69, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70,
0x69, 0x6c, 0x65, 0x5f, 0x75, 0x73, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x04, 0x52, 0x1a, 0x63, 0x72,
0x65, 0x61, 0x74, 0x65, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x6f, 0x72, 0x4a, 0x69, 0x74, 0x43,
0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x55, 0x73, 0x42, 0x35, 0x5a, 0x33, 0x67, 0x6f, 0x2e, 0x66,
0x69, 0x72, 0x65, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x2e, 0x69, 0x6f, 0x2f, 0x72, 0x61, 0x64,
0x69, 0x61, 0x6e, 0x63, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x68, 0x65, 0x69, 0x6d,
0x64, 0x61, 0x6c, 0x6c, 0x3b, 0x68, 0x65, 0x69, 0x6d, 0x64, 0x61, 0x6c, 0x6c, 0x76, 0x31, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_proto_heimdall_v1_heimdall_proto_rawDescOnce sync.Once
file_proto_heimdall_v1_heimdall_proto_rawDescData = file_proto_heimdall_v1_heimdall_proto_rawDesc
)
func file_proto_heimdall_v1_heimdall_proto_rawDescGZIP() []byte {
file_proto_heimdall_v1_heimdall_proto_rawDescOnce.Do(func() {
file_proto_heimdall_v1_heimdall_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_heimdall_v1_heimdall_proto_rawDescData)
})
return file_proto_heimdall_v1_heimdall_proto_rawDescData
}
var file_proto_heimdall_v1_heimdall_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_proto_heimdall_v1_heimdall_proto_goTypes = []interface{}{
(*Observation)(nil), // 0: heimdall.Observation
(*Timings)(nil), // 1: heimdall.Timings
}
var file_proto_heimdall_v1_heimdall_proto_depIdxs = []int32{
1, // 0: heimdall.Observation.timings:type_name -> heimdall.Timings
1, // [1:1] is the sub-list for method output_type
1, // [1:1] is the sub-list for method input_type
1, // [1:1] is the sub-list for extension type_name
1, // [1:1] is the sub-list for extension extendee
0, // [0:1] is the sub-list for field type_name
}
func init() { file_proto_heimdall_v1_heimdall_proto_init() }
func file_proto_heimdall_v1_heimdall_proto_init() {
if File_proto_heimdall_v1_heimdall_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_proto_heimdall_v1_heimdall_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Observation); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_heimdall_v1_heimdall_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Timings); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_heimdall_v1_heimdall_proto_rawDesc,
NumEnums: 0,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_heimdall_v1_heimdall_proto_goTypes,
DependencyIndexes: file_proto_heimdall_v1_heimdall_proto_depIdxs,
MessageInfos: file_proto_heimdall_v1_heimdall_proto_msgTypes,
}.Build()
File_proto_heimdall_v1_heimdall_proto = out.File
file_proto_heimdall_v1_heimdall_proto_rawDesc = nil
file_proto_heimdall_v1_heimdall_proto_goTypes = nil
file_proto_heimdall_v1_heimdall_proto_depIdxs = nil
}

View File

@ -1,31 +0,0 @@
syntax = "proto3";
package heimdall;
option go_package = "go.firedancer.io/radiance/proto/heimdall;heimdallv1";
message Observation{
uint64 bankSlot = 1;
uint64 bankID = 2;
string bankParentHash = 3;
string feePayer = 4;
string signature = 5;
string program = 6;
Timings timings = 7;
}
message Timings {
uint64 serialize_us = 1;
uint64 create_vm_us = 2;
uint64 execute_us = 3;
uint64 deserialize_us = 4;
uint64 get_or_create_executor_us = 5;
uint64 changed_account_count = 6;
uint64 total_account_count = 7;
uint64 total_data_size = 8;
uint64 data_size_changed = 9;
uint64 create_executor_register_syscalls_us = 10;
uint64 create_executor_load_elf_us = 11;
uint64 create_executor_verify_code_us = 12;
uint64 create_executor_jit_compile_us = 13;
}

View File

@ -1,422 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.17.3
// source: proto/network/v1/slot_status.proto
package networkv1
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Update type
type SlotStatus_UpdateType int32
const (
SlotStatus_UPDATE_TYPE_UNSPECIFIED SlotStatus_UpdateType = 0
SlotStatus_UPDATE_TYPE_FIRST_SHRED_RECEIVED SlotStatus_UpdateType = 1
SlotStatus_UPDATE_TYPE_COMPLETED SlotStatus_UpdateType = 2
SlotStatus_UPDATE_TYPE_CREATED_BANK SlotStatus_UpdateType = 3
SlotStatus_UPDATE_TYPE_FROZEN SlotStatus_UpdateType = 4
SlotStatus_UPDATE_TYPE_DEAD SlotStatus_UpdateType = 5
SlotStatus_UPDATE_TYPE_OPTIMISTIC_CONFIRMATION SlotStatus_UpdateType = 6
SlotStatus_UPDATE_TYPE_ROOT SlotStatus_UpdateType = 7
)
// Enum value maps for SlotStatus_UpdateType.
var (
SlotStatus_UpdateType_name = map[int32]string{
0: "UPDATE_TYPE_UNSPECIFIED",
1: "UPDATE_TYPE_FIRST_SHRED_RECEIVED",
2: "UPDATE_TYPE_COMPLETED",
3: "UPDATE_TYPE_CREATED_BANK",
4: "UPDATE_TYPE_FROZEN",
5: "UPDATE_TYPE_DEAD",
6: "UPDATE_TYPE_OPTIMISTIC_CONFIRMATION",
7: "UPDATE_TYPE_ROOT",
}
SlotStatus_UpdateType_value = map[string]int32{
"UPDATE_TYPE_UNSPECIFIED": 0,
"UPDATE_TYPE_FIRST_SHRED_RECEIVED": 1,
"UPDATE_TYPE_COMPLETED": 2,
"UPDATE_TYPE_CREATED_BANK": 3,
"UPDATE_TYPE_FROZEN": 4,
"UPDATE_TYPE_DEAD": 5,
"UPDATE_TYPE_OPTIMISTIC_CONFIRMATION": 6,
"UPDATE_TYPE_ROOT": 7,
}
)
func (x SlotStatus_UpdateType) Enum() *SlotStatus_UpdateType {
p := new(SlotStatus_UpdateType)
*p = x
return p
}
func (x SlotStatus_UpdateType) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (SlotStatus_UpdateType) Descriptor() protoreflect.EnumDescriptor {
return file_proto_network_v1_slot_status_proto_enumTypes[0].Descriptor()
}
func (SlotStatus_UpdateType) Type() protoreflect.EnumType {
return &file_proto_network_v1_slot_status_proto_enumTypes[0]
}
func (x SlotStatus_UpdateType) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use SlotStatus_UpdateType.Descriptor instead.
func (SlotStatus_UpdateType) EnumDescriptor() ([]byte, []int) {
return file_proto_network_v1_slot_status_proto_rawDescGZIP(), []int{0, 0}
}
// See client/src/rpc_response.rs.
type SlotStatus struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Slot number
Slot uint64 `protobuf:"varint,1,opt,name=slot,proto3" json:"slot,omitempty"`
// Millisecond UNIX timestamp of the observation on the Solana node.
// Depends on accurate local clocks.
Timestamp uint64 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
// One-way delay between the Solana node and the client.
Delay uint64 `protobuf:"varint,3,opt,name=delay,proto3" json:"delay,omitempty"`
Type SlotStatus_UpdateType `protobuf:"varint,4,opt,name=type,proto3,enum=proto.network.v1.SlotStatus_UpdateType" json:"type,omitempty"`
// For type == CREATED_BANK, the parent slot number is included.
Parent uint64 `protobuf:"varint,5,opt,name=parent,proto3" json:"parent,omitempty"`
// For type == FROZEN, extra transaction stats are included.
Stats *TxStats `protobuf:"bytes,6,opt,name=stats,proto3" json:"stats,omitempty"`
// For type == DEAD, an error is included.
// TODO: solana-go doesn't currently expose this
Err string `protobuf:"bytes,7,opt,name=err,proto3" json:"err,omitempty"`
// Slot's leader as base58 string (looked up by the ingester)
Leader string `protobuf:"bytes,8,opt,name=leader,proto3" json:"leader,omitempty"`
// Source node identifier
Source string `protobuf:"bytes,9,opt,name=source,proto3" json:"source,omitempty"`
}
func (x *SlotStatus) Reset() {
*x = SlotStatus{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_network_v1_slot_status_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SlotStatus) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SlotStatus) ProtoMessage() {}
func (x *SlotStatus) ProtoReflect() protoreflect.Message {
mi := &file_proto_network_v1_slot_status_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use SlotStatus.ProtoReflect.Descriptor instead.
func (*SlotStatus) Descriptor() ([]byte, []int) {
return file_proto_network_v1_slot_status_proto_rawDescGZIP(), []int{0}
}
func (x *SlotStatus) GetSlot() uint64 {
if x != nil {
return x.Slot
}
return 0
}
func (x *SlotStatus) GetTimestamp() uint64 {
if x != nil {
return x.Timestamp
}
return 0
}
func (x *SlotStatus) GetDelay() uint64 {
if x != nil {
return x.Delay
}
return 0
}
func (x *SlotStatus) GetType() SlotStatus_UpdateType {
if x != nil {
return x.Type
}
return SlotStatus_UPDATE_TYPE_UNSPECIFIED
}
func (x *SlotStatus) GetParent() uint64 {
if x != nil {
return x.Parent
}
return 0
}
func (x *SlotStatus) GetStats() *TxStats {
if x != nil {
return x.Stats
}
return nil
}
func (x *SlotStatus) GetErr() string {
if x != nil {
return x.Err
}
return ""
}
func (x *SlotStatus) GetLeader() string {
if x != nil {
return x.Leader
}
return ""
}
func (x *SlotStatus) GetSource() string {
if x != nil {
return x.Source
}
return ""
}
type TxStats struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
NumTransactionEntries uint64 `protobuf:"varint,1,opt,name=num_transaction_entries,json=numTransactionEntries,proto3" json:"num_transaction_entries,omitempty"`
NumSuccessfulTransactions uint64 `protobuf:"varint,2,opt,name=num_successful_transactions,json=numSuccessfulTransactions,proto3" json:"num_successful_transactions,omitempty"`
NumFailedTransactions uint64 `protobuf:"varint,3,opt,name=num_failed_transactions,json=numFailedTransactions,proto3" json:"num_failed_transactions,omitempty"`
MaxTransactionsPerEntry uint64 `protobuf:"varint,4,opt,name=max_transactions_per_entry,json=maxTransactionsPerEntry,proto3" json:"max_transactions_per_entry,omitempty"`
}
func (x *TxStats) Reset() {
*x = TxStats{}
if protoimpl.UnsafeEnabled {
mi := &file_proto_network_v1_slot_status_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *TxStats) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*TxStats) ProtoMessage() {}
func (x *TxStats) ProtoReflect() protoreflect.Message {
mi := &file_proto_network_v1_slot_status_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use TxStats.ProtoReflect.Descriptor instead.
func (*TxStats) Descriptor() ([]byte, []int) {
return file_proto_network_v1_slot_status_proto_rawDescGZIP(), []int{1}
}
func (x *TxStats) GetNumTransactionEntries() uint64 {
if x != nil {
return x.NumTransactionEntries
}
return 0
}
func (x *TxStats) GetNumSuccessfulTransactions() uint64 {
if x != nil {
return x.NumSuccessfulTransactions
}
return 0
}
func (x *TxStats) GetNumFailedTransactions() uint64 {
if x != nil {
return x.NumFailedTransactions
}
return 0
}
func (x *TxStats) GetMaxTransactionsPerEntry() uint64 {
if x != nil {
return x.MaxTransactionsPerEntry
}
return 0
}
var File_proto_network_v1_slot_status_proto protoreflect.FileDescriptor
var file_proto_network_v1_slot_status_proto_rawDesc = []byte{
0x0a, 0x22, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2f,
0x76, 0x31, 0x2f, 0x73, 0x6c, 0x6f, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x12, 0x10, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x77,
0x6f, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x22, 0x94, 0x04, 0x0a, 0x0a, 0x53, 0x6c, 0x6f, 0x74, 0x53,
0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x01, 0x20,
0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d,
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x14, 0x0a, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79,
0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x3b, 0x0a,
0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53,
0x6c, 0x6f, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61,
0x72, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x70, 0x61, 0x72, 0x65,
0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x78, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x05, 0x73, 0x74,
0x61, 0x74, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x72, 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x65, 0x72, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x18,
0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a,
0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73,
0x6f, 0x75, 0x72, 0x63, 0x65, 0x22, 0xf5, 0x01, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54,
0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10,
0x00, 0x12, 0x24, 0x0a, 0x20, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45,
0x5f, 0x46, 0x49, 0x52, 0x53, 0x54, 0x5f, 0x53, 0x48, 0x52, 0x45, 0x44, 0x5f, 0x52, 0x45, 0x43,
0x45, 0x49, 0x56, 0x45, 0x44, 0x10, 0x01, 0x12, 0x19, 0x0a, 0x15, 0x55, 0x50, 0x44, 0x41, 0x54,
0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x43, 0x4f, 0x4d, 0x50, 0x4c, 0x45, 0x54, 0x45, 0x44,
0x10, 0x02, 0x12, 0x1c, 0x0a, 0x18, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50,
0x45, 0x5f, 0x43, 0x52, 0x45, 0x41, 0x54, 0x45, 0x44, 0x5f, 0x42, 0x41, 0x4e, 0x4b, 0x10, 0x03,
0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
0x46, 0x52, 0x4f, 0x5a, 0x45, 0x4e, 0x10, 0x04, 0x12, 0x14, 0x0a, 0x10, 0x55, 0x50, 0x44, 0x41,
0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x45, 0x41, 0x44, 0x10, 0x05, 0x12, 0x27,
0x0a, 0x23, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4f, 0x50,
0x54, 0x49, 0x4d, 0x49, 0x53, 0x54, 0x49, 0x43, 0x5f, 0x43, 0x4f, 0x4e, 0x46, 0x49, 0x52, 0x4d,
0x41, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x06, 0x12, 0x14, 0x0a, 0x10, 0x55, 0x50, 0x44, 0x41, 0x54,
0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x4f, 0x4f, 0x54, 0x10, 0x07, 0x22, 0xf6, 0x01,
0x0a, 0x07, 0x54, 0x78, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x6e, 0x75, 0x6d,
0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x74,
0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x15, 0x6e, 0x75, 0x6d, 0x54,
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x74, 0x72, 0x69, 0x65,
0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x6e, 0x75, 0x6d, 0x5f, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73,
0x66, 0x75, 0x6c, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x19, 0x6e, 0x75, 0x6d, 0x53, 0x75, 0x63, 0x63, 0x65,
0x73, 0x73, 0x66, 0x75, 0x6c, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x73, 0x12, 0x36, 0x0a, 0x17, 0x6e, 0x75, 0x6d, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x5f,
0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01,
0x28, 0x04, 0x52, 0x15, 0x6e, 0x75, 0x6d, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3b, 0x0a, 0x1a, 0x6d, 0x61, 0x78,
0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x70, 0x65,
0x72, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x17, 0x6d,
0x61, 0x78, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x50, 0x65,
0x72, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x33, 0x5a, 0x31, 0x67, 0x6f, 0x2e, 0x66, 0x69, 0x72,
0x65, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x72, 0x2e, 0x69, 0x6f, 0x2f, 0x72, 0x61, 0x64, 0x69, 0x61,
0x6e, 0x63, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72,
0x6b, 0x3b, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
}
var (
file_proto_network_v1_slot_status_proto_rawDescOnce sync.Once
file_proto_network_v1_slot_status_proto_rawDescData = file_proto_network_v1_slot_status_proto_rawDesc
)
func file_proto_network_v1_slot_status_proto_rawDescGZIP() []byte {
file_proto_network_v1_slot_status_proto_rawDescOnce.Do(func() {
file_proto_network_v1_slot_status_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_network_v1_slot_status_proto_rawDescData)
})
return file_proto_network_v1_slot_status_proto_rawDescData
}
var file_proto_network_v1_slot_status_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_proto_network_v1_slot_status_proto_msgTypes = make([]protoimpl.MessageInfo, 2)
var file_proto_network_v1_slot_status_proto_goTypes = []interface{}{
(SlotStatus_UpdateType)(0), // 0: proto.network.v1.SlotStatus.UpdateType
(*SlotStatus)(nil), // 1: proto.network.v1.SlotStatus
(*TxStats)(nil), // 2: proto.network.v1.TxStats
}
var file_proto_network_v1_slot_status_proto_depIdxs = []int32{
0, // 0: proto.network.v1.SlotStatus.type:type_name -> proto.network.v1.SlotStatus.UpdateType
2, // 1: proto.network.v1.SlotStatus.stats:type_name -> proto.network.v1.TxStats
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_proto_network_v1_slot_status_proto_init() }
func file_proto_network_v1_slot_status_proto_init() {
if File_proto_network_v1_slot_status_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_proto_network_v1_slot_status_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SlotStatus); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_proto_network_v1_slot_status_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TxStats); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_proto_network_v1_slot_status_proto_rawDesc,
NumEnums: 1,
NumMessages: 2,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_proto_network_v1_slot_status_proto_goTypes,
DependencyIndexes: file_proto_network_v1_slot_status_proto_depIdxs,
EnumInfos: file_proto_network_v1_slot_status_proto_enumTypes,
MessageInfos: file_proto_network_v1_slot_status_proto_msgTypes,
}.Build()
File_proto_network_v1_slot_status_proto = out.File
file_proto_network_v1_slot_status_proto_rawDesc = nil
file_proto_network_v1_slot_status_proto_goTypes = nil
file_proto_network_v1_slot_status_proto_depIdxs = nil
}

View File

@ -1,55 +0,0 @@
syntax = "proto3";
package proto.network.v1;
option go_package = "go.firedancer.io/radiance/proto/network;networkv1";
// See client/src/rpc_response.rs.
message SlotStatus {
// Slot number
uint64 slot = 1;
// Millisecond UNIX timestamp of the observation on the Solana node.
// Depends on accurate local clocks.
uint64 timestamp = 2;
// One-way delay between the Solana node and the client.
uint64 delay = 3;
// Update type
enum UpdateType {
UPDATE_TYPE_UNSPECIFIED = 0;
UPDATE_TYPE_FIRST_SHRED_RECEIVED = 1;
UPDATE_TYPE_COMPLETED = 2;
UPDATE_TYPE_CREATED_BANK = 3;
UPDATE_TYPE_FROZEN = 4;
UPDATE_TYPE_DEAD = 5;
UPDATE_TYPE_OPTIMISTIC_CONFIRMATION = 6;
UPDATE_TYPE_ROOT = 7;
}
UpdateType type = 4;
// For type == CREATED_BANK, the parent slot number is included.
uint64 parent = 5;
// For type == FROZEN, extra transaction stats are included.
TxStats stats = 6;
// For type == DEAD, an error is included.
// TODO: solana-go doesn't currently expose this
string err = 7;
// Slot's leader as base58 string (looked up by the ingester)
string leader = 8;
// Source node identifier
string source = 9;
}
message TxStats {
uint64 num_transaction_entries = 1;
uint64 num_successful_transactions = 2;
uint64 num_failed_transactions = 3;
uint64 max_transactions_per_entry = 4;
}