Skip to content

Commit

Permalink
Adding a preset network of 3 master nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
otherview committed May 1, 2024
1 parent d10e6f2 commit d231469
Show file tree
Hide file tree
Showing 8 changed files with 231 additions and 4 deletions.
7 changes: 6 additions & 1 deletion cmd/cmd/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"github.com/vechain/networkhub/hub"
"github.com/vechain/networkhub/preset"

"github.com/vechain/networkhub/entrypoint/api"
"github.com/vechain/networkhub/environments/local"
Expand All @@ -18,7 +19,11 @@ var apiCmd = &cobra.Command{

envManager := hub.NewNetworkHub()
envManager.RegisterEnvironment("local", local.NewLocalEnv)
httpAPI := api.New(envManager)

presets := preset.NewPresetNetworks()
presets.Register("threeMasterNodesNetwork", preset.LocalThreeMasterNodesNetwork)

httpAPI := api.New(envManager, presets)

if err := httpAPI.Start(); err != nil {
fmt.Println("Shutting down.. Unexpected error in api - %w", err)
Expand Down
36 changes: 35 additions & 1 deletion entrypoint/api/http_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"encoding/json"
"fmt"
"github.com/vechain/networkhub/hub"
"github.com/vechain/networkhub/preset"
"net/http"
"strings"

Expand All @@ -12,15 +13,18 @@ import (

type Server struct {
entrypoint *hub.NetworkHub
presets *preset.Networks
}

func New(envMgr *hub.NetworkHub) *Server {
func New(envMgr *hub.NetworkHub, presets *preset.Networks) *Server {
return &Server{
entrypoint: envMgr,
presets: presets,
}
}

func (s *Server) Start() error {
http.HandleFunc("/preset", s.presetHandler)
http.HandleFunc("/config", s.configHandler)
http.HandleFunc("/start", s.startHandler)
http.HandleFunc("/stop", s.stopHandler)
Expand All @@ -33,6 +37,36 @@ func (s *Server) Start() error {
return nil
}

func (s *Server) presetHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodGet {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
return
}

// Extract the part of the path after "/preset/"
networkPresetID := strings.TrimPrefix(r.URL.Path, "/preset/")
if networkPresetID == "" {
http.Error(w, "Network preset ID must be specified", http.StatusBadRequest)
return
}

networkCfg, err := s.presets.Load(networkPresetID)
if err != nil {
http.Error(w, fmt.Sprintf("unable to load network preset - %s", err), http.StatusBadRequest)
return
}

networkID, err := s.entrypoint.LoadNetworkConfig(networkCfg)
if err != nil {
http.Error(w, fmt.Sprintf("Unable to load network config - %s", err.Error()), http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
fmt.Fprintf(w, fmt.Sprintf("{\"networkId\": \"%s\"}", networkID))

}

func (s *Server) configHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
Expand Down
26 changes: 25 additions & 1 deletion entrypoint/api/http_api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package api
import (
"bytes"
"github.com/vechain/networkhub/hub"
"github.com/vechain/networkhub/network"
"github.com/vechain/networkhub/preset"
"net/http"
"net/http/httptest"
"strings"
Expand Down Expand Up @@ -59,11 +61,31 @@ func TestStartStopHandler(t *testing.T) {
wantStatus: http.StatusInternalServerError,
wantBody: "Unable to stop network - network no-exist is not configured\n",
},
{
name: "Load existing preset network",
target: "/preset/noop-network",
payload: "{}",
method: http.MethodGet,
wantStatus: http.StatusOK,
wantBody: "{\"networkId\": \"noop\"}",
},
{
name: "Load non-preset network",
target: "/preset/noop-network-no-exist",
payload: "{}",
method: http.MethodGet,
wantStatus: http.StatusBadRequest,
wantBody: "unable to load network preset - unable to find preset with id noop-network-no-exist",
},
}

envManager := hub.NewNetworkHub()
envManager.RegisterEnvironment("noop", noop.NewNoopEnv)
api := New(envManager)

presets := preset.NewPresetNetworks()
presets.Register("noop-network", &network.Network{Environment: "noop"})

api := New(envManager, presets)

for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
Expand All @@ -72,6 +94,8 @@ func TestStartStopHandler(t *testing.T) {
var handler http.HandlerFunc

switch {
case strings.Contains(tc.target, "/preset"):
handler = api.presetHandler
case strings.Contains(tc.target, "/config"):
handler = api.configHandler
case strings.Contains(tc.target, "/start"):
Expand Down
4 changes: 4 additions & 0 deletions environments/actions.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ type Actions interface {
StopNetwork() error
Info() error
}

const (
Local = "local"
)
2 changes: 1 addition & 1 deletion network/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
)

type Network struct {
Nodes []*node.Node `json:"nodes"`
Environment string `json:"environment"`
Nodes []*node.Node `json:"nodes"`
}
type Builder struct {
}
Expand Down
5 changes: 5 additions & 0 deletions network/node/node.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package node

const (
MasterNode = "MasterNode"
RegularNode = "RegularNode"
)

type Node struct {
ID string `json:"id"` //TODO this is a mandatory field
Genesis interface{} `json:"genesis,omitempty"` //TODO would be nice to have validation in this format
Expand Down
127 changes: 127 additions & 0 deletions preset/LocalThreeMasterNodes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package preset

import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/vechain/networkhub/environments"
"github.com/vechain/networkhub/network"
"github.com/vechain/networkhub/network/node"
"github.com/vechain/thor/genesis"
"github.com/vechain/thor/thor"
"math/big"
)

var LocalThreeMasterNodesNetwork = &network.Network{
Environment: environments.Local,
Nodes: []*node.Node{
{
ID: "node1",
Genesis: localThreeMasterNodesNetworkGenesis,
P2PListenPort: 8081,
APIAddr: "127.0.0.1:8181",
APICORS: "*",
Type: node.MasterNode,
Key: "01a4107bfb7d5141ec519e75788c34295741a1eefbfe460320efd2ada944071e",
Enode: "enode://2ac08a2c35f090e5c47fe99bb0b2956d5b3366c61a83ef30719d393b5984227f4a5bb35b42fef94c3c03c1797ddd97546bb6eeb627b040c4c8dd554b4289024d@127.0.0.1:8081",
},
{
ID: "node2",
Genesis: localThreeMasterNodesNetworkGenesis,
P2PListenPort: 8082,
APIAddr: "127.0.0.1:8182",
APICORS: "*",
Type: node.MasterNode,
Key: "7072249b800ddac1d29a3cd06468cc1a917cbcd110dde358a905d03dad51748d",
Enode: "enode://ca36cbb2e9ad0ed582350ee04f49408f4fa409a8ca39982a34e4d5bb82418c45f3fd74bc4861f5aaecd986f1697f28010e1f6af7fadf08c6f529188752f47bee@127.0.0.1:8082",
},
{
ID: "node3",
Genesis: localThreeMasterNodesNetworkGenesis,
P2PListenPort: 8083,
APIAddr: "127.0.0.1:8183",
APICORS: "*",
Type: node.MasterNode,
Key: "c55455943bf026dc44fcf189e8765eb0587c94e66029d580bae795386c0b737a",
Enode: "enode://2d5b5f39e906dd717d721e3f039326e55163697e99e0a9998193eddfbb42e21a457ab877c355ee89c2bdf2562c86f6946b1e98119e945c091cab1a5ded8ca027@127.0.0.1:8083",
},
},
}

var localThreeMasterEndorser = thor.MustParseAddress("0x0000000000000000000000004578656375746f72")
var localThreeMasterNodesNetworkGenesis = &genesis.CustomGenesis{
LaunchTime: 1703180212,
GasLimit: 10000000,
ExtraData: "Local Three Master Nodes Network",
Accounts: []genesis.Account{
{
Address: thor.MustParseAddress("0x7567d83b7b8d80addcb281a71d54fc7b3364ffed"),
Balance: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
Energy: (*genesis.HexOrDecimal256)(big.NewInt(0)),
Code: "0x6060604052600256",
Storage: map[string]thor.Bytes32{
"0x0000000000000000000000000000000000000000000000000000000000000001": thor.MustParseBytes32("0x0000000000000000000000000000000000000000000000000000000000000002"),
},
},
{
Address: thor.MustParseAddress("0x7567d83b7b8d80addcb281a71d54fc7b3364ffed"),
Balance: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
Energy: (*genesis.HexOrDecimal256)(big.NewInt(0)),
Code: "0x6060604052600256",
Storage: map[string]thor.Bytes32{
"0x0000000000000000000000000000000000000000000000000000000000000001": thor.MustParseBytes32("0x0000000000000000000000000000000000000000000000000000000000000002"),
},
},
{
Address: thor.MustParseAddress("0x61fF580B63D3845934610222245C116E013717ec"),
Balance: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
Energy: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
},
{
Address: thor.MustParseAddress("0x327931085B4cCbCE0baABb5a5E1C678707C51d90"),
Balance: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
Energy: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
},
{
Address: thor.MustParseAddress("0x084E48c8AE79656D7e27368AE5317b5c2D6a7497"),
Balance: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
Energy: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
},
},
Authority: []genesis.Authority{
{
MasterAddress: thor.MustParseAddress("0x61fF580B63D3845934610222245C116E013717ec"),
EndorsorAddress: thor.MustParseAddress("0x7567d83b7b8d80addcb281a71d54fc7b3364ffed"),
Identity: thor.MustParseBytes32("0x000000000000000068747470733a2f2f636f6e6e65782e76656368612e696e2f"),
},
{
MasterAddress: thor.MustParseAddress("0x327931085B4cCbCE0baABb5a5E1C678707C51d90"),
EndorsorAddress: thor.MustParseAddress("0x7567d83b7b8d80addcb281a71d54fc7b3364ffed"),
Identity: thor.MustParseBytes32("0x000000000000000068747470733a2f2f656e762e7665636861696e2e6f72672f"),
},
{
MasterAddress: thor.MustParseAddress("0x084E48c8AE79656D7e27368AE5317b5c2D6a7497"),
EndorsorAddress: thor.MustParseAddress("0x7567d83b7b8d80addcb281a71d54fc7b3364ffed"),
Identity: thor.MustParseBytes32("0x0000000000000068747470733a2f2f617070732e7665636861696e2e6f72672f"),
},
},
Params: genesis.Params{
RewardRatio: (*genesis.HexOrDecimal256)(big.NewInt(300000000000000000)),
BaseGasPrice: (*genesis.HexOrDecimal256)(big.NewInt(1000000000000000)),
ProposerEndorsement: (*genesis.HexOrDecimal256)(new(big.Int).SetBytes(hexutil.MustDecode("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))),
ExecutorAddress: &localThreeMasterEndorser,
},
Executor: genesis.Executor{
Approvers: []genesis.Approver{
{
Address: thor.MustParseAddress("0x199b836d8a57365baccd4f371c1fabb7be77d389"),
Identity: thor.MustParseBytes32("0x00000000000067656e6572616c20707572706f736520626c6f636b636861696e"),
},
},
},
ForkConfig: &thor.ForkConfig{
VIP191: 0,
ETH_CONST: 0,
BLOCKLIST: 0,
ETH_IST: 0,
VIP214: 0,
},
}
28 changes: 28 additions & 0 deletions preset/preset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package preset

import (
"fmt"
"github.com/vechain/networkhub/network"
)

type Networks struct {
presets map[string]*network.Network
}

func NewPresetNetworks() *Networks {
return &Networks{
presets: map[string]*network.Network{},
}
}

func (p *Networks) Register(id string, preset *network.Network) {
p.presets[id] = preset
}

func (p *Networks) Load(id string) (*network.Network, error) {
preset, ok := p.presets[id]
if !ok {
return nil, fmt.Errorf("unable to find preset with id %s", id)
}
return preset, nil
}

0 comments on commit d231469

Please sign in to comment.