Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pruned and archive #7

Merged
merged 7 commits into from
Mar 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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