major release
This commit is contained in:
parent
750f3b1547
commit
9947861ff8
13 changed files with 372 additions and 254 deletions
18
.github/workflows/go.yml
vendored
18
.github/workflows/go.yml
vendored
|
|
@ -14,15 +14,15 @@ jobs:
|
|||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.24'
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.24'
|
||||
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
- name: Build
|
||||
run: go build -v ./...
|
||||
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
- name: Test
|
||||
run: go test -v ./...
|
||||
|
|
|
|||
9
.gitignore
vendored
9
.gitignore
vendored
|
|
@ -10,6 +10,15 @@ config/
|
|||
data/
|
||||
yggstack/
|
||||
.vscode/
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -1,4 +1,8 @@
|
|||
# lbc
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
>>>>>>> d8e9608 (Fix key parsing and update docs)
|
||||
|
||||
Experimental blockchain implementation built on Tendermint and BadgerDB.
|
||||
|
||||
|
|
@ -27,3 +31,9 @@ go run .
|
|||
```
|
||||
|
||||
See `--help` for a full list of available options.
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
blockchain for social cooperation
|
||||
>>>>>>> 1e4be97 (Initial commit)
|
||||
=======
|
||||
>>>>>>> d8e9608 (Fix key parsing and update docs)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package abciapp
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
@ -106,7 +106,6 @@ tcp://longseason.1200bps.xyz:13121
|
|||
tcp://149.28.123.138:8008
|
||||
tcp://lancis.iscute.moe:49273
|
||||
tcp://zabugor.itrus.su:7991
|
||||
tcp://supergay.network:9002
|
||||
tls://108.175.10.127:61216
|
||||
tls://longseason.1200bps.xyz:13122
|
||||
tls://167.160.89.98:7040
|
||||
|
|
|
|||
33
cli/init.go
Normal file
33
cli/init.go
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var initCmd = &cobra.Command{
|
||||
Use: "init [genesis|join] [genesis-path]",
|
||||
Short: "Инициализация ноды: genesis или join",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
switch args[0] {
|
||||
case "genesis":
|
||||
initGenesis()
|
||||
case "join":
|
||||
if len(args) < 2 {
|
||||
fmt.Println("Укажите путь к genesis.json")
|
||||
os.Exit(1)
|
||||
}
|
||||
initJoiner(args[1])
|
||||
default:
|
||||
fmt.Printf("Неизвестный режим init: %s\n", args[0])
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(initCmd)
|
||||
}
|
||||
23
cli/root.go
Normal file
23
cli/root.go
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "lbc",
|
||||
Short: "Лёгкий блокчейн координатор",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
runNode()
|
||||
},
|
||||
}
|
||||
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "ошибка: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
223
cli/run.go
Normal file
223
cli/run.go
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
abciApp "lbc/abciapp"
|
||||
cfg "lbc/configfunctions"
|
||||
"lbc/yggdrasil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/dgraph-io/badger"
|
||||
"github.com/spf13/viper"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
nm "github.com/tendermint/tendermint/node"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
tmTypes "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
var defaultConfigPath string
|
||||
var dbPath string
|
||||
|
||||
func init() {
|
||||
rootCmd.PersistentFlags().StringVar(&defaultConfigPath, "config", "./config/config.toml", "Путь к конфигурационному файлу")
|
||||
rootCmd.PersistentFlags().StringVar(&dbPath, "badger", "./badger", "Путь к базе данных BadgerDB")
|
||||
}
|
||||
|
||||
func newTendermint(app abci.Application, configFile string, v *viper.Viper) (*nm.Node, error) {
|
||||
config, err := cfg.ReadConfig(configFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("конфигурация не прочитана: %w", err)
|
||||
}
|
||||
|
||||
laddrReturner := make(chan string, 2)
|
||||
go yggdrasil.Yggdrasil(v, laddrReturner)
|
||||
|
||||
config.P2P.ListenAddress = "tcp://" + <-laddrReturner
|
||||
config.P2P.PersistentPeers = <-laddrReturner
|
||||
|
||||
var pv tmTypes.PrivValidator
|
||||
if _, err := os.Stat(config.PrivValidatorKeyFile()); err == nil {
|
||||
pv = privval.LoadFilePV(
|
||||
config.PrivValidatorKeyFile(),
|
||||
config.PrivValidatorStateFile(),
|
||||
)
|
||||
} else {
|
||||
fmt.Println("⚠️ priv_validator_key.json not found. Node will run as non-validator.")
|
||||
pv = tmTypes.NewMockPV()
|
||||
}
|
||||
|
||||
nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load node key: %w", err)
|
||||
}
|
||||
|
||||
clientCreator := proxy.NewLocalClientCreator(app)
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||
|
||||
return nm.NewNode(
|
||||
config,
|
||||
pv,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
nm.DefaultGenesisDocProviderFunc(config),
|
||||
nm.DefaultDBProvider,
|
||||
nm.DefaultMetricsProvider(config.Instrumentation),
|
||||
logger,
|
||||
)
|
||||
}
|
||||
|
||||
func exitWithError(msg string, err error) {
|
||||
fmt.Fprintf(os.Stderr, "%s: %v\n", msg, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func loadViperConfig(path string) (*viper.Viper, error) {
|
||||
v := viper.New()
|
||||
v.SetConfigFile(path)
|
||||
err := v.ReadInConfig()
|
||||
return v, err
|
||||
}
|
||||
|
||||
func openBadger(path string) (*badger.DB, error) {
|
||||
return badger.Open(badger.DefaultOptions(path).WithTruncate(true))
|
||||
}
|
||||
|
||||
func buildNode() (*nm.Node, *badger.DB, error) {
|
||||
v, err := loadViperConfig(defaultConfigPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, `Конфигурационный файл не найден: %v
|
||||
|
||||
Похоже, что нода ещё не инициализирована.
|
||||
|
||||
Чтобы создать необходимые файлы, запусти одну из следующих команд:
|
||||
|
||||
lbc --init=genesis # если это новая цепочка
|
||||
lbc --init=join # если ты присоединяешься к существующей
|
||||
|
||||
По умолчанию файл конфигурации ищется по пути: %s
|
||||
`, err, defaultConfigPath)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
db, err := openBadger(dbPath)
|
||||
if err != nil {
|
||||
exitWithError("failed to open badger db", err)
|
||||
}
|
||||
|
||||
app := abciApp.NewKVStoreApplication(db)
|
||||
|
||||
node, err := newTendermint(app, defaultConfigPath, v)
|
||||
if err != nil {
|
||||
exitWithError("error creating node", err)
|
||||
}
|
||||
return node, db, err
|
||||
}
|
||||
|
||||
func runNode() {
|
||||
node, db, err := buildNode()
|
||||
if err != nil {
|
||||
exitWithError("failed to build node", err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
if err := node.Start(); err != nil {
|
||||
exitWithError("failed to start node", err)
|
||||
}
|
||||
defer func() {
|
||||
node.Stop()
|
||||
node.Wait()
|
||||
}()
|
||||
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
}
|
||||
|
||||
func initGenesis() {
|
||||
config := cfg.DefaultConfig()
|
||||
config.RootDir = filepath.Dir(filepath.Dir(defaultConfigPath))
|
||||
|
||||
nodeinfo := p2p.DefaultNodeInfo{}
|
||||
viper := cfg.WriteConfig(config, &defaultConfigPath, nodeinfo)
|
||||
if err := cfg.InitTendermintFiles(config); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to init files: %v\n", err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
node, db, err := buildNode()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
db.Close()
|
||||
|
||||
cfg.UpdateGenesisJson(node.NodeInfo(), viper)
|
||||
fmt.Println("Genesis node initialized.")
|
||||
}
|
||||
|
||||
func copyFile(src, dst string) error {
|
||||
in, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer in.Close()
|
||||
|
||||
if err = os.MkdirAll(filepath.Dir(dst), 0o700); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out, err := os.Create(dst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = out.Sync()
|
||||
_ = out.Close()
|
||||
}()
|
||||
|
||||
_, err = io.Copy(out, in)
|
||||
return err
|
||||
}
|
||||
|
||||
func initJoiner(path string) {
|
||||
config := cfg.DefaultConfig()
|
||||
config.RootDir = filepath.Dir(filepath.Dir(defaultConfigPath))
|
||||
|
||||
if err := copyFile(path, config.GenesisFile()); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "не удалось скопировать genesis.json:", err)
|
||||
os.Exit(3)
|
||||
}
|
||||
|
||||
node, db, err := buildNode()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
cfg.WriteConfig(config, &defaultConfigPath, node.NodeInfo())
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(config.RootDir, "data"), 0o700); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "не удалось создать директорию data")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "ошибка генерации node_key.json")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
pv := privval.GenFilePV(
|
||||
config.PrivValidatorKeyFile(),
|
||||
config.PrivValidatorStateFile(),
|
||||
)
|
||||
pv.Save()
|
||||
|
||||
fmt.Println("Joiner node initialized.")
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package configfunctions
|
|||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"lbc/yggdrasil"
|
||||
|
|
@ -75,7 +76,7 @@ func writeYggdrasilKey(path string) {
|
|||
os.WriteFile(path, []byte(hexKey), 0600)
|
||||
}
|
||||
|
||||
func WriteConfig(config *cfg.Config, configPath *string, isJoinerGenerator bool, nodeInfo p2p.NodeInfo) {
|
||||
func WriteConfig(config *cfg.Config, configPath *string, nodeInfo p2p.NodeInfo) *viper.Viper {
|
||||
writeYggdrasilKey(*yggKeyPath)
|
||||
pubkey, err := yggdrasil.GetPublicKey(*yggKeyPath)
|
||||
if err != nil {
|
||||
|
|
@ -115,19 +116,10 @@ func WriteConfig(config *cfg.Config, configPath *string, isJoinerGenerator bool,
|
|||
"private_key_file": *yggKeyPath,
|
||||
})
|
||||
|
||||
if isJoinerGenerator {
|
||||
// TODO idea what if mix persistent peers from the current persistent peers list appending current and mix them all?
|
||||
nodeId := nodeInfo.ID()
|
||||
myPeer := yggdrasil.GetYggdrasilAddress(v)
|
||||
config.P2P.PersistentPeers = string(nodeId) + "@ygg://[" + myPeer + "]:" + strconv.Itoa(yggListenPort)
|
||||
} else {
|
||||
config.P2P.PersistentPeers = ""
|
||||
}
|
||||
|
||||
v.Set("p2p", map[string]interface{}{
|
||||
"use_legacy": false,
|
||||
"queue_type": "priority",
|
||||
"laddr": strconv.Itoa(yggListenPort) + ":127.0.0.1:80",
|
||||
"laddr": strconv.Itoa(yggListenPort) + ":127.0.0.1:8000",
|
||||
"external_address": "", // will be set automatically by Tendermint if needed
|
||||
"upnp": false,
|
||||
"bootstrap_peers": "",
|
||||
|
|
@ -136,13 +128,17 @@ func WriteConfig(config *cfg.Config, configPath *string, isJoinerGenerator bool,
|
|||
"addr_book_strict": true,
|
||||
})
|
||||
|
||||
nodeId := nodeInfo.ID()
|
||||
myPeer := yggdrasil.GetYggdrasilAddress(v, nil)
|
||||
config.P2P.PersistentPeers = string(nodeId) + "@ygg://[" + myPeer + "]:" + strconv.Itoa(yggListenPort)
|
||||
|
||||
err = v.WriteConfigAs(*configPath)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error writing config: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("Custom config written to %s\n", *configPath)
|
||||
return v
|
||||
}
|
||||
|
||||
func ReadConfig(configFile string) (*cfg.Config, error) {
|
||||
|
|
@ -169,3 +165,28 @@ func ReadConfig(configFile string) (*cfg.Config, error) {
|
|||
func DefaultConfig() *cfg.Config {
|
||||
return cfg.DefaultConfig()
|
||||
}
|
||||
|
||||
func UpdateGenesisJson(nodeInfo p2p.NodeInfo, v *viper.Viper) {
|
||||
file, err := os.ReadFile("./config/genesis.json") // TODO remove hardocded paths
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
var dat map[string]any
|
||||
if err := json.Unmarshal(file, &dat); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
myPeer := yggdrasil.GetYggdrasilAddress(v, nil)
|
||||
|
||||
p2peers := fmt.Sprintf("%s@ygg://[%s]:%d", nodeInfo.ID(), myPeer, yggListenPort)
|
||||
dat["p2peers"] = p2peers
|
||||
|
||||
out, err := json.MarshalIndent(dat, "", " ")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := os.WriteFile("./config/genesis.json", out, 0o644); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
22
go.mod
22
go.mod
|
|
@ -1,10 +1,17 @@
|
|||
module lbc
|
||||
|
||||
go 1.24
|
||||
go 1.24.3
|
||||
|
||||
require (
|
||||
github.com/dgraph-io/badger v1.6.2
|
||||
github.com/go-git/go-git/v5 v5.16.2
|
||||
github.com/gologme/log v1.3.0
|
||||
github.com/spf13/cobra v1.6.0
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/tendermint/tendermint v0.34.24
|
||||
github.com/things-go/go-socks5 v0.0.5
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.5.12
|
||||
github.com/yggdrasil-network/yggstack v0.0.0-20250208132654-8ad1962f6456
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -52,6 +59,7 @@ require (
|
|||
github.com/gtank/merlin v0.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hjson/hjson-go/v4 v4.4.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jmhodges/levigo v1.0.0 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
|
|
@ -81,7 +89,6 @@ require (
|
|||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/subosito/gotenv v1.4.1 // indirect
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
|
||||
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
|
||||
|
|
@ -106,16 +113,5 @@ require (
|
|||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-git/go-git/v5 v5.16.2
|
||||
github.com/gologme/log v1.3.0
|
||||
github.com/spf13/viper v1.13.0
|
||||
github.com/things-go/go-socks5 v0.0.5
|
||||
github.com/yggdrasil-network/yggdrasil-go v0.5.12
|
||||
github.com/yggdrasil-network/yggstack v0.0.0-20250208132654-8ad1962f6456
|
||||
gvisor.dev/gvisor v0.0.0-20240810013311-326fe0f2a77f // indirect
|
||||
)
|
||||
|
||||
replace github.com/yggdrasil-network/yggstack/cmd/yggstack => ./yggstack
|
||||
|
|
|
|||
9
go.sum
9
go.sum
|
|
@ -117,6 +117,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
|
|||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creachadair/taskgroup v0.3.2 h1:zlfutDS+5XG40AOxcHDSThxKzns8Tnr9jnr6VqkYlkM=
|
||||
github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+kq+TDlRJQ0Wbk=
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
|
||||
|
|
@ -278,6 +279,8 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
|
|||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc=
|
||||
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
|
||||
|
|
@ -369,6 +372,7 @@ github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7
|
|||
github.com/rs/cors v1.8.2 h1:KCooALfAYGs415Cwu5ABvv9n9509fSiG5SQJn/AQo4U=
|
||||
github.com/rs/cors v1.8.2/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0=
|
||||
github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
|
|
@ -388,6 +392,8 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
|
|||
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
|
||||
github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/cobra v1.6.0 h1:42a0n6jwCot1pUmomAp4T7DeMD+20LFv4Q54pxLf2LI=
|
||||
github.com/spf13/cobra v1.6.0/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
|
|
@ -398,9 +404,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
|
|||
github.com/spf13/viper v1.13.0 h1:BWSJ/M+f+3nmdz9bxB+bWX28kkALN2ok11D0rSo8EJU=
|
||||
github.com/spf13/viper v1.13.0/go.mod h1:Icm2xNL3/8uyh/wFuB1jI7TiTNKp8632Nwegu+zgdYw=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
|
|
|
|||
160
main.go
160
main.go
|
|
@ -1,163 +1,9 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
|
||||
cfg "lbc/configfunctions"
|
||||
"lbc/yggdrasil"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"syscall"
|
||||
|
||||
"github.com/dgraph-io/badger"
|
||||
"github.com/spf13/viper"
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
nm "github.com/tendermint/tendermint/node"
|
||||
"github.com/tendermint/tendermint/p2p"
|
||||
"github.com/tendermint/tendermint/privval"
|
||||
"github.com/tendermint/tendermint/proxy"
|
||||
tmTypes "github.com/tendermint/tendermint/types"
|
||||
"lbc/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
defaultConfigPath = flag.String("config", "./config/config.toml", "Path to config file")
|
||||
dbPath = flag.String("badger", "./badger", "Path to database")
|
||||
initMode = flag.Bool("init", false, "Generate new config, keys and genesis")
|
||||
initType = flag.String("mode", "genesis", "Init mode: genesis or join")
|
||||
writeConfigStubPath = flag.String("joiner-config", "", "Stub for join file")
|
||||
)
|
||||
|
||||
func initFiles() {
|
||||
config := cfg.DefaultConfig()
|
||||
config.RootDir = filepath.Dir(filepath.Dir(*defaultConfigPath))
|
||||
|
||||
switch *initType {
|
||||
case "genesis":
|
||||
cfg.WriteConfig(config, defaultConfigPath, false, p2p.DefaultNodeInfo{})
|
||||
if err := cfg.InitTendermintFiles(config); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to init files: %v\n", err)
|
||||
panic(err)
|
||||
}
|
||||
fmt.Println("Genesis node initialized.")
|
||||
case "join":
|
||||
cfg.WriteConfig(config, defaultConfigPath, false, p2p.DefaultNodeInfo{})
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(config.RootDir, "data"), 0700); err != nil {
|
||||
fmt.Fprint(os.Stderr, "не удалось создать директорию data")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if _, err := p2p.LoadOrGenNodeKey(config.NodeKeyFile()); err != nil {
|
||||
fmt.Fprint(os.Stderr, "ошибка генерации node_key.json")
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
pv := privval.GenFilePV(
|
||||
config.PrivValidatorKeyFile(),
|
||||
config.PrivValidatorStateFile(),
|
||||
)
|
||||
pv.Save()
|
||||
|
||||
fmt.Println("Peer node initialized. Please ensure genesis.json is placed correctly.")
|
||||
default:
|
||||
fmt.Fprintf(os.Stderr, "Unknown mode: %s\n", *initType)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if *initMode {
|
||||
initFiles()
|
||||
return
|
||||
}
|
||||
|
||||
viper.SetConfigFile(*defaultConfigPath)
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, `Конфигурационный файл не найден: %v
|
||||
|
||||
Похоже, что нода ещё не инициализирована.
|
||||
|
||||
Чтобы создать необходимые файлы, запусти одну из следующих команд:
|
||||
|
||||
lbc --init --mode=genesis # если это новая цепочка
|
||||
lbc --init --mode=join # если ты присоединяешься к существующей
|
||||
|
||||
По умолчанию файл конфигурации ищется по пути: %s
|
||||
`, err, *defaultConfigPath)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
db, err := badger.Open(badger.DefaultOptions(*dbPath).WithTruncate(true))
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "failed to open badger db: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
app := NewKVStoreApplication(db)
|
||||
|
||||
ch := make(chan string, 2)
|
||||
|
||||
go yggdrasil.Yggdrasil(viper.GetViper(), ch)
|
||||
|
||||
node, err := newTendermint(app, *defaultConfigPath, ch)
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "error creating node: %v\n", err)
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
if *writeConfigStubPath != "" {
|
||||
cfg.WriteConfig(node.Config(), writeConfigStubPath, true, node.NodeInfo())
|
||||
return
|
||||
}
|
||||
|
||||
node.Start()
|
||||
defer func() { node.Stop(); node.Wait() }()
|
||||
sigCh := make(chan os.Signal, 1)
|
||||
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
|
||||
<-sigCh
|
||||
}
|
||||
|
||||
func newTendermint(app abci.Application, configFile string, laddrReturner chan string) (*nm.Node, error) {
|
||||
config, err := cfg.ReadConfig(configFile)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("конфигурация не прочитана")
|
||||
}
|
||||
config.P2P.ListenAddress = "tcp://" + <-laddrReturner
|
||||
config.P2P.PersistentPeers = <-laddrReturner
|
||||
|
||||
var pv tmTypes.PrivValidator
|
||||
if _, err := os.Stat(config.PrivValidatorKeyFile()); err == nil {
|
||||
pv = privval.LoadFilePV(
|
||||
config.PrivValidatorKeyFile(),
|
||||
config.PrivValidatorStateFile(),
|
||||
)
|
||||
} else {
|
||||
fmt.Println("⚠️ priv_validator_key.json not found. Node will run as non-validator.")
|
||||
pv = tmTypes.NewMockPV()
|
||||
}
|
||||
|
||||
nodeKey, err := p2p.LoadNodeKey(config.NodeKeyFile())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("load node key: %w", err)
|
||||
}
|
||||
|
||||
clientCreator := proxy.NewLocalClientCreator(app)
|
||||
logger := log.NewTMLogger(log.NewSyncWriter(os.Stdout))
|
||||
|
||||
return nm.NewNode(
|
||||
config,
|
||||
pv,
|
||||
nodeKey,
|
||||
clientCreator,
|
||||
nm.DefaultGenesisDocProviderFunc(config),
|
||||
nm.DefaultDBProvider,
|
||||
nm.DefaultMetricsProvider(config.Instrumentation),
|
||||
logger,
|
||||
)
|
||||
}
|
||||
cli.Execute()
|
||||
}
|
||||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
autoPeering "lbc/autopeering"
|
||||
"lbc/autoPeering"
|
||||
ppp "lbc/persistentpeersparser"
|
||||
"net"
|
||||
"os"
|
||||
|
|
@ -18,7 +18,6 @@ import (
|
|||
|
||||
"github.com/gologme/log"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/things-go/go-socks5"
|
||||
|
||||
"github.com/yggdrasil-network/yggdrasil-go/src/admin"
|
||||
yggConfig "github.com/yggdrasil-network/yggdrasil-go/src/config"
|
||||
|
|
@ -69,12 +68,20 @@ func GetPublicKey(keyPath string) (ed25519.PublicKey, error) {
|
|||
return privateKey.Public().(ed25519.PublicKey), nil
|
||||
}
|
||||
|
||||
func GetYggdrasilAddress(config *viper.Viper) string {
|
||||
func GetYggdrasilAddress(config *viper.Viper, ch chan string) string {
|
||||
var remoteTcp types.TCPRemoteMappings
|
||||
ygg := config.Sub("yggdrasil")
|
||||
if ygg == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
laddr := config.Sub("p2p").GetString("laddr")
|
||||
remoteTcp.Set(laddr)
|
||||
if ch != nil {
|
||||
ch <- remoteTcp[0].Mapped.String()
|
||||
ch <- ""
|
||||
}
|
||||
|
||||
cfg := yggConfig.GenerateConfig()
|
||||
|
||||
cfg.AdminListen = ygg.GetString("admin_listen")
|
||||
|
|
@ -175,6 +182,8 @@ func Yggdrasil(config *viper.Viper, ch chan string) {
|
|||
cfg.Peers = ygg.GetStringSlice("peers")
|
||||
}
|
||||
|
||||
logger.Infof("Yggdrasil peers: %s", cfg.Peers)
|
||||
|
||||
cfg.AllowedPublicKeys = ygg.GetStringSlice("allowed-public-keys")
|
||||
cfg.PrivateKeyPath = ygg.GetString("private-key-file")
|
||||
|
||||
|
|
@ -265,62 +274,6 @@ func Yggdrasil(config *viper.Viper, ch chan string) {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
// Create SOCKS server
|
||||
{
|
||||
if socks != "" {
|
||||
socksOptions := []socks5.Option{
|
||||
socks5.WithDial(s.DialContext),
|
||||
}
|
||||
if logger.GetLevel("debug") {
|
||||
socksOptions = append(socksOptions, socks5.WithLogger(logger))
|
||||
}
|
||||
server := socks5.NewServer(socksOptions...)
|
||||
if strings.Contains(socks, ":") {
|
||||
logger.Infof("Starting SOCKS server on %s", socks)
|
||||
n.socks5Tcp, err = net.Listen("tcp", socks)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
go func() {
|
||||
err := server.Serve(n.socks5Tcp)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
logger.Infof("Starting SOCKS server with socket file %s", socks)
|
||||
n.socks5Unix, err = net.Listen("unix", socks)
|
||||
if err != nil {
|
||||
// If address in use, try connecting to
|
||||
// the socket to see if other yggstack
|
||||
// instance is listening on it
|
||||
|
||||
if isErrorAddressAlreadyInUse(err) {
|
||||
_, err = net.Dial("unix", socks)
|
||||
if err != nil {
|
||||
// Unlink dead socket if not connected
|
||||
err = os.RemoveAll(socks)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
log.Errorf("Another yggstack instance is listening on socket '%s'", socks)
|
||||
panic(err)
|
||||
}
|
||||
} else {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
go func() {
|
||||
err := server.Serve(n.socks5Unix)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Create local TCP mappings (forwarding connections from local port
|
||||
// to remote Yggdrasil node)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue