ceremonyclient/node/main.go
Cassandra Heart 9e1d07d1a0
Squashed commit of the following:
commit d05a4d5f688dbd09900ceccdcc5f8109dd0671c2
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Wed Jun 12 00:50:16 2024 -0500

    merge

commit db57ff1f191f9dedc87ca77da1c71244dd2325bd
Merge: 7b43494 2e3279a
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Wed Jun 12 00:49:32 2024 -0500

    Merge branch 'v1.4.19' into not-release

commit 7b43494246e28152b46710c8c9821429d4231f7e
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Wed Jun 12 00:49:13 2024 -0500

    pull from release site

commit 2e3279ac930ac630d9ca2b26cf4f3232abe79823
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 06:31:02 2024 -0500

    remove binaries

commit 2768a8778b3860c5736352c8aa950e3496a46e56
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 06:24:44 2024 -0500

    signatory #8 added

commit 6a944628575ccadd17c9f9f4a11a49c032fa0c1d
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 06:08:26 2024 -0500

    signatory #6 added

commit b401fb65e5ddbe0340fe85aab1182d6120a4e161
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 05:39:03 2024 -0500

    signatory #3 added

commit e5700913c0f6246fb607bcd3e219c257cb4a80e9
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 05:31:24 2024 -0500

    signatory #15 added

commit 9b1da6c03e517135bfcd59226f900adab42f3687
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 05:23:02 2024 -0500

    signatories #4 and #16 added

commit 9c97d1bbc399a070ac21b35ed9b1af127fa4c7ea
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 04:59:27 2024 -0500

    signatories #1 and #2 added

commit 905e3f78a8121eade1c331ae910ed25dd534f27a
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 04:40:32 2024 -0500

    build, binaries, signatory #13

commit ebfb57bc29d9ed1fb25d0dd100e38709354b3d84
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Sat Jun 8 03:38:53 2024 -0500

    tests pass, let's go

commit 5d4612c6c624c3dc18f9a5657936034ac9d9d8dd
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Fri Jun 7 03:53:15 2024 -0500

    update version info + readme

commit 6b0dd69e930d01b98acb8d7b56bb5d572e1a4324
Merge: 090d630 859221b
Author: Cassie Heart <cassandra@quilibrium.com>
Date:   Fri Jun 7 08:25:16 2024 +0000

    Merge branch 'feat-data-worker-direct-config' into 'v1.4.19'

    feat: support detached configuration mode for data workers

    See merge request quilibrium/ceremonyclient!7

commit 859221b179ab2631fa474be2494259afaaa6bd51
Author: Cassandra Heart <cassandra@quilibrium.com>
Date:   Fri Jun 7 03:24:22 2024 -0500

    feat: support detached configuration mode for data workers

commit 090d6301d44a2aa88886120783cd5a6e537aa6d1
Merge: 62db30c d1cae94
Author: Cassie Heart <cassandra@quilibrium.com>
Date:   Fri Jun 7 06:25:43 2024 +0000

    Merge branch 'feat-go-1-22' into 'v1.4.19'

    feat: go 1.22 support

    See merge request quilibrium/ceremonyclient!6

commit d1cae942165f4871f8051e266722c0ca717780cb
Author: Cassie Heart <cassandra@quilibrium.com>
Date:   Fri Jun 7 06:25:43 2024 +0000

    feat: go 1.22 support

commit 62db30c54f9258c92113c6664ce817670a339083
Merge: 0cbc0d0 f36cea3
Author: Cassie Heart <cassandra@quilibrium.com>
Date:   Fri Jun 7 03:52:17 2024 +0000

    Merge branch 'rust-vdf' into 'v1.4.19'

    Switch to Rust VDF

    See merge request quilibrium/ceremonyclient!2

commit f36cea323bfe5e56f519f59f9a0cce35f0f8b6ab
Author: Agost Biro <agostbiro@gmail.com>
Date:   Fri Jun 7 03:52:16 2024 +0000

    Switch to Rust VDF

