Skip to content

Commit

Permalink
Pruned and archive (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
baabeetaa authored Mar 28, 2023
1 parent 9938473 commit 5b80395
Show file tree
Hide file tree
Showing 10 changed files with 225 additions and 102 deletions.
12 changes: 8 additions & 4 deletions cmd/root.go → cmd_root.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
package cmd
package main

import (
"fmt"
"github.com/notional-labs/subnode/config"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"os"
)

var (
cfg *config.Config
cfg *Config
conf string // path to config file
)

Expand All @@ -22,11 +21,12 @@ func NewRootCmd() *cobra.Command {
}

rootCmd.PersistentPreRunE = func(cmd *cobra.Command, _ []string) error {
cfg, err := config.LoadConfigFromFile(conf)
c, err := LoadConfigFromFile(conf)
if err != nil {
return err
}

cfg = c
fmt.Printf("%+v\n", cfg)

return nil
Expand Down Expand Up @@ -58,3 +58,7 @@ func Execute() {
os.Exit(1)
}
}

func GetConfig() *Config {
return cfg
}
5 changes: 2 additions & 3 deletions cmd/start.go → cmd_start.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cmd
package main

import (
"github.com/notional-labs/subnode/rpc"
"github.com/spf13/cobra"
)

Expand All @@ -11,7 +10,7 @@ func startCmd() *cobra.Command {
Short: "start subnode server",
Args: cobra.ExactArgs(0),
RunE: func(cmd *cobra.Command, args []string) error {
rpc.StartRpcServer()
StartRpcServer()
return nil
},
}
Expand Down
75 changes: 75 additions & 0 deletions config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"gopkg.in/yaml.v3"
"os"
)

type Backend struct {
Rpc string

// examples:
// [1, 100] => from block 1 to block 100 (subnode)
// [10] => last 10 recent blocks
// [] => archive node
Blocks []int
}

type Config struct {
Upstream []Backend `yaml:",flow"`
}

type BackendNodeType uint8

const (
BackendNodeTypePruned BackendNodeType = 0
BackendNodeTypeSubNode BackendNodeType = 1
BackendNodeTypeArchive BackendNodeType = 2
)

func GetBackendNodeType(b *Backend) BackendNodeType {
switch c := len(b.Blocks); c {
case 0:
return BackendNodeTypeArchive
case 1:
return BackendNodeTypePruned
case 2:
return BackendNodeTypeSubNode
default:
panic("invalid blocks config")
}
}

func SelectPrunedNode(cfg *Config) *Backend {
for _, s := range cfg.Upstream {
if GetBackendNodeType(&s) == BackendNodeTypePruned {
return &s
}
}

return nil
}

func LoadConfigFromFile(filename string) (*Config, error) {
buf, err := os.ReadFile(filename)
if err != nil {
return nil, err
}

c, err := LoadConfigFromBytes(buf)
if err != nil {
return nil, err
}

return c, err
}

func LoadConfigFromBytes(buf []byte) (*Config, error) {
c := &Config{}
err := yaml.Unmarshal(buf, c)
if err != nil {
return nil, err
}

return c, err
}
43 changes: 0 additions & 43 deletions config/config.go

This file was deleted.

24 changes: 0 additions & 24 deletions config/config_test.go

This file was deleted.

48 changes: 48 additions & 0 deletions config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package main

import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
)

func TestLoadConfigFromBytes(t *testing.T) {
var data = `
upstream:
- rpc: "http://pruned"
blocks: [50]
- rpc: "http://subnode"
blocks: [100, 200]
- rpc: "http://archive"
blocks: []
`
cfg, err := LoadConfigFromBytes([]byte(data))
assert.NoError(t, err)
fmt.Printf("%+v\n", cfg)
}

func TestGetBackendNodeType(t *testing.T) {
b := Backend{
Rpc: "http://pruned",
Blocks: []int{10},
}

assert.Equal(t, GetBackendNodeType(&b), BackendNodeTypePruned)
}

func TestSelectPrunedNode(t *testing.T) {
pruned := Backend{
Rpc: "http://pruned",
Blocks: []int{10},
}
archive := Backend{
Rpc: "http://archive",
Blocks: []int{},
}

cfg := Config{
Upstream: []Backend{pruned, archive},
}

assert.Equal(t, SelectPrunedNode(&cfg).Rpc, pruned.Rpc)
}
67 changes: 67 additions & 0 deletions doc/rpc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
### Tendermint RPC

#### URI over HTTP

https://docs.tendermint.com/v0.34/rpc/#/


[ ] /abci_info?
route to pruned node
[ ] /abci_query?path=_&data=_&height=_&prove=_
base on height
[ ] /block?height=_
base on height
[ ] /block_by_hash?hash=_
not supported, should use indexer instead
[ ] /block_results?height=_
base on height
[ ] /block_search?query=_&page=_&per_page=_&order_by=_
not supported, should be used with indexer
[ ] /blockchain?minHeight=_&maxHeight=_
base on minHeight & maxHeight
[ ] /broadcast_evidence?evidence=_
route to pruned node
[ ] /broadcast_tx_async?tx=_
route to pruned node
[ ] /broadcast_tx_commit?tx=_
route to pruned node
[ ] /broadcast_tx_sync?tx=_
route to pruned node
[ ] /check_tx?tx=_
route to pruned node
[ ] /commit?height=_
base on height
[ ] /consensus_params?height=_
base on height
[ ] /consensus_state?
route to pruned node
[ ] /dump_consensus_state?
route to pruned node
[ ] /genesis?
route to pruned node
[ ] /genesis_chunked?chunk=_
route to pruned node
[ ] /health?
route to pruned node
[ ] /net_info?
route to pruned node
[ ] /num_unconfirmed_txs?
route to pruned node
[ ] /status?
route to pruned node
[ ] /subscribe?query=_
not supported, use pruned node directly
[ ] /tx?hash=_&prove=_
not supported, should use indexer instead
[ ] /tx_search?query=_&prove=_&page=_&per_page=_&order_by=_
not supported, should use indexer instead
[ ] /unconfirmed_txs?limit=_
route to pruned node
[ ] /unsubscribe?query=_
not supported, use pruned node directly
[ ] /unsubscribe_all?
not supported, use pruned node directly
[ ] /validators?height=_&page=_&per_page=_
base on height


6 changes: 1 addition & 5 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
package main

import (
"github.com/notional-labs/subnode/cmd"
)

func main() {
cmd.Execute()
Execute()
}
37 changes: 20 additions & 17 deletions rpc/rpc_server.go → rpc_server.go
Original file line number Diff line number Diff line change
@@ -1,45 +1,48 @@
package rpc
package main

import (
"fmt"
"log"
"net/http"
"net/http/httputil"
"net/url"
"strings"
)

func StartRpcServer() {
hostProxy := make(map[string]*httputil.ReverseProxy)

target, err := url.Parse("https://google.com:443")
if err != nil {
panic(err)
}
hostProxy["/google"] = httputil.NewSingleHostReverseProxy(target)

target, err = url.Parse("https://rpc-osmosis-ia.cosmosia.notional.ventures:443")
if err != nil {
panic(err)
cfg := GetConfig()
for _, s := range cfg.Upstream {
target, err := url.Parse(s.Rpc)
if err != nil {
panic(err)
}
hostProxy[s.Rpc] = httputil.NewSingleHostReverseProxy(target)
}
hostProxy["/osmosis"] = httputil.NewSingleHostReverseProxy(target)

handler := func(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
fmt.Println("%v", r.RequestURI)
// see `/doc/rpc.md` to see the logic

fmt.Print("r.RequestURI=%s\n", r.RequestURI)

prunedNode := SelectPrunedNode(cfg)
selectedHost := prunedNode.Rpc // default to pruned node

if strings.HasPrefix(r.RequestURI, "/abci_info") {
selectedHost = prunedNode.Rpc
}

r.Host = r.URL.Host
hostProxy[r.RequestURI].ServeHTTP(w, r)
hostProxy[selectedHost].ServeHTTP(w, r)
} else {
w.Header().Set("Content-Type", "text/html")
w.WriteHeader(http.StatusBadRequest)
w.Write([]byte("Oops! Something was wrong"))
}
}

if err != nil {
panic(err)
}

// handle all requests to your server using the proxy
http.HandleFunc("/", handler)
log.Fatal(http.ListenAndServe(":8080", nil))
Expand Down
Loading

0 comments on commit 5b80395

Please sign in to comment.