commit 0cbc0d0d319713e20ca7f48588c4153833e58429
Merge: 986e12c 0c48a83
Author: Cassie Heart <cassandra@quilibrium.com>
Date:   Fri Jun 7 00:50:15 2024 +0000

    Merge branch 'release_image' into 'v1.4.19'

    create docker image based on release binaries

    See merge request quilibrium/ceremonyclient!4

commit 0c48a83bb5751abf7c8c0ff188bfdc2130631e78
Author: Marius Scurtescu <marius.scurtescu@gmail.com>
Date:   Fri Jun 7 00:50:15 2024 +0000

    create docker image based on release binaries

commit 986e12c88bb2d2b412b59f7db1ae39f828304dbe
Merge: 58456c1 a3ef5c6
Author: Cassie Heart <cassandra@quilibrium.com>
Date:   Wed Jun 5 22:01:37 2024 +0000

    Merge branch 'signature_check' into 'v1.4.19'

    add default of signature check from QUILIBRIUM_SIGNATURE_CHECK env var

    See merge request quilibrium/ceremonyclient!1

commit a3ef5c6af2d5de107d01c45a62d7324165e2551b
Author: Marius Scurtescu <marius.scurtescu@gmail.com>
Date:   Wed Jun 5 14:37:50 2024 -0700

    add default of signature check from QUILIBRIUM_SIGNATURE_CHECK env var
2024-06-12 00:51:16 -05:00

944 lines
25 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//go:build !js && !wasm
package main
import (
"bytes"
"crypto/rand"
"encoding/binary"
"encoding/hex"
"flag"
"fmt"
"io/fs"
"log"
"math/big"
"os"
"os/exec"
"os/signal"
"path/filepath"
"runtime"
rdebug "runtime/debug"
"runtime/pprof"
"strconv"
"strings"
"syscall"
"time"
"go.uber.org/zap"
"golang.org/x/crypto/sha3"
"google.golang.org/protobuf/proto"
"source.quilibrium.com/quilibrium/monorepo/node/execution/intrinsics/ceremony/application"
"source.quilibrium.com/quilibrium/monorepo/node/p2p"
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
"source.quilibrium.com/quilibrium/monorepo/node/store"
"source.quilibrium.com/quilibrium/monorepo/node/utils"
"github.com/cloudflare/circl/sign/ed448"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/pbnjay/memory"
"github.com/pkg/errors"
"source.quilibrium.com/quilibrium/monorepo/node/app"
"source.quilibrium.com/quilibrium/monorepo/node/config"
qcrypto "source.quilibrium.com/quilibrium/monorepo/node/crypto"
"source.quilibrium.com/quilibrium/monorepo/node/crypto/kzg"
"source.quilibrium.com/quilibrium/monorepo/node/rpc"
)
var (
configDirectory = flag.String(
"config",
filepath.Join(".", ".config"),
"the configuration directory",
)
balance = flag.Bool(
"balance",
false,
"print the node's confirmed token balance to stdout and exit",
)
dbConsole = flag.Bool(
"db-console",
false,
"starts the node in database console mode",
)
importPrivKey = flag.String(
"import-priv-key",
"",
"creates a new config using a specific key from the phase one ceremony",
)
peerId = flag.Bool(
"peer-id",
false,
"print the peer id to stdout from the config and exit",
)
cpuprofile = flag.String(
"cpuprofile",
"",
"write cpu profile to file",
)
memprofile = flag.String(
"memprofile",
"",
"write memory profile after 20m to this file",
)
nodeInfo = flag.Bool(
"node-info",
false,
"print node related information",
)
debug = flag.Bool(
"debug",
false,
"sets log output to debug (verbose)",
)
dhtOnly = flag.Bool(
"dht-only",
false,
"sets a node to run strictly as a dht bootstrap peer (not full node)",
)
network = flag.Uint(
"network",
0,
"sets the active network for the node (mainnet = 0, primary testnet = 1)",
)
signatureCheck = flag.Bool(
"signature-check",
signatureCheckDefault(),
"enables or disables signature validation (default true or value of QUILIBRIUM_SIGNATURE_CHECK env var)",
)
core = flag.Int(
"core",
0,
"specifies the core of the process (defaults to zero, the initial launcher)",
)
parentProcess = flag.Int(
"parent-process",
0,
"specifies the parent process pid for a data worker",
)
)
var signatories = []string{
"b1214da7f355f5a9edb7bcc23d403bdf789f070cca10db2b4cadc22f2d837afb650944853e35d5f42ef3c4105b802b144b4077d5d3253e4100",
"de4cfe7083104bfe32f0d4082fa0200464d8b10804a811653eedda376efcad64dd222f0f0ceb0b8ae58abe830d7a7e3f3b2d79d691318daa00",
"540237a35e124882d6b64e7bb5718273fa338e553f772b77fe90570e45303762b34131bdcb6c0b9f2cf9e393d9c7e0f546eeab0bcbbd881680",
"fbe4166e37f93f90d2ebf06305315ae11b37e501d09596f8bde11ba9d343034fbca80f252205aa2f582a512a72ad293df371baa582da072900",
"4160572e493e1bf15c44e055b11bf75230c76c7d2c67b48066770ab03dfd5ed34c97b9a431ec18578c83a0df9250b8362c38068650e8b01400",
"45170b626884b85d61ae109f2aa9b0e1ecc18b181508431ea6308f3869f2adae49da9799a0a594eaa4ef3ad492518fb1729decd44169d40d00",
"92cd8ee5362f3ae274a75ab9471024dbc144bff441ed8af7d19750ac512ff51e40e7f7b01e4f96b6345dd58878565948c3eb52c53f250b5080",
"001a4cbfce5d9aeb7e20665b0d236721b228a32f0baee62ffa77f45b82ecaf577e8a38b7ef91fcf7d2d2d2b504f085461398d30b24abb1d700",
"65b835071731c6e785bb2d107c7d85d8a537d79c435c3f42bb2f87027f93f858d7b37c598cef267a5db46e345f7a6f81969b465686657d1e00",
"4507626f7164e7d8c304c07ff8d2e23c113fe108b221d2e60672f4d07750345815e2b4b3cc3df4d3466bf2f669c35c3172e06511270612ab00",
"4fb2537345e46be3d5f96340c1441007501702dd5bfaf6dbf6943bbefceca8fb2b94ec0a8a1a2f49850fbe1d10244889a4f40abfa9e0c9e000",
"57be2861faf0fffcbfd122c85c77010dce8f213030905781b85b6f345d912c7b5ace17797d9810899dfb8d13e7c8369595740725ab3dd5bd00",
"61628beef8f6964466fd078d6a2b90a397ab0777a14b9728227fd19f36752f9451b1a8d780740a0b9a8ce3df5f89ca7b9ff17de9274a270980",
"5547afc71b02821e2f5bfdd30fbe1374c3853898deff20a1b5cc729b8e81670fbbb9d1e917f85d153ea4b26bbf6f9c546dc1b64b9916608d80",
"81d63a45f068629f568de812f18be5807bfe828a830097f09cf02330d6acd35e3607401df3fda08b03b68ea6e68afd506b23506b11e87a0f80",
"6e2872f73c4868c4286bef7bfe2f5479a41c42f4e07505efa4883c7950c740252e0eea78eef10c584b19b1dcda01f7767d3135d07c33244100",
"a114b061f8d35e3f3497c8c43d83ba6b4af67aa7b39b743b1b0a35f2d66110b5051dd3d86f69b57122a35b64e624b8180bee63b6152fce4280",
}
func signatureCheckDefault() bool {
envVarValue, envVarExists := os.LookupEnv("QUILIBRIUM_SIGNATURE_CHECK")
if envVarExists {
def, err := strconv.ParseBool(envVarValue)
if err == nil {
return def
} else {
fmt.Println("Invalid environment variable QUILIBRIUM_SIGNATURE_CHECK, must be 'true' or 'false'. Got: " + envVarValue)
}
}
return true
}
func main() {
flag.Parse()
if *signatureCheck {
if runtime.GOOS == "windows" {
fmt.Println("Signature check not available for windows yet, skipping...")
} else {
ex, err := os.Executable()
if err != nil {
panic(err)
}
b, err := os.ReadFile(ex)
if err != nil {
fmt.Println(
"Error encountered during signature check are you running this " +
"from source? (use --signature-check=false)",
)
panic(err)
}
checksum := sha3.Sum256(b)
digest, err := os.ReadFile(ex + ".dgst")
if err != nil {
fmt.Println("Digest file not found")
os.Exit(1)
}
parts := strings.Split(string(digest), " ")
if len(parts) != 2 {
fmt.Println("Invalid digest file format")
os.Exit(1)
}
digestBytes, err := hex.DecodeString(parts[1][:64])
if err != nil {
fmt.Println("Invalid digest file format")
os.Exit(1)
}
if !bytes.Equal(checksum[:], digestBytes) {
fmt.Println("Invalid digest for node")
os.Exit(1)
}
count := 0
for i := 1; i <= len(signatories); i++ {
signatureFile := fmt.Sprintf(ex+".dgst.sig.%d", i)
sig, err := os.ReadFile(signatureFile)
if err != nil {
continue
}
pubkey, _ := hex.DecodeString(signatories[i-1])
if !ed448.Verify(pubkey, digest, sig, "") {
fmt.Printf("Failed signature check for signatory #%d\n", i)
os.Exit(1)
}
count++
}
if count < len(signatories)/2 {
fmt.Printf("Quorum on signatures not met")
os.Exit(1)
}
fmt.Println("Signature check passed")
}
} else {
fmt.Println("Signature check disabled, skipping...")
}
if *memprofile != "" {
go func() {
for {
time.Sleep(5 * time.Minute)
f, err := os.Create(*memprofile)
if err != nil {
log.Fatal(err)
}
pprof.WriteHeapProfile(f)
f.Close()
}
}()
}
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
}
pprof.StartCPUProfile(f)
defer pprof.StopCPUProfile()
}
if *balance {
config, err := config.LoadConfig(*configDirectory, "")
if err != nil {
panic(err)
}
printBalance(config)
return
}
if *peerId {
config, err := config.LoadConfig(*configDirectory, "")
if err != nil {
panic(err)
}
printPeerID(config.P2P)
return
}
if *importPrivKey != "" {
config, err := config.LoadConfig(*configDirectory, *importPrivKey)
if err != nil {
panic(err)
}
printPeerID(config.P2P)
fmt.Println("Import completed, you are ready for the launch.")
return
}
if *nodeInfo {
config, err := config.LoadConfig(*configDirectory, "")
if err != nil {
panic(err)
}
printNodeInfo(config)
return
}
if !*dbConsole && *core == 0 {
printLogo()
printVersion()
fmt.Println(" ")
}
nodeConfig, err := config.LoadConfig(*configDirectory, "")
if err != nil {
panic(err)
}
if *network != 0 {
if nodeConfig.P2P.BootstrapPeers[0] == config.BootstrapPeers[0] {
fmt.Println(
"Node has specified to run outside of mainnet but is still " +
"using default bootstrap list. This will fail. Exiting.",
)
os.Exit(1)
}
nodeConfig.Engine.GenesisSeed = fmt.Sprintf(
"%02x%s",
byte(*network),
nodeConfig.Engine.GenesisSeed,
)
nodeConfig.P2P.Network = uint8(*network)
fmt.Println(
"Node is operating outside of mainnet be sure you intended to do this.",
)
}
clearIfTestData(*configDirectory, nodeConfig)
if *dbConsole {
console, err := app.NewDBConsole(nodeConfig)
if err != nil {
panic(err)
}
console.Run()
return
}
if *dhtOnly {
done := make(chan os.Signal, 1)
signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
dht, err := app.NewDHTNode(nodeConfig)
if err != nil {
panic(err)
}
go func() {
dht.Start()
}()
<-done
dht.Stop()
return
}
if *core != 0 {
runtime.GOMAXPROCS(1)
rdebug.SetGCPercent(9999)
if nodeConfig.Engine.DataWorkerMemoryLimit == 0 {
nodeConfig.Engine.DataWorkerMemoryLimit = 1792 * 1024 * 1024 // 1.75GiB
}
rdebug.SetMemoryLimit(nodeConfig.Engine.DataWorkerMemoryLimit)
if nodeConfig.Engine.DataWorkerBaseListenMultiaddr == "" {
nodeConfig.Engine.DataWorkerBaseListenMultiaddr = "/ip4/127.0.0.1/tcp/%d"
}
if nodeConfig.Engine.DataWorkerBaseListenPort == 0 {
nodeConfig.Engine.DataWorkerBaseListenPort = 40000
}
if *parentProcess == 0 && len(nodeConfig.Engine.DataWorkerMultiaddrs) == 0 {
panic("parent process pid not specified")
}
l, err := zap.NewProduction()
if err != nil {
panic(err)
}
rpcMultiaddr := fmt.Sprintf(
nodeConfig.Engine.DataWorkerBaseListenMultiaddr,
int(nodeConfig.Engine.DataWorkerBaseListenPort)+*core-1,
)
if len(nodeConfig.Engine.DataWorkerMultiaddrs) != 0 {
rpcMultiaddr = nodeConfig.Engine.DataWorkerMultiaddrs[*core-1]
}
srv, err := rpc.NewDataWorkerIPCServer(
rpcMultiaddr,
l,
uint32(*core)-1,
qcrypto.NewWesolowskiFrameProver(l),
*parentProcess,
)
if err != nil {
panic(err)
}
err = srv.Start()
if err != nil {
panic(err)
}
return
}
fmt.Println("Loading ceremony state and starting node...")
go spawnDataWorkers(nodeConfig)
kzg.Init()
report := RunSelfTestIfNeeded(*configDirectory, nodeConfig)
RunMigrationIfNeeded(*configDirectory, nodeConfig)
done := make(chan os.Signal, 1)
signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
var node *app.Node
if *debug {
node, err = app.NewDebugNode(nodeConfig, report)
} else {
node, err = app.NewNode(nodeConfig, report)
}
if err != nil {
panic(err)
}
repair(*configDirectory, node)
if nodeConfig.ListenGRPCMultiaddr != "" {
srv, err := rpc.NewRPCServer(
nodeConfig.ListenGRPCMultiaddr,
nodeConfig.ListenRestMultiaddr,
node.GetLogger(),
node.GetDataProofStore(),
node.GetClockStore(),
node.GetKeyManager(),
node.GetPubSub(),
node.GetMasterClock(),
node.GetExecutionEngines(),
)
if err != nil {
panic(err)
}
go func() {
err := srv.Start()
if err != nil {
panic(err)
}
}()
}
node.Start()
<-done
stopDataWorkers()
node.Stop()
}
var dataWorkers []*exec.Cmd
func spawnDataWorkers(nodeConfig *config.Config) {
if len(nodeConfig.Engine.DataWorkerMultiaddrs) != 0 {
fmt.Println(
"Data workers configured by multiaddr, be sure these are running...",
)
return
}
process, err := os.Executable()
if err != nil {
panic(err)
}
cores := runtime.GOMAXPROCS(0)
dataWorkers = make([]*exec.Cmd, cores-1)
fmt.Printf("Spawning %d data workers...\n", cores-1)
for i := 1; i <= cores-1; i++ {
i := i
go func() {
args := []string{
fmt.Sprintf("--core=%d", i),
fmt.Sprintf("--parent-process=%d", os.Getpid()),
}
args = append(args, os.Args[1:]...)
cmd := exec.Command(process, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stdout
err := cmd.Start()
if err != nil {
panic(err)
}
dataWorkers[i-1] = cmd
}()
}
}
func stopDataWorkers() {
for i := 0; i < len(dataWorkers); i++ {
err := dataWorkers[i].Process.Signal(os.Kill)
if err != nil {
fmt.Printf(
"fatal: unable to kill worker with pid %d, please kill this process!\n",
dataWorkers[i].Process.Pid,
)
}
}
}
// Reintroduce at a later date
func RunCompaction(clockStore *store.PebbleClockStore) {
intrinsicFilter := append(
p2p.GetBloomFilter(application.CEREMONY_ADDRESS, 256, 3),
p2p.GetBloomFilterIndices(application.CEREMONY_ADDRESS, 65536, 24)...,
)
fmt.Println("running compaction")
if err := clockStore.Compact(
intrinsicFilter,
); err != nil {
if errors.Is(err, store.ErrNotFound) {
fmt.Println("missing compaction data, skipping for now", zap.Error(err))
} else {
panic(err)
}
}
fmt.Println("compaction complete")
}
func RunMigrationIfNeeded(
configDir string,
nodeConfig *config.Config,
) {
shouldMigrate := false
migrationInfo := []byte{0x00, 0x00, 0x00}
_, err := os.Stat(filepath.Join(configDir, "MIGRATIONS"))
if err != nil && os.IsNotExist(err) {
fmt.Println("Migrations file not found, will perform migration...")
shouldMigrate = true
}
if !shouldMigrate {
migrationInfo, err = os.ReadFile(filepath.Join(configDir, "MIGRATIONS"))
if err != nil {
panic(err)
}
if len(migrationInfo) < 3 ||
!bytes.Equal(migrationInfo, []byte{0x01, 0x04, 0x013}) {
fmt.Println("Migrations file outdated, will perform migration...")
shouldMigrate = true
}
}
// If subsequent migrations arise, we will need to distinguish by version
if shouldMigrate {
fmt.Println("Running migration...")
// Easiest migration in the world.
err := os.RemoveAll(filepath.Join(configDir, "store"))
if err != nil {
fmt.Println("ERROR: Could not remove store, please be sure to do this before restarting the node.")
panic(err)
}
err = os.WriteFile(
filepath.Join(configDir, "MIGRATIONS"),
[]byte{0x01, 0x04, 0x13},
fs.FileMode(0600),
)
if err != nil {
fmt.Println("ERROR: Could not save migration file.")
panic(err)
}
fmt.Println("Migration completed.")
}
}
func RunSelfTestIfNeeded(
configDir string,
nodeConfig *config.Config,
) *protobufs.SelfTestReport {
logger, _ := zap.NewProduction()
cores := runtime.GOMAXPROCS(0)
if len(nodeConfig.Engine.DataWorkerMultiaddrs) != 0 {
cores = len(nodeConfig.Engine.DataWorkerMultiaddrs) + 1
}
memory := memory.TotalMemory()
d, err := os.Stat(filepath.Join(configDir, "store"))
if d == nil {
err := os.Mkdir(filepath.Join(configDir, "store"), 0755)
if err != nil {
panic(err)
}
}
f, err := os.Stat(filepath.Join(configDir, "SELF_TEST"))
if f != nil {
if f.Size() != 0 {
report := &protobufs.SelfTestReport{}
selfTestBytes, err := os.ReadFile(filepath.Join(configDir, "SELF_TEST"))
if err != nil {
panic(err)
}
err = proto.Unmarshal(selfTestBytes, report)
if err != nil {
panic(err)
}
if report.Cores == uint32(cores) &&
binary.BigEndian.Uint64(report.Memory) == memory {
return report
}
}
logger.Info("no self-test report found, generating")
}
report := &protobufs.SelfTestReport{}
difficulty := nodeConfig.Engine.Difficulty
if difficulty == 0 || difficulty == 10000 {
difficulty = 100000
}
report.Difficulty = difficulty
frameProver := qcrypto.NewWesolowskiFrameProver(logger)
logger.Info("generating difficulty metric")
start := time.Now().UnixMilli()
_, err = frameProver.ProveMasterClockFrame(
&protobufs.ClockFrame{
Filter: []byte{0x00},
FrameNumber: 0,
Timestamp: 0,
Difficulty: difficulty,
ParentSelector: []byte{0x00},
Input: make([]byte, 516),
Output: make([]byte, 516),
},
0,
difficulty,
)
if err != nil {
panic(err)
}
end := time.Now().UnixMilli()
report.DifficultyMetric = end - start
logger.Info("generating entropy for commit/proof sizes")
p16bytes := make([]byte, 1024)
p128bytes := make([]byte, 8192)
p1024bytes := make([]byte, 65536)
p65536bytes := make([]byte, 4194304)
rand.Read(p16bytes)
rand.Read(p128bytes)
rand.Read(p1024bytes)
rand.Read(p65536bytes)
kzgProver := kzg.DefaultKZGProver()
p16, _ := kzgProver.BytesToPolynomial(p16bytes)
p128, _ := kzgProver.BytesToPolynomial(p128bytes)
p1024, _ := kzgProver.BytesToPolynomial(p1024bytes)
p65536, _ := kzgProver.BytesToPolynomial(p65536bytes)
logger.Info("generating 16 degree commitment metric")
start = time.Now().UnixMilli()
c16, err := kzgProver.Commit(p16)
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Commit_16Metric = end - start
logger.Info("generating 128 degree commitment metric")
start = time.Now().UnixMilli()
c128, err := kzgProver.Commit(p128)
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Commit_128Metric = end - start
logger.Info("generating 1024 degree commitment metric")
start = time.Now().UnixMilli()
c1024, err := kzgProver.Commit(p1024)
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Commit_1024Metric = end - start
logger.Info("generating 65536 degree commitment metric")
start = time.Now().UnixMilli()
c65536, err := kzgProver.Commit(p65536)
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Commit_65536Metric = end - start
logger.Info("generating 16 degree proof metric")
start = time.Now().UnixMilli()
_, err = kzgProver.Prove(p16, c16, p16[0])
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Proof_16Metric = end - start
logger.Info("generating 128 degree proof metric")
start = time.Now().UnixMilli()
_, err = kzgProver.Prove(p128, c128, p128[0])
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Proof_128Metric = end - start
logger.Info("generating 1024 degree proof metric")
start = time.Now().UnixMilli()
_, err = kzgProver.Prove(p1024, c1024, p1024[0])
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Proof_1024Metric = end - start
logger.Info("generating 65536 degree proof metric")
start = time.Now().UnixMilli()
_, err = kzgProver.Prove(p65536, c65536, p65536[0])
if err != nil {
panic(err)
}
end = time.Now().UnixMilli()
report.Proof_65536Metric = end - start
report.Cores = uint32(cores)
report.Memory = binary.BigEndian.AppendUint64([]byte{}, memory)
disk := utils.GetDiskSpace(nodeConfig.DB.Path)
report.Storage = binary.BigEndian.AppendUint64([]byte{}, disk)
logger.Info("writing report")
// tag: dusk capabilities report in v1.5
reportBytes, err := proto.Marshal(report)
if err != nil {
panic(err)
}
err = os.WriteFile(
filepath.Join(configDir, "SELF_TEST"),
reportBytes,
fs.FileMode(0600),
)
if err != nil {
panic(err)
}
return report
}
func clearIfTestData(configDir string, nodeConfig *config.Config) {
_, err := os.Stat(filepath.Join(configDir, "RELEASE_VERSION"))
if os.IsNotExist(err) {
fmt.Println("Clearing test data...")
err := os.RemoveAll(nodeConfig.DB.Path)
if err != nil {
panic(err)
}
versionFile, err := os.OpenFile(
filepath.Join(configDir, "RELEASE_VERSION"),
os.O_CREATE|os.O_RDWR,
fs.FileMode(0600),
)
if err != nil {
panic(err)
}
_, err = versionFile.Write([]byte{0x01, 0x00, 0x00})
if err != nil {
panic(err)
}
err = versionFile.Close()
if err != nil {
panic(err)
}
}
}
func repair(configDir string, node *app.Node) {
_, err := os.Stat(filepath.Join(configDir, "REPAIR"))
if os.IsNotExist(err) {
node.RunRepair()
repairFile, err := os.OpenFile(
filepath.Join(configDir, "REPAIR"),
os.O_CREATE|os.O_RDWR,
fs.FileMode(0600),
)
if err != nil {
panic(err)
}
_, err = repairFile.Write([]byte{0x00, 0x00, 0x01})
if err != nil {
panic(err)
}
err = repairFile.Close()
if err != nil {
panic(err)
}
}
}
func printBalance(config *config.Config) {
if config.ListenGRPCMultiaddr == "" {
_, _ = fmt.Fprintf(os.Stderr, "gRPC Not Enabled, Please Configure\n")
os.Exit(1)
}
conn, err := app.ConnectToNode(config)
if err != nil {
panic(err)
}
defer conn.Close()
client := protobufs.NewNodeServiceClient(conn)
balance, err := app.FetchTokenBalance(client)
if err != nil {
panic(err)
}
// fmt.Println("Owned balance:", balance.Owned, "QUIL")
conversionFactor, _ := new(big.Int).SetString("1DCD65000", 16)
r := new(big.Rat).SetFrac(balance.UnconfirmedOwned, conversionFactor)
fmt.Println("Note: Balance is strictly rewards earned with 1.4.19+, check https://www.quilibrium.com/rewards for more info about previous rewards.")
fmt.Println("Unclaimed balance:", r.FloatString(12), "QUIL")
}
func printPeerID(p2pConfig *config.P2PConfig) {
peerPrivKey, err := hex.DecodeString(p2pConfig.PeerPrivKey)
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
privKey, err := crypto.UnmarshalEd448PrivateKey(peerPrivKey)
if err != nil {
panic(errors.Wrap(err, "error unmarshaling peerkey"))
}
pub := privKey.GetPublic()
id, err := peer.IDFromPublicKey(pub)
if err != nil {
panic(errors.Wrap(err, "error getting peer id"))
}
fmt.Println("Peer ID: " + id.String())
}
func printNodeInfo(cfg *config.Config) {
if cfg.ListenGRPCMultiaddr == "" {
_, _ = fmt.Fprintf(os.Stderr, "gRPC Not Enabled, Please Configure\n")
os.Exit(1)
}
printPeerID(cfg.P2P)
conn, err := app.ConnectToNode(cfg)
if err != nil {
panic(err)
}
defer conn.Close()
client := protobufs.NewNodeServiceClient(conn)
nodeInfo, err := app.FetchNodeInfo(client)
if err != nil {
panic(err)
}
fmt.Println("Version: " + config.FormatVersion(nodeInfo.Version))
fmt.Println("Max Frame: " + strconv.FormatUint(nodeInfo.GetMaxFrame(), 10))
fmt.Println("Peer Score: " + strconv.FormatUint(nodeInfo.GetPeerScore(), 10))
printBalance(cfg)
}
func printLogo() {
fmt.Println(" ..-------..")
fmt.Println(" ..---'''' ''''---..")
fmt.Println(" .---'' ''---.")
fmt.Println(" .-' '-.")
fmt.Println(" ..-' ..--''''''''''''''--.. '-..")
fmt.Println(" .' .--'' ''--. ''.")
fmt.Println(" .'' ..-' ''-. '.")
fmt.Println(" ' ' ''. '.")
fmt.Println(" '' .'' '. '")
fmt.Println(" ' '' '. '")
fmt.Println(" ' ' ########## . '")
fmt.Println(" ' ' ############## ' '")
fmt.Println(" ' ' ############## ' '")
fmt.Println(" ' ' ############## ' '")
fmt.Println("' ' ########## ' '")
fmt.Println("' ' ' '")
fmt.Println("' ' ' '")
fmt.Println("' ' ####### ####### ' '")
fmt.Println("' ' &######################### ' '")
fmt.Println("' ' ##############% ############## ' '")
fmt.Println(" ' ' &############## ############### ' '")
fmt.Println(" ' ' ############### ##############% '. '")
fmt.Println(" ' '. ########## ############### '-. '")
fmt.Println(" '. . ##### ##############% '-.'")
fmt.Println(" ' '. ###############")
fmt.Println(" '. '.. ##############%")
fmt.Println(" '. '-. ###############")
fmt.Println(" '-. ''-.. .. ##############%")
fmt.Println(" '-. ''---............----' '. ###############")
fmt.Println(" '-.. '. ############")
fmt.Println(" ''-.. ..' ########")
fmt.Println(" ''---.. ...---'' ##")
fmt.Println(" ''----------''")
}
func printVersion() {
patch := config.GetPatchNumber()
patchString := ""
if patch != 0x00 {
patchString = fmt.Sprintf("-p%d", patch)
}
fmt.Println(" ")
fmt.Println(" Quilibrium Node - v" + config.GetVersionString() + patchString + " Betelgeuse")
}