add tari-gbt(rust)
This commit is contained in:
parent
953a76439a
commit
8cc56a489e
|
@ -1,4 +1,4 @@
|
|||
# tari-server
|
||||
# m2pool-mining-core
|
||||
|
||||
一个基于 Go 的轻量化挖矿池服务内核,包含 Job 生成/分发与 Stratum 矿工端接入两大模块:
|
||||
- gbt:区块模板生成与同步(GetBlockTemplate/Job Producer),通过 ZMQ 向服务端发布新任务
|
||||
|
|
3
go.mod
3
go.mod
|
@ -6,16 +6,15 @@ toolchain go1.23.1
|
|||
|
||||
require (
|
||||
github.com/btcsuite/btcd v0.24.2
|
||||
github.com/golang/protobuf v1.5.4
|
||||
github.com/zeromq/goczmq v4.1.0+incompatible
|
||||
go.uber.org/zap v1.27.0
|
||||
google.golang.org/protobuf v1.36.6
|
||||
)
|
||||
|
||||
require (
|
||||
golang.org/x/net v0.41.0 // indirect
|
||||
golang.org/x/text v0.26.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
@ -12,9 +12,8 @@ import (
|
|||
|
||||
//"pool/internal/cache"
|
||||
"pool/internal/gbt/coin"
|
||||
"pool/internal/gbt/monero"
|
||||
monero_rpc "pool/internal/gbt/monero/rpc"
|
||||
"pool/internal/gbt/tari"
|
||||
"pool/internal/gbt/tari/sha3x"
|
||||
"pool/internal/utility"
|
||||
|
||||
"os"
|
||||
|
@ -49,15 +48,6 @@ func InitClient(gbt *coin.GbtContext) error {
|
|||
rpcClient := monero_rpc.NewHttpClient(url, 10*time.Second)
|
||||
gbt.MoneroClinet = rpcClient
|
||||
gbt.MoneroAddr = gbt.Config.Rpc.User
|
||||
case "sha3x":
|
||||
url := gbt.Config.Rpc.Host
|
||||
grpcClient, err := tari.NewBaseNodeClient(url)
|
||||
if err != nil {
|
||||
fmt.Println("tari创建grpc服务失败:", err)
|
||||
return err
|
||||
}
|
||||
gbt.TariClient = grpcClient
|
||||
gbt.TariAddr = gbt.Config.Rpc.Host
|
||||
default:
|
||||
var config rpcclient.ConnConfig
|
||||
if gbt.Config.Rpc.Type == "testnet" {
|
||||
|
@ -145,8 +135,8 @@ type coinobj struct {
|
|||
|
||||
var coinobjs = []coinobj{
|
||||
// {Coin: "nexa", Init: nexa.Init, Start: nexa.Start, Stop: nexa.Stop},
|
||||
// {Coin: "monero", Init: monero.Init, Start: monero.Start, Stop: monero.Stop},
|
||||
{Coin: "sha3x", Init: sha3x.Init, Start: sha3x.Start, Stop: sha3x.Stop},
|
||||
{Coin: "monero", Init: monero.Init, Start: monero.Start, Stop: monero.Stop},
|
||||
// {Coin: "sha3x", Init: sha3x.Init, Start: sha3x.Start, Stop: sha3x.Stop},
|
||||
}
|
||||
|
||||
func register_signal(dbctx *db.DbContext) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,62 @@
|
|||
# A sample log configuration file for running in release mode. By default, this configuration splits up log messages to
|
||||
# three destinations:
|
||||
# * Console: For log messages with level INFO and higher
|
||||
# * log/miner/network.log: INFO-level logs related to the comms crate. This file will be quite busy since there
|
||||
# are lots of P2P debug messages, and so this traffic is segregated from the application log messages
|
||||
#
|
||||
# See https://docs.rs/log4rs/0.8.3/log4rs/encode/pattern/index.html for deciphering the log pattern. The log format
|
||||
# used in this sample configuration prints messages as:
|
||||
# timestamp [target] LEVEL message
|
||||
refresh_rate: 30 seconds
|
||||
appenders:
|
||||
# An appender named "stdout" that writes to stdout
|
||||
stdout:
|
||||
kind: console
|
||||
encoder:
|
||||
pattern: "{d(%H:%M)} {h({l}):5} {m}{n}"
|
||||
filters:
|
||||
- kind: threshold
|
||||
level: info
|
||||
# An appender named "base_layer" that writes to a file with a custom pattern encoder
|
||||
miner:
|
||||
kind: rolling_file
|
||||
path: "{{log_dir}}/log/miner/miner.log"
|
||||
policy:
|
||||
kind: compound
|
||||
trigger:
|
||||
kind: size
|
||||
limit: 10mb
|
||||
roller:
|
||||
kind: fixed_window
|
||||
base: 1
|
||||
count: 5
|
||||
pattern: "{{log_dir}}/log/miner/miner.{}.log"
|
||||
encoder:
|
||||
pattern: "{d(%Y-%m-%d %H:%M:%S.%f)} [{t}] [Thread:{I}] {l:5} {m}{n}"
|
||||
|
||||
# Set the default logging level to "warn" and attach the "stdout" appender to the root
|
||||
root:
|
||||
level: info
|
||||
appenders:
|
||||
- stdout
|
||||
|
||||
loggers:
|
||||
# miner
|
||||
minotari::application:
|
||||
level: info
|
||||
appenders:
|
||||
- miner
|
||||
- stdout
|
||||
additive: false
|
||||
minotari::miner:
|
||||
level: info
|
||||
appenders:
|
||||
- miner
|
||||
- stdout
|
||||
additive: false
|
||||
minotari_miner:
|
||||
level: info
|
||||
appenders:
|
||||
- miner
|
||||
- stdout
|
||||
additive: false
|
|
@ -0,0 +1,68 @@
|
|||
[package]
|
||||
name = "minotari_miner"
|
||||
authors = ["The Tari Development Community"]
|
||||
description = "The tari miner implementation"
|
||||
repository = "https://github.com/tari-project/tari"
|
||||
license = "BSD-3-Clause"
|
||||
version = "4.9.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
tari_core = { path = "../../base_layer/core", default-features = false }
|
||||
tari_common = { path = "../../common" }
|
||||
tari_common_types = { path = "../../base_layer/common_types" }
|
||||
tari_max_size = { path = "../../infrastructure/max_size" }
|
||||
minotari_app_utilities = { path = "../minotari_app_utilities", features = [
|
||||
"miner_input",
|
||||
] }
|
||||
minotari_app_grpc = { path = "../minotari_app_grpc" }
|
||||
tari_utilities = { version = "0.8" }
|
||||
|
||||
base64 = "0.13.0"
|
||||
borsh = "1.5.7"
|
||||
bufstream = "0.1"
|
||||
chrono = { version = "0.4.39", default-features = false }
|
||||
clap = { version = "3.2", features = ["derive"] }
|
||||
crossbeam = "0.8"
|
||||
crossterm = { version = "0.28" }
|
||||
derivative = "2.2.0"
|
||||
futures = "0.3"
|
||||
hex = "0.4.2"
|
||||
log = { version = "0.4", features = ["std"] }
|
||||
log4rs = { version = "1.3.0", default-features = false, features = [
|
||||
"config_parsing",
|
||||
"threshold_filter",
|
||||
"yaml_format",
|
||||
"console_appender",
|
||||
"rolling_file_appender",
|
||||
"compound_policy",
|
||||
"size_trigger",
|
||||
"fixed_window_roller",
|
||||
] }
|
||||
native-tls = "0.2"
|
||||
num_cpus = "1.13"
|
||||
rand = "0.8"
|
||||
serde = { version = "1.0", default-features = false, features = ["derive"] }
|
||||
serde_json = "1.0.57"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.44", default-features = false, features = [
|
||||
"rt-multi-thread",
|
||||
] }
|
||||
tonic = { version = "0.13.1", features = ["tls-ring", "tls-native-roots"] }
|
||||
zmq = "0.10"
|
||||
anyhow = "1.0"
|
||||
|
||||
[dev-dependencies]
|
||||
prost-types = "0.13.3"
|
||||
chrono = { version = "0.4.39", default-features = false }
|
||||
config = "0.14.0"
|
||||
|
||||
zmq = "0.10"
|
||||
anyhow = "1.0"
|
||||
|
||||
[package.metadata.cargo-machete]
|
||||
ignored = [
|
||||
# We need to specify extra features for log4rs even though it is not used directly in this crate
|
||||
"log4rs",
|
||||
"prost",
|
||||
]
|
|
@ -0,0 +1,39 @@
|
|||
# Standalone miner for the Minotari network
|
||||
|
||||
The Minotari Miner application should be running connected to the Minotari Base Node and the Minotari Console Wallet,
|
||||
allowing it insert the coinbase transactions created by the Minotari Wallet and to to mine blocks matching the
|
||||
required network difficulty. This also serves as a reference implementation for custom miners that which can be derived
|
||||
from it.
|
||||
|
||||
### Installation
|
||||
|
||||
Please refer to the relevant section in the main
|
||||
[README installation section](https://github.com/tari-project/tari/blob/development/README.md#install-and-run).
|
||||
|
||||
### Configuration
|
||||
|
||||
When running with local versions of the Minotari Base Node and the Minotari Wallet, no additional configuration other
|
||||
than what is described in the main
|
||||
[README configuration section](https://github.com/tari-project/tari/blob/development/README.md#tari-sha3-mining)
|
||||
is required. The Minotari Miner can also be located on a remote workstation.
|
||||
|
||||
Configuration options for the Minotari Miner are as follows:
|
||||
|
||||
- `base_node_grpc_address` - this is IPv4/IPv6 address including port number, by which the Minotari Base Node can be found;
|
||||
- `num_mining_threads` - the number of mining threads, which defaults to the number of CPU cores;
|
||||
- `mine_on_tip_only` - mining will only start when the Minotari Base Node reports it is in the bootstrapped state;
|
||||
- `proof_of_work_algo` - The proof of work algorithm to use
|
||||
- `validate_tip_timeout_sec` - the interval at which the current block height will be checked to determine if mining
|
||||
must be restarted, whereby the tip might have advanced passed the block height that is in use in the current template.
|
||||
- `mining_pool_address` - Stratum Mode configuration - mining pool address
|
||||
- `mining_wallet_address` - `Stratum Mode configuration - mining wallet address/public key`
|
||||
- `mining_worker_name` - `Stratum Mode configuration - mining worker name`
|
||||
- `coinbase_extra` - Note that this data is publicly readable, but it is suggested you populate it so that pool
|
||||
dominance can be seen before any one party has more than 51%.
|
||||
- `network` - "Selected network"
|
||||
- `wait_timeout_on_error` - "Base node reconnect timeout after any gRPC or miner error"
|
||||
- `wallet_payment_address` - "The Tari wallet address where the mining funds will be sent to"
|
||||
|
||||
### Caveats
|
||||
|
||||
Currently, the Minotari Miner only supports SHA3 mining; this is adequate for the current Tari protocol.
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#[cfg(windows)]
|
||||
fn main() {
|
||||
use std::env;
|
||||
println!("cargo:rerun-if-changed=icon.res");
|
||||
let mut path = env::current_dir().unwrap();
|
||||
path.push("icon.res");
|
||||
println!("cargo:rustc-link-arg={}", path.into_os_string().into_string().unwrap());
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn main() {}
|
Binary file not shown.
After Width: | Height: | Size: 279 KiB |
|
@ -0,0 +1 @@
|
|||
miner ICON "icon.ico"
|
Binary file not shown.
|
@ -0,0 +1,53 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2024. The Tari Project
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
# following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
# disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
# following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
# products derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
echo
|
||||
echo "Starting Miner"
|
||||
echo
|
||||
|
||||
# Initialize
|
||||
if [ -z "${use_parent_paths}" ]
|
||||
then
|
||||
base_path="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
||||
config_path="${base_path}/config"
|
||||
exe_path="${base_path}/runtime"
|
||||
fi
|
||||
"${exe_path}/start_tor.sh"
|
||||
|
||||
if [ ! -f "${config_path}/log4rs_miner.yml" ]
|
||||
then
|
||||
echo Creating new "${config_path}/log4rs_miner.yml";
|
||||
init_flag="--init"
|
||||
else
|
||||
echo Using existing "${config_path}/log4rs_miner.yml";
|
||||
init_flag=""
|
||||
fi
|
||||
echo
|
||||
|
||||
# Run
|
||||
echo Spawning Miner into new terminal..
|
||||
echo
|
||||
gnome-terminal --working-directory="$PWD" -- "${exe_path}/minotari_miner" ${init_flag} --config "${config_path}/config.toml" --log_config "${config_path}/log4rs_miner.yml" --base-path ${base_path}
|
|
@ -0,0 +1 @@
|
|||
./runtime/start_minotari_miner.sh
|
|
@ -0,0 +1,62 @@
|
|||
# A sample log configuration file for running in release mode. By default, this configuration splits up log messages to
|
||||
# three destinations:
|
||||
# * Console: For log messages with level INFO and higher
|
||||
# * log/miner/network.log: INFO-level logs related to the comms crate. This file will be quite busy since there
|
||||
# are lots of P2P debug messages, and so this traffic is segregated from the application log messages
|
||||
#
|
||||
# See https://docs.rs/log4rs/0.8.3/log4rs/encode/pattern/index.html for deciphering the log pattern. The log format
|
||||
# used in this sample configuration prints messages as:
|
||||
# timestamp [target] LEVEL message
|
||||
refresh_rate: 30 seconds
|
||||
appenders:
|
||||
# An appender named "stdout" that writes to stdout
|
||||
stdout:
|
||||
kind: console
|
||||
encoder:
|
||||
pattern: "{d(%H:%M)} {h({l}):5} {m}{n}"
|
||||
filters:
|
||||
- kind: threshold
|
||||
level: info
|
||||
# An appender named "base_layer" that writes to a file with a custom pattern encoder
|
||||
miner:
|
||||
kind: rolling_file
|
||||
path: "{{log_dir}}/log/miner/miner.log"
|
||||
policy:
|
||||
kind: compound
|
||||
trigger:
|
||||
kind: size
|
||||
limit: 10mb
|
||||
roller:
|
||||
kind: fixed_window
|
||||
base: 1
|
||||
count: 5
|
||||
pattern: "{{log_dir}}/log/miner/miner.{}.log"
|
||||
encoder:
|
||||
pattern: "{d(%Y-%m-%d %H:%M:%S.%f)} [{t}] [Thread:{I}] {l:5} {m}{n}"
|
||||
|
||||
# Set the default logging level to "warn" and attach the "stdout" appender to the root
|
||||
root:
|
||||
level: warn
|
||||
appenders:
|
||||
- stdout
|
||||
|
||||
loggers:
|
||||
# miner
|
||||
minotari::application:
|
||||
level: debug
|
||||
appenders:
|
||||
- miner
|
||||
- stdout
|
||||
additive: false
|
||||
minotari::miner:
|
||||
level: debug
|
||||
appenders:
|
||||
- miner
|
||||
- stdout
|
||||
additive: false
|
||||
minotari_miner:
|
||||
level: debug
|
||||
appenders:
|
||||
- miner
|
||||
- stdout
|
||||
additive: false
|
|
@ -0,0 +1,63 @@
|
|||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2024. The Tari Project
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
# following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
# disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
# following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
# products derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
#
|
||||
echo
|
||||
echo "Starting Miner"
|
||||
echo
|
||||
|
||||
# Initialize
|
||||
if [ -z "${use_parent_paths}" ]
|
||||
then
|
||||
base_path="$( cd "$(dirname "$0")" >/dev/null 2>&1 ; pwd -P )"
|
||||
config_path="${base_path}/config"
|
||||
exe_path="${base_path}/runtime"
|
||||
fi
|
||||
|
||||
tor_running=$(lsof -nP -iTCP:9050)
|
||||
if [ -z "${tor_running}" ]
|
||||
then
|
||||
echo "Starting Tor"
|
||||
open -a Terminal.app "${exe_path}/start_tor.sh"
|
||||
ping -c 15 localhost > /dev/null
|
||||
fi
|
||||
|
||||
if [ ! -f "${config_path}/log4rs_miner.yml" ]
|
||||
then
|
||||
echo Creating new "${config_path}/log4rs_miner.yml";
|
||||
init_flag="--init"
|
||||
else
|
||||
echo Using existing "${config_path}/log4rs_miner.yml";
|
||||
init_flag=""
|
||||
fi
|
||||
echo
|
||||
|
||||
# Run
|
||||
echo Spawning Console Wallet into new terminal..
|
||||
echo "${exe_path}/minotari_miner" ${init_flag} --config="${config_path}/config.toml" --log_config="${config_path}/log4rs_miner.yml" --base-path=${base_path} > $exe_path/tari_miner_command.sh
|
||||
chmod +x $exe_path/minotari_miner_command.sh
|
||||
|
||||
open -a terminal $exe_path/minotari_miner_command.sh
|
||||
echo
|
|
@ -0,0 +1 @@
|
|||
./runtime/start_minotari_miner.sh
|
|
@ -0,0 +1,70 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use clap::Parser;
|
||||
use minotari_app_utilities::common_cli_args::CommonCliArgs;
|
||||
use tari_common::configuration::{ConfigOverrideProvider, Network};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
#[clap(propagate_version = true)]
|
||||
pub struct Cli {
|
||||
#[clap(flatten)]
|
||||
pub common: CommonCliArgs,
|
||||
#[clap(long, alias = "mine-until-height")]
|
||||
pub mine_until_height: Option<u64>,
|
||||
#[clap(long, alias = "max-blocks")]
|
||||
pub miner_max_blocks: Option<u64>,
|
||||
#[clap(long, alias = "min-difficulty")]
|
||||
pub miner_min_diff: Option<u64>,
|
||||
#[clap(long, alias = "max-difficulty")]
|
||||
pub miner_max_diff: Option<u64>,
|
||||
#[clap(short, long, alias = "non-interactive", env = "TARI_NON_INTERACTIVE")]
|
||||
pub non_interactive_mode: bool,
|
||||
|
||||
|
||||
#[clap(long, alias = "zmq-pub-port", default_value = "11113")]
|
||||
zmq_pub_port: u16,
|
||||
#[clap(long, alias = "zmq-sub-port", default_value = "11112")]
|
||||
zmq_sub_port: u16,
|
||||
}
|
||||
|
||||
impl ConfigOverrideProvider for Cli {
|
||||
/// Get the configuration property overrides for the given network. In case of duplicates, the final override
|
||||
/// added to the list will have preference.
|
||||
fn get_config_property_overrides(&self, network: &Network) -> Vec<(String, String)> {
|
||||
// Config file overrides
|
||||
let mut overrides = vec![("miner.network".to_string(), network.to_string())];
|
||||
// Command-line overrides
|
||||
let command_line_overrides = self.common.get_config_property_overrides(network);
|
||||
command_line_overrides.iter().for_each(|(k, v)| {
|
||||
replace_or_add_override(&mut overrides, k, v);
|
||||
});
|
||||
overrides
|
||||
}
|
||||
}
|
||||
|
||||
fn replace_or_add_override(overrides: &mut Vec<(String, String)>, key: &str, value: &str) {
|
||||
if let Some(index) = overrides.iter().position(|(k, _)| k == key) {
|
||||
overrides.remove(index);
|
||||
}
|
||||
overrides.push((key.to_string(), value.to_string()));
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. Minotari Miner Node derives all
|
||||
// configuration management
|
||||
//! from [tari_common] crate, also extending with few
|
||||
//! specific options:
|
||||
//! - base_node_grpc_address - is IPv4/IPv6 address including port number, by which Minotari Base Node can be found
|
||||
//! - num_mining_threads - number of mining threads, defaults to number of cpu cores
|
||||
//! - mine_on_tip_only - will start mining only when node is reporting bootstrapped state
|
||||
//! - validate_tip_timeout_sec - will check tip with node every N seconds to validate that still mining on a tip All
|
||||
//! miner options configured under `[miner]` section of Minotari's `config.toml`.
|
||||
|
||||
use std::{
|
||||
path::{Path, PathBuf},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use minotari_app_grpc::tari_rpc::{pow_algo::PowAlgos, NewBlockTemplateRequest, PowAlgo};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tari_common::{
|
||||
configuration::{utils::deserialize_string_or_struct, Network},
|
||||
SubConfigPath,
|
||||
};
|
||||
use tari_common_types::{grpc_authentication::GrpcAuthentication, tari_address::TariAddress};
|
||||
use tari_core::{proof_of_work::PowAlgorithm, transactions::transaction_components::RangeProofType};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct MinerConfig {
|
||||
/// gRPC address of base node
|
||||
pub base_node_grpc_address: Option<String>,
|
||||
/// GRPC authentication for base node
|
||||
pub base_node_grpc_authentication: GrpcAuthentication,
|
||||
/// GRPC domain name for node TLS validation
|
||||
pub base_node_grpc_tls_domain_name: Option<String>,
|
||||
/// GRPC ca cert name for TLS
|
||||
pub base_node_grpc_ca_cert_filename: String,
|
||||
/// Number of mining threads
|
||||
pub num_mining_threads: usize,
|
||||
/// Start mining only when base node is bootstrapped and current block height is on the tip of network
|
||||
pub mine_on_tip_only: bool,
|
||||
/// The proof of work algorithm to use (Sha3x or RandomXT)
|
||||
#[serde(deserialize_with = "deserialize_string_or_struct")]
|
||||
pub proof_of_work_algo: PowAlgorithm,
|
||||
/// Will check tip with node every N seconds and restart mining if height already taken and option
|
||||
/// `mine_on_tip_only` is set to true
|
||||
pub validate_tip_timeout_sec: u64,
|
||||
/// Stratum Mode configuration - mining pool address
|
||||
pub stratum_mining_pool_address: String,
|
||||
/// Stratum Mode configuration - mining wallet address/public key
|
||||
pub stratum_mining_wallet_address: String,
|
||||
/// Stratum Mode configuration - mining worker name
|
||||
pub mining_worker_name: String,
|
||||
/// The extra data to store in the coinbase, usually some data about the mining pool.
|
||||
/// Note that this data is publicly readable, but it is suggested you populate it so that
|
||||
/// pool dominance can be seen before any one party has more than 51%.
|
||||
pub coinbase_extra: String,
|
||||
/// Selected network
|
||||
pub network: Network,
|
||||
/// Base node reconnect timeout after any gRPC or miner error
|
||||
pub wait_timeout_on_error: u64,
|
||||
/// The relative path to store persistent config
|
||||
pub config_dir: PathBuf,
|
||||
/// The Tari wallet address (valid address in hex) where the mining funds will be sent to - must be assigned
|
||||
pub wallet_payment_address: String,
|
||||
/// Range proof type - revealed_value or bullet_proof_plus: (default = revealed_value)
|
||||
pub range_proof_type: RangeProofType,
|
||||
/// SHA based p2pool decentralized mining enabled or not
|
||||
pub sha_p2pool_enabled: bool,
|
||||
|
||||
pub zmq_publisher_port: u16,
|
||||
pub zmq_subscriber_port: u16,
|
||||
}
|
||||
|
||||
impl SubConfigPath for MinerConfig {
|
||||
fn main_key_prefix() -> &'static str {
|
||||
"miner"
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for MinerConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
base_node_grpc_address: None,
|
||||
base_node_grpc_authentication: GrpcAuthentication::default(),
|
||||
base_node_grpc_tls_domain_name: None,
|
||||
base_node_grpc_ca_cert_filename: "node_ca.pem".to_string(),
|
||||
num_mining_threads: num_cpus::get(),
|
||||
mine_on_tip_only: true,
|
||||
proof_of_work_algo: PowAlgorithm::Sha3x,
|
||||
validate_tip_timeout_sec: 30,
|
||||
stratum_mining_pool_address: String::new(),
|
||||
stratum_mining_wallet_address: String::new(),
|
||||
mining_worker_name: String::new(),
|
||||
coinbase_extra: "m2pool.com".to_string(),
|
||||
network: Default::default(),
|
||||
wait_timeout_on_error: 10,
|
||||
config_dir: PathBuf::from("config/miner"),
|
||||
wallet_payment_address: TariAddress::default().to_base58(),
|
||||
range_proof_type: RangeProofType::RevealedValue,
|
||||
sha_p2pool_enabled: false,
|
||||
zmq_publisher_port: 11112,
|
||||
zmq_subscriber_port: 11113,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MinerConfig {
|
||||
pub fn pow_algo_request(&self) -> NewBlockTemplateRequest {
|
||||
let algo = match self.proof_of_work_algo {
|
||||
PowAlgorithm::Sha3x => Some(PowAlgo {
|
||||
pow_algo: PowAlgos::Sha3x.into(),
|
||||
}),
|
||||
PowAlgorithm::RandomXM => Some(PowAlgo {
|
||||
pow_algo: PowAlgos::Randomxm.into(),
|
||||
}),
|
||||
PowAlgorithm::RandomXT => Some(PowAlgo {
|
||||
pow_algo: PowAlgos::Randomxt.into(),
|
||||
}),
|
||||
};
|
||||
NewBlockTemplateRequest { algo, max_weight: 0 }
|
||||
}
|
||||
|
||||
pub fn wait_timeout(&self) -> Duration {
|
||||
Duration::from_secs(self.wait_timeout_on_error)
|
||||
}
|
||||
|
||||
pub fn validate_tip_interval(&self) -> Duration {
|
||||
Duration::from_secs(self.validate_tip_timeout_sec)
|
||||
}
|
||||
|
||||
pub fn set_base_path<P: AsRef<Path>>(&mut self, base_path: P) {
|
||||
if !self.config_dir.is_absolute() {
|
||||
self.config_dir = base_path.as_ref().join(self.config_dir.as_path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use tari_common::DefaultConfigLoader;
|
||||
|
||||
use crate::config::MinerConfig;
|
||||
|
||||
#[test]
|
||||
fn miner_configuration() {
|
||||
const CONFIG: &str = r#"
|
||||
[miner]
|
||||
num_mining_threads=2
|
||||
base_node_grpc_address = "http://my_base_node:1234"
|
||||
mine_on_tip_only = false
|
||||
"#;
|
||||
let mut cfg: config::Config = config::Config::default();
|
||||
#[allow(deprecated)]
|
||||
cfg.merge(config::File::from_str(CONFIG, config::FileFormat::Toml))
|
||||
.unwrap();
|
||||
let config = MinerConfig::load_from(&cfg).expect("Failed to load config");
|
||||
assert_eq!(config.num_mining_threads, 2);
|
||||
assert_eq!(
|
||||
config.base_node_grpc_address,
|
||||
Some("http://my_base_node:1234".to_string())
|
||||
);
|
||||
assert!(!config.mine_on_tip_only);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,163 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use minotari_app_grpc::tari_rpc::BlockHeader as grpc_header;
|
||||
use tari_common_types::types::FixedHash;
|
||||
use tari_core::{
|
||||
blocks::BlockHeader,
|
||||
proof_of_work::{randomx_factory::RandomXFactory, sha3x_difficulty, tari_randomx_difficulty},
|
||||
};
|
||||
use tari_utilities::epoch_time::EpochTime;
|
||||
|
||||
use crate::errors::MinerError;
|
||||
|
||||
pub type Difficulty = u64;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BlockHeaderSha3 {
|
||||
pub header: BlockHeader,
|
||||
pub hashes: u64,
|
||||
pub vm_key: FixedHash,
|
||||
pub rx_factory: Option<RandomXFactory>,
|
||||
}
|
||||
|
||||
impl BlockHeaderSha3 {
|
||||
#[allow(clippy::cast_possible_truncation)]
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
pub fn new(header: grpc_header, vm_key: FixedHash, rx_factory: Option<RandomXFactory>) -> Result<Self, MinerError> {
|
||||
let header: BlockHeader = header.try_into().map_err(MinerError::BlockHeader)?;
|
||||
Ok(Self {
|
||||
header,
|
||||
hashes: 0,
|
||||
vm_key,
|
||||
rx_factory,
|
||||
})
|
||||
}
|
||||
|
||||
/// This function will update the timestamp of the header, but only if the new timestamp is greater than the current
|
||||
/// one.
|
||||
pub fn set_forward_timestamp(&mut self, timestamp: u64) {
|
||||
// if the timestamp has been advanced by the base_node due to the median time we should not reverse it but we
|
||||
// should only change the timestamp if we move it forward.
|
||||
if timestamp > self.header.timestamp.as_u64() {
|
||||
self.header.timestamp = EpochTime::from(timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn random_nonce(&mut self) {
|
||||
use rand::{rngs::OsRng, RngCore};
|
||||
self.header.nonce = OsRng.next_u64();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inc_nonce(&mut self) {
|
||||
self.header.nonce = self.header.nonce.wrapping_add(1);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn difficulty_sha3(&mut self) -> Result<Difficulty, MinerError> {
|
||||
self.hashes = self.hashes.saturating_add(1);
|
||||
Ok(sha3x_difficulty(&self.header)?.as_u64())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn difficulty_rx(&mut self) -> Result<Difficulty, MinerError> {
|
||||
self.hashes = self.hashes.saturating_add(1);
|
||||
let randomx_factory = self.rx_factory.as_ref().ok_or(MinerError::RandomXFactoryNotSet)?;
|
||||
Ok(tari_randomx_difficulty(&self.header, randomx_factory, &self.vm_key)?.as_u64())
|
||||
}
|
||||
|
||||
#[allow(clippy::cast_possible_wrap)]
|
||||
pub fn create_header(&self) -> grpc_header {
|
||||
self.header.clone().into()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn height(&self) -> u64 {
|
||||
self.header.height
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod test {
|
||||
use chrono::{DateTime, NaiveDate, Utc};
|
||||
use tari_core::proof_of_work::sha3x_difficulty as core_sha3x_difficulty;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[allow(clippy::cast_sign_loss)]
|
||||
pub fn get_header() -> (grpc_header, BlockHeader) {
|
||||
let mut header = BlockHeader::new(0);
|
||||
header.timestamp = (DateTime::<Utc>::from_naive_utc_and_offset(
|
||||
NaiveDate::from_ymd_opt(2000, 1, 1)
|
||||
.unwrap()
|
||||
.and_hms_opt(1, 1, 1)
|
||||
.unwrap(),
|
||||
Utc,
|
||||
)
|
||||
.timestamp() as u64)
|
||||
.into();
|
||||
header.pow.pow_algo = tari_core::proof_of_work::PowAlgorithm::Sha3x;
|
||||
(header.clone().into(), header)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_nonce_difficulty() {
|
||||
let (mut header, mut core_header) = get_header();
|
||||
header.nonce = 1;
|
||||
core_header.nonce = 1;
|
||||
let mut hasher = BlockHeaderSha3::new(header, FixedHash::zero(), None).unwrap();
|
||||
for _ in 0..1000 {
|
||||
assert_eq!(
|
||||
hasher.difficulty_sha3().unwrap(),
|
||||
core_sha3x_difficulty(&core_header).unwrap().as_u64(),
|
||||
"with nonces = {}:{}",
|
||||
hasher.header.nonce,
|
||||
core_header.nonce
|
||||
);
|
||||
core_header.nonce += 1;
|
||||
hasher.inc_nonce();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn validate_timestamp_difficulty() {
|
||||
let (mut header, mut core_header) = get_header();
|
||||
header.nonce = 1;
|
||||
core_header.nonce = 1;
|
||||
let mut hasher = BlockHeaderSha3::new(header, FixedHash::zero(), None).unwrap();
|
||||
let mut timestamp = core_header.timestamp;
|
||||
for _ in 0..1000 {
|
||||
assert_eq!(
|
||||
hasher.difficulty_sha3().unwrap(),
|
||||
core_sha3x_difficulty(&core_header).unwrap().as_u64(),
|
||||
"with timestamp = {}",
|
||||
timestamp
|
||||
);
|
||||
timestamp = timestamp.checked_add(EpochTime::from(1)).unwrap();
|
||||
core_header.timestamp = timestamp;
|
||||
hasher.set_forward_timestamp(timestamp.as_u64());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use minotari_app_grpc::authentication::BasicAuthError;
|
||||
use minotari_app_utilities::parse_miner_input::ParseInputError;
|
||||
use tari_max_size::MaxSizeBytesError;
|
||||
use thiserror::Error;
|
||||
use tonic::codegen::http::uri::InvalidUri;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum MinerError {
|
||||
#[error("I/O error")]
|
||||
IOError(#[from] std::io::Error),
|
||||
#[error("gRPC error: {0}")]
|
||||
GrpcStatus(#[from] tonic::Status),
|
||||
#[error("Connection error: {0}")]
|
||||
GrpcConnection(#[from] tonic::transport::Error),
|
||||
#[error("Node not ready")]
|
||||
NodeNotReady,
|
||||
#[error("Blockchain reached specified height {0}, mining will be stopped")]
|
||||
MineUntilHeightReached(u64),
|
||||
#[error("Block height {0} already mined")]
|
||||
MinerLostBlock(u64),
|
||||
#[error("Expected non empty {0}")]
|
||||
EmptyObject(String),
|
||||
#[error("Invalid block header {0}")]
|
||||
BlockHeader(String),
|
||||
#[error("Conversion error: {0}")]
|
||||
Conversion(String),
|
||||
#[error("Invalid gRPC credentials: {0}")]
|
||||
BasicAuthError(#[from] BasicAuthError),
|
||||
#[error("Invalid gRPC url: {0}")]
|
||||
InvalidUri(#[from] InvalidUri),
|
||||
#[error("TLS connection error: {0}")]
|
||||
TlsConnectionError(String),
|
||||
#[error("Coinbase error: {0}")]
|
||||
CoinbaseError(String),
|
||||
#[error("Consensus build error: {0}")]
|
||||
ParseInputError(#[from] ParseInputError),
|
||||
#[error("Base node not responding to gRPC requests: {0}")]
|
||||
BaseNodeNotResponding(String),
|
||||
#[error("Limit error {0}")]
|
||||
MaxSizeBytesError(#[from] MaxSizeBytesError),
|
||||
#[error("Miner is set to use Rx, but not RX factory is set")]
|
||||
RandomXFactoryNotSet,
|
||||
#[error("RandomX error: {0}")]
|
||||
MergeMineError(#[from] tari_core::proof_of_work::monero_rx::MergeMineError),
|
||||
#[error("Difficulty error: {0}")]
|
||||
DifficultyError(#[from] tari_core::proof_of_work::DifficultyError),
|
||||
}
|
||||
|
||||
pub fn err_empty(name: &str) -> MinerError {
|
||||
MinerError::EmptyObject(name.to_string())
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// non-64-bit not supported
|
||||
minotari_app_utilities::deny_non_64_bit_archs!();
|
||||
|
||||
mod cli;
|
||||
pub use cli::Cli;
|
||||
use tari_common::exit_codes::ExitError;
|
||||
mod run_miner;
|
||||
use run_miner::start_miner;
|
||||
mod config;
|
||||
mod difficulty;
|
||||
mod errors;
|
||||
mod miner;
|
||||
mod stratum;
|
||||
|
||||
pub async fn run_miner(cli: Cli) -> Result<(), ExitError> {
|
||||
start_miner(cli).await
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use std::io::stdout;
|
||||
|
||||
use clap::Parser;
|
||||
use crossterm::{execute, terminal::SetTitle};
|
||||
use log::*;
|
||||
use minotari_app_utilities::consts;
|
||||
use run_miner::start_miner;
|
||||
use tari_common::{exit_codes::ExitError, initialize_logging};
|
||||
|
||||
use crate::cli::Cli;
|
||||
|
||||
pub const LOG_TARGET: &str = "minotari::miner::main";
|
||||
pub const LOG_TARGET_FILE: &str = "minotari::logging::miner::main";
|
||||
|
||||
mod cli;
|
||||
mod config;
|
||||
mod difficulty;
|
||||
mod errors;
|
||||
mod miner;
|
||||
mod run_miner;
|
||||
mod stratum;
|
||||
|
||||
/// Application entry point
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let terminal_title = format!("Minotari Miner - Version {}", consts::APP_VERSION);
|
||||
if let Err(e) = execute!(stdout(), SetTitle(terminal_title.as_str())) {
|
||||
println!("Error setting terminal title. {}", e)
|
||||
}
|
||||
match main_inner().await {
|
||||
Ok(_) => std::process::exit(0),
|
||||
Err(err) => {
|
||||
error!(target: LOG_TARGET, "Fatal error: {}", err);
|
||||
let exit_code = err.exit_code;
|
||||
error!(target: LOG_TARGET, "Exiting with code: {}", exit_code);
|
||||
std::process::exit(exit_code as i32)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
async fn main_inner() -> Result<(), ExitError> {
|
||||
let cli = Cli::parse();
|
||||
initialize_logging(
|
||||
&cli.common.log_config_path("miner"),
|
||||
&cli.common.get_base_path(),
|
||||
include_str!("../log4rs_sample.yml"),
|
||||
)?;
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"Starting Minotari Miner version: {}",
|
||||
consts::APP_VERSION
|
||||
);
|
||||
start_miner(cli).await
|
||||
}
|
|
@ -0,0 +1,505 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use std::{
|
||||
panic::panic_any,
|
||||
pin::Pin,
|
||||
task::{Context, Poll, Waker},
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use chrono::Utc;
|
||||
use crossbeam::channel::{bounded, Select, Sender, TrySendError};
|
||||
use futures::Stream;
|
||||
use log::*;
|
||||
use minotari_app_grpc::tari_rpc::BlockHeader;
|
||||
use tari_common_types::types::FixedHash;
|
||||
use tari_core::proof_of_work::randomx_factory::RandomXFactory;
|
||||
use thread::JoinHandle;
|
||||
|
||||
use super::difficulty::BlockHeaderSha3;
|
||||
|
||||
use zmq::{Socket};
|
||||
|
||||
use anyhow::{Result};
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
use std::sync::{Arc};
|
||||
use tokio::sync::{Mutex, };
|
||||
use minotari_app_utilities::parse_miner_input::BaseNodeGrpcClient;
|
||||
use crate::errors::MinerError;
|
||||
|
||||
pub const LOG_TARGET: &str = "minotari::miner::standalone";
|
||||
|
||||
// Identify how often mining thread is reporting / checking context
|
||||
// ~400_000 hashes per second
|
||||
const REPORTING_FREQUENCY_RX: u64 = 300;
|
||||
const REPORTING_FREQUENCY_SHA3: u64 = 3_000_000;
|
||||
|
||||
// Thread's stack size, ideally we would fit all thread's data in the CPU L1 cache
|
||||
const STACK_SIZE: usize = 320_000;
|
||||
|
||||
/// Miner will send regular reports from every mining threads
|
||||
#[derive(Debug)]
|
||||
pub struct MiningReport {
|
||||
pub miner: usize,
|
||||
pub target_difficulty: u64,
|
||||
pub difficulty: u64,
|
||||
pub hashes: u64,
|
||||
pub elapsed: Duration,
|
||||
/// Will be set for when mined header is matching required difficulty
|
||||
pub header: Option<BlockHeader>,
|
||||
pub height: u64,
|
||||
}
|
||||
|
||||
/// Miner is starting number of mining threads and implements Stream for async reports polling
|
||||
/// Communication with async world is performed via channel and waker so should be quite efficient
|
||||
pub struct Miner {
|
||||
threads: Vec<JoinHandle<()>>,
|
||||
channels: Vec<crossbeam::channel::Receiver<MiningReport>>,
|
||||
num_threads: usize,
|
||||
header: BlockHeader,
|
||||
target_difficulty: u64,
|
||||
share_mode: bool,
|
||||
vm_key: FixedHash,
|
||||
rx_factory: Option<RandomXFactory>,
|
||||
|
||||
publisher_socket: Arc<Mutex<Socket>>,
|
||||
subscriber_socket: Arc<Mutex<Socket>>,
|
||||
base_node_client: BaseNodeGrpcClient,
|
||||
}
|
||||
|
||||
impl Miner {
|
||||
pub fn init_mining(
|
||||
base_node_client: BaseNodeGrpcClient,
|
||||
header: BlockHeader,
|
||||
target_difficulty: u64,
|
||||
num_threads: usize,
|
||||
share_mode: bool,
|
||||
vm_key: FixedHash,
|
||||
rx_factory: Option<RandomXFactory>,
|
||||
publisher_socket: Arc<Mutex<Socket>>,
|
||||
subscriber_socket: Arc<Mutex<Socket>>,
|
||||
) -> Self {
|
||||
Self {
|
||||
threads: vec![],
|
||||
channels: vec![],
|
||||
header,
|
||||
num_threads,
|
||||
target_difficulty,
|
||||
share_mode,
|
||||
vm_key,
|
||||
rx_factory,
|
||||
publisher_socket,
|
||||
subscriber_socket,
|
||||
base_node_client,
|
||||
}
|
||||
}
|
||||
|
||||
// this will kill all mining threads currently active and attached to this miner
|
||||
pub fn kill_threads(&mut self) {
|
||||
self.channels.clear();
|
||||
}
|
||||
|
||||
// Start mining threads with async context waker
|
||||
fn start_threads(&mut self, ctx: &Context<'_>) {
|
||||
let miners = (0..self.num_threads)
|
||||
.map(|i| {
|
||||
(
|
||||
thread::Builder::new()
|
||||
.name(format!("cpu-miner-{}", i))
|
||||
.stack_size(STACK_SIZE),
|
||||
i,
|
||||
)
|
||||
})
|
||||
.map(|(thread, i)| {
|
||||
let (tx, rx) = bounded(1);
|
||||
let header = self.header.clone();
|
||||
let waker = ctx.waker().clone();
|
||||
let difficulty = self.target_difficulty;
|
||||
let share_mode = self.share_mode;
|
||||
let vm_key = self.vm_key;
|
||||
let rx_factory = self.rx_factory.clone();
|
||||
|
||||
let pub_socket = Arc::clone(&self.publisher_socket);
|
||||
let sub_socket = Arc::clone(&self.subscriber_socket);
|
||||
let base_node_client_clone = self.base_node_client.clone();
|
||||
let handle = thread
|
||||
.spawn(move || mining_task(base_node_client_clone, header, difficulty, tx, waker, i, share_mode, vm_key, rx_factory, pub_socket, sub_socket))
|
||||
.expect("Failed to create mining thread");
|
||||
(handle, rx)
|
||||
});
|
||||
|
||||
let (threads, channels) = miners.unzip();
|
||||
self.threads = threads;
|
||||
self.channels = channels;
|
||||
}
|
||||
}
|
||||
|
||||
impl Stream for Miner {
|
||||
type Item = MiningReport;
|
||||
|
||||
fn poll_next(mut self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
|
||||
trace!(target: LOG_TARGET, "Polling Miner");
|
||||
// First poll would start all the threads passing async context waker
|
||||
if self.threads.is_empty() && self.num_threads > 0 {
|
||||
debug!(
|
||||
target: LOG_TARGET,
|
||||
"Starting {} mining threads for target difficulty {}", self.num_threads, self.target_difficulty
|
||||
);
|
||||
self.start_threads(ctx);
|
||||
return Poll::Pending;
|
||||
} else if self.num_threads == 0 {
|
||||
error!(target: LOG_TARGET, "Cannot mine: no mining threads");
|
||||
return Poll::Ready(None);
|
||||
} else if self.channels.is_empty() {
|
||||
debug!(target: LOG_TARGET, "Finished mining");
|
||||
return Poll::Ready(None);
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
// Non blocking select from all miner's receiver channels
|
||||
let mut sel = Select::new();
|
||||
for rx in &self.channels {
|
||||
sel.recv(rx);
|
||||
}
|
||||
let report = match sel.try_select() {
|
||||
Ok(oper) => {
|
||||
let idx = oper.index();
|
||||
match oper.recv(&self.channels[idx]) {
|
||||
Ok(report) => report,
|
||||
Err(_) => {
|
||||
// Received error would mean thread is disconnected already
|
||||
trace!("Thread {} disconnected.", idx);
|
||||
return Poll::Ready(None);
|
||||
},
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
// No reports
|
||||
return Poll::Pending;
|
||||
},
|
||||
};
|
||||
if report.header.is_some() && !self.share_mode {
|
||||
// Dropping recipients would stop miners next time they try to report
|
||||
self.channels.clear();
|
||||
}
|
||||
Poll::Ready(Some(report))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct GbtMsg {
|
||||
pub height: u64,
|
||||
pub header: String,
|
||||
pub u64target: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct SubmitRequest {
|
||||
pub id: u64,
|
||||
pub user: String,
|
||||
pub miner: String,
|
||||
pub index: String,
|
||||
pub header: String,
|
||||
pub nonce: u64,
|
||||
pub pow: String,
|
||||
pub subidx: i64,
|
||||
pub height: u64,
|
||||
pub submitidx: u64,
|
||||
}
|
||||
|
||||
fn send_gbt_message(socket: &Arc<Mutex<Socket>>, msg: &GbtMsg) -> Result<(), Box<dyn std::error::Error>> {
|
||||
let msg_json = serde_json::to_string(msg)?;
|
||||
if let Ok(pub_socket) = socket.try_lock() {
|
||||
pub_socket.send_multipart(&["jobsha3x".as_bytes(), msg_json.as_bytes()], 0)?;
|
||||
println!("send_gbt_message");
|
||||
Ok(())
|
||||
} else {
|
||||
Err("Socket lock busy".into())
|
||||
}
|
||||
}
|
||||
|
||||
fn try_receive_nonce(socket: &Arc<Mutex<Socket>>) -> Option<u64> {
|
||||
let sub_socket = match socket.try_lock() {
|
||||
Ok(sub_socket) => sub_socket,
|
||||
Err(_) => return None,
|
||||
};
|
||||
sub_socket.set_rcvtimeo(100).expect("Set timeout failed");
|
||||
let frames = match sub_socket.recv_multipart(zmq::DONTWAIT) {
|
||||
Ok(frames) => frames,
|
||||
Err(zmq::Error::EAGAIN) => return None,
|
||||
Err(e) => {
|
||||
error!("ZMQ receive error: {}", e);
|
||||
return None;
|
||||
}
|
||||
};
|
||||
|
||||
drop(sub_socket);
|
||||
|
||||
|
||||
if frames.len() < 2 {
|
||||
warn!("Invalid message format: expected at least 2 frames");
|
||||
return None;
|
||||
}
|
||||
|
||||
//println!("First frame: {:?}", frames.first().unwrap().as_slice());
|
||||
//println!("Nonce frame: {:?}", &frames[1]);
|
||||
|
||||
if frames.first().map(Vec::as_slice) != Some(b"blksha3x") {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
||||
match serde_json::from_slice::<SubmitRequest>(&frames[1]) {
|
||||
Ok(request) => Some(request.nonce),
|
||||
Err(e) => {
|
||||
warn!("Failed to parse nonce: {}", e);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Miner starts with a random nonce and iterates until it finds a header hash that meets the desired
|
||||
/// target
|
||||
pub fn mining_task(
|
||||
mut node_conn: BaseNodeGrpcClient,
|
||||
header: BlockHeader,
|
||||
target_difficulty: u64,
|
||||
sender: Sender<MiningReport>,
|
||||
waker: Waker,
|
||||
miner: usize,
|
||||
share_mode: bool,
|
||||
vm_key: FixedHash,
|
||||
rx_factory: Option<RandomXFactory>,
|
||||
publisher_socket: Arc<Mutex<Socket>>,
|
||||
subscriber_socket: Arc<Mutex<Socket>>,
|
||||
) {
|
||||
let mining_algorithm = if rx_factory.is_some() { "RandomXT" } else { "Sha3X" };
|
||||
let start = Instant::now();
|
||||
let mut hasher = match BlockHeaderSha3::new(header, vm_key, rx_factory) {
|
||||
Ok(hasher) => hasher,
|
||||
Err(err) => {
|
||||
let err = format!(
|
||||
"Miner {} on {} failed to create hasher: {:?}",
|
||||
miner, mining_algorithm, err
|
||||
);
|
||||
error!(target: LOG_TARGET, "{}", err);
|
||||
panic_any(err);
|
||||
},
|
||||
};
|
||||
hasher.random_nonce();
|
||||
|
||||
let gbt_msg = GbtMsg {
|
||||
height: hasher.header.height,
|
||||
header: hasher.header.mining_hash().to_string(),
|
||||
u64target: target_difficulty,
|
||||
};
|
||||
|
||||
|
||||
if let Err(e) = send_gbt_message(&publisher_socket, &gbt_msg) {
|
||||
error!(
|
||||
target: LOG_TARGET,
|
||||
"Miner {} failed to send GBT message: {}", miner, e
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// We're mining over here!
|
||||
trace!(target: LOG_TARGET, "Mining thread {} started for {}", miner, mining_algorithm);
|
||||
|
||||
let mut check_count:u64 = 0;
|
||||
// Mining work
|
||||
loop {
|
||||
if let Some(nonce) = try_receive_nonce(&subscriber_socket) {
|
||||
check_count = 0;
|
||||
hasher.header.nonce = nonce;
|
||||
println!("nonce {} {}", nonce, hasher.header.nonce);
|
||||
trace!(
|
||||
target: LOG_TARGET,
|
||||
"Miner {} received new nonce: {}", miner, nonce
|
||||
);
|
||||
} else {
|
||||
check_count += 1;
|
||||
if check_count > 10 {
|
||||
check_count = 0;
|
||||
let result = futures::executor::block_on(validate_tip(&mut node_conn, hasher.header.height));
|
||||
match result {
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
error!("Tip validation error: {:?}", e);
|
||||
let difficulty = 0;
|
||||
let res = sender.try_send(MiningReport {
|
||||
miner,
|
||||
difficulty,
|
||||
hashes: hasher.hashes,
|
||||
elapsed: start.elapsed(),
|
||||
header: None,
|
||||
height: hasher.height(),
|
||||
target_difficulty,
|
||||
});
|
||||
waker.wake_by_ref();
|
||||
trace!(target: LOG_TARGET, "Reporting from {} on {} result {:?}", miner, mining_algorithm, res);
|
||||
if let Err(TrySendError::Disconnected(_)) = res {
|
||||
info!(target: LOG_TARGET, "Mining thread {} on {} disconnected", miner, mining_algorithm);
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*check_count += 1;
|
||||
let reporting_frequency = if hasher.rx_factory.is_some() {
|
||||
REPORTING_FREQUENCY_RX
|
||||
} else {
|
||||
REPORTING_FREQUENCY_SHA3
|
||||
};
|
||||
if check_count > reporting_frequency {
|
||||
check_count = 0;
|
||||
let difficulty = 0;
|
||||
let res = sender.try_send(MiningReport {
|
||||
miner,
|
||||
difficulty,
|
||||
hashes: hasher.hashes,
|
||||
elapsed: start.elapsed(),
|
||||
header: None,
|
||||
height: hasher.height(),
|
||||
target_difficulty,
|
||||
});
|
||||
waker.wake_by_ref();
|
||||
trace!(target: LOG_TARGET, "Reporting from {} on {} result {:?}", miner, mining_algorithm, res);
|
||||
if let Err(TrySendError::Disconnected(_)) = res {
|
||||
info!(target: LOG_TARGET, "Mining thread {} on {} disconnected", miner, mining_algorithm);
|
||||
return;
|
||||
}
|
||||
|
||||
}*/
|
||||
continue;
|
||||
}
|
||||
println!("get nonce {}", hasher.header.nonce);
|
||||
let hashed = if hasher.rx_factory.is_some() {
|
||||
hasher.difficulty_rx()
|
||||
} else {
|
||||
println!("calc diff sha3x");
|
||||
hasher.difficulty_sha3()
|
||||
};
|
||||
|
||||
println!("check diff");
|
||||
let difficulty = match hashed {
|
||||
Ok(difficulty) => difficulty,
|
||||
Err(err) => {
|
||||
let err = format!(
|
||||
"Miner {} failed to calculate difficulty on {}: {:?}",
|
||||
miner, mining_algorithm, err
|
||||
);
|
||||
error!(target: LOG_TARGET, "{}", err);
|
||||
panic_any(err);
|
||||
},
|
||||
};
|
||||
|
||||
println!("difficulty {},{}", difficulty, target_difficulty);
|
||||
|
||||
if difficulty >= target_difficulty {
|
||||
debug!(
|
||||
target: LOG_TARGET,
|
||||
"Miner {} found nonce {} with matching difficulty {} on {} height {}",
|
||||
miner, hasher.header.nonce, difficulty, mining_algorithm, hasher.header.height
|
||||
);
|
||||
println!(
|
||||
"Miner {} found nonce {} with matching difficulty {} on {} height {}",
|
||||
miner, hasher.header.nonce, difficulty, mining_algorithm, hasher.header.height
|
||||
);
|
||||
if let Err(err) = sender.try_send(MiningReport {
|
||||
miner,
|
||||
difficulty,
|
||||
hashes: hasher.hashes,
|
||||
elapsed: start.elapsed(),
|
||||
height: hasher.height(),
|
||||
header: Some(hasher.create_header()),
|
||||
target_difficulty,
|
||||
}) {
|
||||
error!(target: LOG_TARGET, "Miner {} on {} failed to send report: {}", miner, mining_algorithm, err);
|
||||
}
|
||||
// If we are mining in share mode, this share might not be a block, so we need to keep mining till we get a
|
||||
// new job
|
||||
if share_mode {
|
||||
waker.wake_by_ref();
|
||||
} else {
|
||||
waker.wake();
|
||||
trace!(target: LOG_TARGET, "Mining thread {} on {} stopped", miner, mining_algorithm);
|
||||
println!("Mining thread {} on {} stopped", miner, mining_algorithm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let reporting_frequency = if hasher.rx_factory.is_some() {
|
||||
REPORTING_FREQUENCY_RX
|
||||
} else {
|
||||
REPORTING_FREQUENCY_SHA3
|
||||
};
|
||||
if hasher.header.nonce % reporting_frequency == 0 {
|
||||
let res = sender.try_send(MiningReport {
|
||||
miner,
|
||||
difficulty,
|
||||
hashes: hasher.hashes,
|
||||
elapsed: start.elapsed(),
|
||||
header: None,
|
||||
height: hasher.height(),
|
||||
target_difficulty,
|
||||
});
|
||||
waker.wake_by_ref();
|
||||
trace!(target: LOG_TARGET, "Reporting from {} on {} result {:?}", miner, mining_algorithm, res);
|
||||
if let Err(TrySendError::Disconnected(_)) = res {
|
||||
info!(target: LOG_TARGET, "Mining thread {} on {} disconnected", miner, mining_algorithm);
|
||||
return;
|
||||
}
|
||||
/*if !(share_mode) {
|
||||
hasher.set_forward_timestamp(Utc::now().timestamp() as u64);
|
||||
}*/
|
||||
}
|
||||
//hasher.inc_nonce();
|
||||
}
|
||||
}
|
||||
|
||||
async fn validate_tip(
|
||||
node_conn: &mut BaseNodeGrpcClient,
|
||||
height: u64,
|
||||
) -> Result<(), MinerError> {
|
||||
let tip = node_conn
|
||||
.get_tip_info(minotari_app_grpc::tari_rpc::Empty {})
|
||||
.await?
|
||||
.into_inner();
|
||||
let longest_height = tip.clone().metadata.unwrap().best_block_height;
|
||||
if height <= longest_height {
|
||||
return Err(MinerError::MinerLostBlock(height));
|
||||
}
|
||||
if !tip.initial_sync_achieved || tip.metadata.is_none() {
|
||||
return Err(MinerError::NodeNotReady);
|
||||
}
|
||||
if height <= longest_height {
|
||||
return Err(MinerError::MinerLostBlock(height));
|
||||
}
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,735 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use std::{convert::TryFrom, sync::Arc, thread, time::Instant};
|
||||
|
||||
use futures::stream::StreamExt;
|
||||
use log::*;
|
||||
use minotari_app_grpc::{
|
||||
authentication::ClientAuthenticationInterceptor,
|
||||
conversions::transaction_output::grpc_output_with_payref,
|
||||
tari_rpc::{
|
||||
base_node_client::BaseNodeClient,
|
||||
pow_algo::PowAlgos,
|
||||
sha_p2_pool_client::ShaP2PoolClient,
|
||||
Block,
|
||||
GetNewBlockRequest,
|
||||
PowAlgo,
|
||||
SubmitBlockRequest,
|
||||
SubmitBlockResponse,
|
||||
},
|
||||
};
|
||||
use minotari_app_utilities::parse_miner_input::{
|
||||
prompt_for_base_node_address,
|
||||
prompt_for_p2pool_address,
|
||||
verify_base_node_grpc_mining_responses,
|
||||
wallet_payment_address,
|
||||
BaseNodeGrpcClient,
|
||||
ShaP2PoolGrpcClient,
|
||||
};
|
||||
use tari_common::{
|
||||
exit_codes::{ExitCode, ExitError},
|
||||
load_configuration,
|
||||
DefaultConfigLoader,
|
||||
MAX_GRPC_MESSAGE_SIZE,
|
||||
};
|
||||
use tari_common_types::{
|
||||
tari_address::TariAddress,
|
||||
types::{FixedHash, UncompressedPublicKey},
|
||||
};
|
||||
use tari_core::{
|
||||
blocks::BlockHeader,
|
||||
consensus::ConsensusManager,
|
||||
proof_of_work::{randomx_factory::RandomXFactory, PowAlgorithm},
|
||||
transactions::{
|
||||
generate_coinbase,
|
||||
tari_amount::MicroMinotari,
|
||||
transaction_components::{
|
||||
payment_id::{PaymentId, TxType},
|
||||
CoinBaseExtra,
|
||||
},
|
||||
transaction_key_manager::{create_memory_db_key_manager, MemoryDbKeyManager},
|
||||
},
|
||||
};
|
||||
use tari_utilities::hex::Hex;
|
||||
use tokio::{sync::Mutex, time::sleep};
|
||||
use tonic::transport::{Certificate, ClientTlsConfig, Endpoint};
|
||||
use zmq::{Context as ZmqContext, Socket, SUB};
|
||||
use anyhow::anyhow;
|
||||
use anyhow::{Context, Result};
|
||||
use crate::{
|
||||
cli::Cli,
|
||||
config::MinerConfig,
|
||||
errors::{err_empty, MinerError},
|
||||
miner::{Miner, MiningReport},
|
||||
stratum::stratum_controller::controller::Controller,
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
pub const LOG_TARGET: &str = "minotari::miner::main";
|
||||
pub const LOG_TARGET_FILE: &str = "minotari::logging::miner::main";
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub async fn start_miner(cli: Cli) -> Result<(), ExitError> {
|
||||
let config_path = cli.common.config_path();
|
||||
let cfg = load_configuration(
|
||||
config_path.as_path(),
|
||||
true,
|
||||
cli.non_interactive_mode,
|
||||
&cli,
|
||||
cli.common.network,
|
||||
)?;
|
||||
let mut config = MinerConfig::load_from(&cfg).expect("Failed to load config");
|
||||
config.set_base_path(cli.common.get_base_path());
|
||||
|
||||
debug!(target: LOG_TARGET_FILE, "{:?}", config);
|
||||
let key_manager = create_memory_db_key_manager().map_err(|err| {
|
||||
ExitError::new(
|
||||
ExitCode::KeyManagerServiceError,
|
||||
"'wallet_payment_address' ".to_owned() + &err.to_string(),
|
||||
)
|
||||
})?;
|
||||
let wallet_payment_address = wallet_payment_address(config.wallet_payment_address.clone(), config.network)
|
||||
.map_err(|err| {
|
||||
ExitError::new(
|
||||
ExitCode::WalletPaymentAddress,
|
||||
"'wallet_payment_address' ".to_owned() + &err.to_string(),
|
||||
)
|
||||
})?;
|
||||
debug!(target: LOG_TARGET_FILE, "wallet_payment_address: {}", wallet_payment_address);
|
||||
let consensus_manager = ConsensusManager::builder(config.network)
|
||||
.build()
|
||||
.map_err(|err| ExitError::new(ExitCode::ConsensusManagerBuilderError, err.to_string()))?;
|
||||
|
||||
if !config.stratum_mining_wallet_address.is_empty() && !config.stratum_mining_pool_address.is_empty() {
|
||||
let url = config.stratum_mining_pool_address.clone();
|
||||
let mut miner_address = config.stratum_mining_wallet_address.clone();
|
||||
let _unused = UncompressedPublicKey::from_hex(&miner_address).map_err(|_| {
|
||||
ExitError::new(
|
||||
ExitCode::ConfigError,
|
||||
"Miner is not configured with a valid wallet address.",
|
||||
)
|
||||
})?;
|
||||
if !config.mining_worker_name.is_empty() {
|
||||
miner_address += &format!("{}{}", ".", config.mining_worker_name);
|
||||
}
|
||||
let mut mc = Controller::new(config.num_mining_threads).map_err(|e| {
|
||||
debug!(target: LOG_TARGET_FILE, "Error loading mining controller: {}", e);
|
||||
ExitError::new(
|
||||
ExitCode::UnknownError,
|
||||
format!("Error loading mining controller: {}", e),
|
||||
)
|
||||
})?;
|
||||
let cc = crate::stratum::controller::Controller::new(&url, Some(miner_address), None, None, mc.tx.clone())
|
||||
.map_err(|e| {
|
||||
debug!(
|
||||
target: LOG_TARGET_FILE,
|
||||
"Error loading stratum client controller: {:?}", e
|
||||
);
|
||||
ExitError::new(
|
||||
ExitCode::UnknownError,
|
||||
format!("Error loading mining controller: {}", e),
|
||||
)
|
||||
})?;
|
||||
mc.set_client_tx(cc.tx.clone());
|
||||
|
||||
let _join_handle = thread::Builder::new()
|
||||
.name("client_controller".to_string())
|
||||
.spawn(move || {
|
||||
cc.run();
|
||||
});
|
||||
|
||||
mc.run()
|
||||
.await
|
||||
.map_err(|err| ExitError::new(ExitCode::UnknownError, format!("Stratum error: {:?}", err)))?;
|
||||
|
||||
Ok(())
|
||||
} else {
|
||||
let node_clients = connect(&config)
|
||||
.await
|
||||
.map_err(|e| ExitError::new(ExitCode::GrpcError, e.to_string()))?;
|
||||
let mut base_node_client = node_clients.base_node_client;
|
||||
let mut p2pool_node_client = node_clients.p2pool_node_client;
|
||||
|
||||
if let Err(e) = verify_base_node_responses(&mut base_node_client, &config).await {
|
||||
if let MinerError::BaseNodeNotResponding(_) = e {
|
||||
error!(target: LOG_TARGET, "{}", e);
|
||||
println!();
|
||||
let msg = "Could not connect to the base node. \nAre the base node's gRPC mining methods allowed in \
|
||||
its 'config.toml'? Please ensure these methods are enabled in:\n \
|
||||
'grpc_server_allow_methods': \"get_new_block_template\", \"get_tip_info\", \
|
||||
\"get_new_block\", \"submit_block\"";
|
||||
println!("{}", msg);
|
||||
println!();
|
||||
return Err(ExitError::new(ExitCode::GrpcError, e.to_string()));
|
||||
}
|
||||
}
|
||||
config.zmq_publisher_port = 11113;
|
||||
config.zmq_subscriber_port = 11112;
|
||||
println!("pub port:{}, sub port {}", config.zmq_publisher_port, config.zmq_subscriber_port);
|
||||
let zmq_context = ZmqContext::new();
|
||||
let publisher_socket = zmq_context
|
||||
.socket(zmq::PUB)
|
||||
.map_err(|e| anyhow!("ZMQ publisher error: {}", e))?;
|
||||
|
||||
let publisher_addr = format!("tcp://0.0.0.0:{}", config.zmq_publisher_port);
|
||||
println!("publisher_addr:{}",publisher_addr);
|
||||
publisher_socket
|
||||
.bind(&publisher_addr)
|
||||
.map_err(|e| anyhow!("ZMQ bind error: {}", e))?;
|
||||
|
||||
let subscriber_socket = zmq_context
|
||||
.socket(SUB)
|
||||
.context("Failed to create SUB socket")?;
|
||||
let subscriber_addr = format!("tcp://172.17.0.1:{}", config.zmq_subscriber_port);
|
||||
println!("subscriber_addr:{}",subscriber_addr);
|
||||
subscriber_socket
|
||||
.connect(&subscriber_addr)
|
||||
.context("Failed to connect to PUB server")?;
|
||||
subscriber_socket
|
||||
.set_subscribe(b"")
|
||||
.context("Failed to subscribe to all messages")?;
|
||||
|
||||
let publisher = Arc::new(Mutex::new(publisher_socket));
|
||||
let subscriber = Arc::new(Mutex::new(subscriber_socket));
|
||||
|
||||
let mut blocks_found: u64 = 0;
|
||||
loop {
|
||||
debug!(target: LOG_TARGET, "Starting new mining cycle");
|
||||
match mining_cycle(
|
||||
&mut base_node_client,
|
||||
p2pool_node_client.clone(),
|
||||
&config,
|
||||
&cli,
|
||||
&key_manager,
|
||||
&wallet_payment_address,
|
||||
&consensus_manager,
|
||||
publisher.clone(),
|
||||
subscriber.clone(),
|
||||
)
|
||||
.await
|
||||
{
|
||||
err @ Err(MinerError::GrpcConnection(_)) | err @ Err(MinerError::GrpcStatus(_)) => {
|
||||
// Any GRPC error we will try to reconnect with a standard delay
|
||||
error!(target: LOG_TARGET, "Connection error: {:?}", err);
|
||||
loop {
|
||||
info!(target: LOG_TARGET, "Holding for {:?}", config.wait_timeout());
|
||||
sleep(config.wait_timeout()).await;
|
||||
match connect(&config).await {
|
||||
Ok(nc) => {
|
||||
base_node_client = nc.base_node_client;
|
||||
p2pool_node_client = nc.p2pool_node_client;
|
||||
break;
|
||||
},
|
||||
Err(err) => {
|
||||
error!(target: LOG_TARGET, "Connection error: {:?}", err);
|
||||
continue;
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(MinerError::MineUntilHeightReached(h)) => {
|
||||
warn!(
|
||||
target: LOG_TARGET,
|
||||
"Prescribed blockchain height {} reached. Aborting ...", h
|
||||
);
|
||||
return Ok(());
|
||||
},
|
||||
Err(MinerError::MinerLostBlock(h)) => {
|
||||
warn!(
|
||||
target: LOG_TARGET,
|
||||
"Height {} already mined by other node. Restarting ...", h
|
||||
);
|
||||
},
|
||||
Err(err) => {
|
||||
error!(target: LOG_TARGET, "Error: {:?}", err);
|
||||
sleep(config.wait_timeout()).await;
|
||||
},
|
||||
Ok(submitted) => {
|
||||
info!(target: LOG_TARGET, "💰 Found block");
|
||||
|
||||
if submitted {
|
||||
blocks_found += 1;
|
||||
}
|
||||
println!("blocks_found: {} {}", blocks_found, cli.miner_max_blocks.unwrap_or(0));
|
||||
if let Some(max_blocks) = cli.miner_max_blocks {
|
||||
if blocks_found >= max_blocks {
|
||||
println!("blocks_found >= max_blocks exit");
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NodeClientResult {
|
||||
base_node_client: BaseNodeGrpcClient,
|
||||
p2pool_node_client: Option<ShaP2PoolGrpcClient>,
|
||||
}
|
||||
|
||||
async fn connect(config: &MinerConfig) -> Result<NodeClientResult, MinerError> {
|
||||
// always connect to base node first
|
||||
let base_node_client = match connect_base_node(config).await {
|
||||
Ok(client) => client,
|
||||
Err(e) => {
|
||||
error!(target: LOG_TARGET, "Could not connect to base node: {}", e);
|
||||
let msg = "Could not connect to base node. \nIs the base node's gRPC running? Try running it with \
|
||||
`--enable-grpc` or enable it in the config.";
|
||||
println!("{}", msg);
|
||||
return Err(e);
|
||||
},
|
||||
};
|
||||
|
||||
// init client to sha p2pool grpc if enabled
|
||||
let mut p2pool_node_client = None;
|
||||
if config.sha_p2pool_enabled {
|
||||
p2pool_node_client = match connect_sha_p2pool(config).await {
|
||||
Ok(client) => Some(client),
|
||||
Err(e) => {
|
||||
error!(target: LOG_TARGET, "Could not connect to base node: {}", e);
|
||||
let msg = "Could not connect to base node. \nIs the base node's gRPC running? Try running it with \
|
||||
`--enable-grpc` or enable it in the config.";
|
||||
println!("{}", msg);
|
||||
return Err(e);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
Ok(NodeClientResult {
|
||||
base_node_client,
|
||||
p2pool_node_client,
|
||||
})
|
||||
}
|
||||
|
||||
async fn connect_sha_p2pool(config: &MinerConfig) -> Result<ShaP2PoolGrpcClient, MinerError> {
|
||||
let p2pool_node_addr;
|
||||
if let Some(ref a) = config.base_node_grpc_address {
|
||||
p2pool_node_addr = a.clone();
|
||||
} else {
|
||||
p2pool_node_addr = prompt_for_p2pool_address()?;
|
||||
}
|
||||
|
||||
info!(target: LOG_TARGET, "👛 Connecting to p2pool node at {}", p2pool_node_addr);
|
||||
let mut endpoint = Endpoint::new(p2pool_node_addr)?;
|
||||
|
||||
if let Some(domain_name) = config.base_node_grpc_tls_domain_name.as_ref() {
|
||||
let pem = tokio::fs::read(config.config_dir.join(&config.base_node_grpc_ca_cert_filename))
|
||||
.await
|
||||
.map_err(|e| MinerError::TlsConnectionError(e.to_string()))?;
|
||||
let ca = Certificate::from_pem(pem);
|
||||
|
||||
let tls = ClientTlsConfig::new().ca_certificate(ca).domain_name(domain_name);
|
||||
endpoint = endpoint
|
||||
.tls_config(tls)
|
||||
.map_err(|e| MinerError::TlsConnectionError(e.to_string()))?;
|
||||
}
|
||||
|
||||
let channel = endpoint
|
||||
.connect()
|
||||
.await
|
||||
.map_err(|e| MinerError::TlsConnectionError(e.to_string()))?;
|
||||
let node_conn = ShaP2PoolClient::with_interceptor(
|
||||
channel,
|
||||
ClientAuthenticationInterceptor::create(&config.base_node_grpc_authentication)?,
|
||||
)
|
||||
.max_encoding_message_size(MAX_GRPC_MESSAGE_SIZE)
|
||||
.max_decoding_message_size(MAX_GRPC_MESSAGE_SIZE);
|
||||
|
||||
Ok(node_conn)
|
||||
}
|
||||
|
||||
async fn connect_base_node(config: &MinerConfig) -> Result<BaseNodeGrpcClient, MinerError> {
|
||||
let base_node_addr;
|
||||
if let Some(ref a) = config.base_node_grpc_address {
|
||||
base_node_addr = a.clone();
|
||||
} else {
|
||||
base_node_addr = prompt_for_base_node_address(config.network)?;
|
||||
}
|
||||
|
||||
info!(target: LOG_TARGET, "👛 Connecting to base node at {}", base_node_addr);
|
||||
let mut endpoint = Endpoint::new(base_node_addr)?;
|
||||
|
||||
if let Some(domain_name) = config.base_node_grpc_tls_domain_name.as_ref() {
|
||||
let pem = tokio::fs::read(config.config_dir.join(&config.base_node_grpc_ca_cert_filename))
|
||||
.await
|
||||
.map_err(|e| MinerError::TlsConnectionError(e.to_string()))?;
|
||||
let ca = Certificate::from_pem(pem);
|
||||
|
||||
let tls = ClientTlsConfig::new().ca_certificate(ca).domain_name(domain_name);
|
||||
endpoint = endpoint
|
||||
.tls_config(tls)
|
||||
.map_err(|e| MinerError::TlsConnectionError(e.to_string()))?;
|
||||
}
|
||||
|
||||
let channel = endpoint
|
||||
.connect()
|
||||
.await
|
||||
.map_err(|e| MinerError::TlsConnectionError(e.to_string()))?;
|
||||
let node_conn = BaseNodeClient::with_interceptor(
|
||||
channel,
|
||||
ClientAuthenticationInterceptor::create(&config.base_node_grpc_authentication)?,
|
||||
)
|
||||
.max_encoding_message_size(MAX_GRPC_MESSAGE_SIZE)
|
||||
.max_decoding_message_size(MAX_GRPC_MESSAGE_SIZE);
|
||||
|
||||
Ok(node_conn)
|
||||
}
|
||||
|
||||
async fn verify_base_node_responses(
|
||||
node_conn: &mut BaseNodeGrpcClient,
|
||||
config: &MinerConfig,
|
||||
) -> Result<(), MinerError> {
|
||||
if let Err(e) = verify_base_node_grpc_mining_responses(node_conn, config.pow_algo_request()).await {
|
||||
return Err(MinerError::BaseNodeNotResponding(e));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
struct GetNewBlockResponse {
|
||||
block: Block,
|
||||
target_difficulty: u64,
|
||||
vm_key: FixedHash,
|
||||
}
|
||||
|
||||
/// Gets a new block from base node or p2pool node if its enabled in config
|
||||
async fn get_new_block(
|
||||
base_node_client: &mut BaseNodeGrpcClient,
|
||||
sha_p2pool_client: Arc<Mutex<Option<ShaP2PoolGrpcClient>>>,
|
||||
config: &MinerConfig,
|
||||
cli: &Cli,
|
||||
key_manager: &MemoryDbKeyManager,
|
||||
wallet_payment_address: &TariAddress,
|
||||
consensus_manager: &ConsensusManager,
|
||||
) -> Result<GetNewBlockResponse, MinerError> {
|
||||
if config.sha_p2pool_enabled {
|
||||
if let Some(client) = sha_p2pool_client.lock().await.as_mut() {
|
||||
return get_new_block_p2pool_node(config, client, wallet_payment_address).await;
|
||||
}
|
||||
}
|
||||
|
||||
get_new_block_base_node(
|
||||
base_node_client,
|
||||
config,
|
||||
cli,
|
||||
key_manager,
|
||||
wallet_payment_address,
|
||||
consensus_manager,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn get_new_block_base_node(
|
||||
base_node_client: &mut BaseNodeGrpcClient,
|
||||
config: &MinerConfig,
|
||||
cli: &Cli,
|
||||
key_manager: &MemoryDbKeyManager,
|
||||
wallet_payment_address: &TariAddress,
|
||||
consensus_manager: &ConsensusManager,
|
||||
) -> Result<GetNewBlockResponse, MinerError> {
|
||||
debug!(target: LOG_TARGET, "Getting new block template");
|
||||
let template_response = base_node_client
|
||||
.get_new_block_template(config.pow_algo_request())
|
||||
.await?
|
||||
.into_inner();
|
||||
let mut block_template = template_response
|
||||
.new_block_template
|
||||
.clone()
|
||||
.ok_or_else(|| err_empty("new_block_template"))?;
|
||||
let height = block_template
|
||||
.header
|
||||
.as_ref()
|
||||
.ok_or_else(|| err_empty("header"))?
|
||||
.height;
|
||||
|
||||
if config.mine_on_tip_only {
|
||||
debug!(
|
||||
target: LOG_TARGET,
|
||||
"Checking if base node is synced, because mine_on_tip_only is true"
|
||||
);
|
||||
validate_tip(base_node_client, height, cli.mine_until_height).await?;
|
||||
}
|
||||
|
||||
debug!(target: LOG_TARGET, "Getting coinbase");
|
||||
let miner_data = template_response.miner_data.ok_or_else(|| err_empty("miner_data"))?;
|
||||
let fee = MicroMinotari::from(miner_data.total_fees);
|
||||
let reward = MicroMinotari::from(miner_data.reward);
|
||||
let (coinbase_output, coinbase_kernel) = generate_coinbase(
|
||||
fee,
|
||||
reward,
|
||||
height,
|
||||
&CoinBaseExtra::try_from(config.coinbase_extra.as_bytes().to_vec())?,
|
||||
key_manager,
|
||||
wallet_payment_address,
|
||||
true,
|
||||
consensus_manager.consensus_constants(height),
|
||||
config.range_proof_type,
|
||||
PaymentId::Open {
|
||||
user_data: vec![],
|
||||
tx_type: TxType::Coinbase,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.map_err(|e| MinerError::CoinbaseError(e.to_string()))?;
|
||||
debug!(target: LOG_TARGET, "Coinbase kernel: {}", coinbase_kernel);
|
||||
debug!(target: LOG_TARGET, "Coinbase output: {}", coinbase_output);
|
||||
|
||||
let body = block_template
|
||||
.body
|
||||
.as_mut()
|
||||
.ok_or_else(|| err_empty("new_block_template.body"))?;
|
||||
let grpc_output =
|
||||
grpc_output_with_payref(coinbase_output.clone(), None).map_err(|e| MinerError::Conversion(e.to_string()))?;
|
||||
|
||||
body.outputs.push(grpc_output);
|
||||
body.kernels.push(coinbase_kernel.into());
|
||||
let target_difficulty = miner_data.target_difficulty;
|
||||
|
||||
debug!(target: LOG_TARGET, "Asking base node to assemble the MMR roots");
|
||||
let block_result = base_node_client.get_new_block(block_template).await?.into_inner();
|
||||
|
||||
Ok(GetNewBlockResponse {
|
||||
block: block_result.block.ok_or_else(|| err_empty("block"))?,
|
||||
target_difficulty,
|
||||
vm_key: FixedHash::try_from(block_result.vm_key).map_err(|_| MinerError::Conversion("vm_key".to_string()))?,
|
||||
})
|
||||
}
|
||||
|
||||
async fn get_new_block_p2pool_node(
|
||||
config: &MinerConfig,
|
||||
sha_p2pool_client: &mut ShaP2PoolGrpcClient,
|
||||
wallet_payment_address: &TariAddress,
|
||||
) -> Result<GetNewBlockResponse, MinerError> {
|
||||
let pow_algo = PowAlgo {
|
||||
pow_algo: PowAlgos::Sha3x.into(),
|
||||
};
|
||||
let coinbase_extra = if config.coinbase_extra.trim().is_empty() {
|
||||
String::new()
|
||||
} else {
|
||||
config.coinbase_extra.clone()
|
||||
};
|
||||
let block_result = sha_p2pool_client
|
||||
.get_new_block(GetNewBlockRequest {
|
||||
pow: Some(pow_algo),
|
||||
coinbase_extra,
|
||||
wallet_payment_address: wallet_payment_address.to_base58(),
|
||||
})
|
||||
.await?
|
||||
.into_inner();
|
||||
let new_block_result = block_result.block.ok_or_else(|| err_empty("block result"))?;
|
||||
let block = new_block_result.block.ok_or_else(|| err_empty("block response"))?;
|
||||
Ok(GetNewBlockResponse {
|
||||
block,
|
||||
target_difficulty: block_result.target_difficulty,
|
||||
vm_key: FixedHash::zero(),
|
||||
})
|
||||
}
|
||||
|
||||
async fn submit_block(
|
||||
config: &MinerConfig,
|
||||
base_node_client: &mut BaseNodeGrpcClient,
|
||||
sha_p2pool_client: Option<&mut ShaP2PoolGrpcClient>,
|
||||
block: Block,
|
||||
wallet_payment_address: &TariAddress,
|
||||
) -> Result<SubmitBlockResponse, MinerError> {
|
||||
if config.sha_p2pool_enabled {
|
||||
if let Some(client) = sha_p2pool_client {
|
||||
return Ok(client
|
||||
.submit_block(SubmitBlockRequest {
|
||||
block: Some(block),
|
||||
wallet_payment_address: wallet_payment_address.to_hex(),
|
||||
})
|
||||
.await
|
||||
.map_err(MinerError::GrpcStatus)?
|
||||
.into_inner());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(base_node_client
|
||||
.submit_block(block)
|
||||
.await
|
||||
.map_err(MinerError::GrpcStatus)?
|
||||
.into_inner())
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
async fn mining_cycle(
|
||||
base_node_client: &mut BaseNodeGrpcClient,
|
||||
sha_p2pool_client: Option<ShaP2PoolGrpcClient>,
|
||||
config: &MinerConfig,
|
||||
cli: &Cli,
|
||||
key_manager: &MemoryDbKeyManager,
|
||||
wallet_payment_address: &TariAddress,
|
||||
consensus_manager: &ConsensusManager,
|
||||
publisher_socket: Arc<Mutex<Socket>>,
|
||||
subscriber_socket: Arc<Mutex<Socket>>,
|
||||
) -> Result<bool, MinerError> {
|
||||
let sha_p2pool_client = Arc::new(Mutex::new(sha_p2pool_client));
|
||||
let block_result = get_new_block(
|
||||
base_node_client,
|
||||
sha_p2pool_client.clone(),
|
||||
config,
|
||||
cli,
|
||||
key_manager,
|
||||
wallet_payment_address,
|
||||
consensus_manager,
|
||||
)
|
||||
.await?;
|
||||
let block = block_result.block;
|
||||
let header = block.clone().header.ok_or_else(|| err_empty("block.header"))?;
|
||||
|
||||
debug!(target: LOG_TARGET, "Initializing miner");
|
||||
|
||||
let rx_factory = if config.proof_of_work_algo == PowAlgorithm::RandomXT {
|
||||
Some(RandomXFactory::new(config.num_mining_threads))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut reports = Miner::init_mining(
|
||||
base_node_client.clone(),
|
||||
header.clone(),
|
||||
block_result.target_difficulty,
|
||||
config.num_mining_threads,
|
||||
false,
|
||||
block_result.vm_key,
|
||||
rx_factory,
|
||||
publisher_socket,
|
||||
subscriber_socket,
|
||||
);
|
||||
let mut reporting_timeout = Instant::now();
|
||||
let mut block_submitted = false;
|
||||
while let Some(report) = reports.next().await {
|
||||
if let Some(header) = report.header.clone() {
|
||||
let mut submit = true;
|
||||
if let Some(min_diff) = cli.miner_min_diff {
|
||||
if report.difficulty < min_diff {
|
||||
submit = false;
|
||||
debug!(
|
||||
target: LOG_TARGET_FILE,
|
||||
"Mined difficulty {} below minimum difficulty {}. Not submitting.", report.difficulty, min_diff
|
||||
);
|
||||
}
|
||||
}
|
||||
if let Some(max_diff) = cli.miner_max_diff {
|
||||
if report.difficulty > max_diff {
|
||||
submit = false;
|
||||
debug!(
|
||||
target: LOG_TARGET_FILE,
|
||||
"Mined difficulty {} greater than maximum difficulty {}. Not submitting.",
|
||||
report.difficulty,
|
||||
max_diff
|
||||
);
|
||||
}
|
||||
}
|
||||
if submit {
|
||||
// Mined a block fitting the difficulty
|
||||
let block_header = BlockHeader::try_from(header.clone()).map_err(MinerError::Conversion)?;
|
||||
debug!(
|
||||
target: LOG_TARGET,
|
||||
"Miner found block header {} with difficulty {:?}", block_header, report.difficulty,
|
||||
);
|
||||
println!(
|
||||
"Miner found block header {} with difficulty {:?}", block_header, report.difficulty,
|
||||
);
|
||||
let mut mined_block = block.clone();
|
||||
mined_block.header = Some(header);
|
||||
// 5. Sending block to the node
|
||||
submit_block(
|
||||
config,
|
||||
base_node_client,
|
||||
sha_p2pool_client.lock().await.as_mut(),
|
||||
mined_block,
|
||||
wallet_payment_address,
|
||||
)
|
||||
.await?;
|
||||
block_submitted = true;
|
||||
break;
|
||||
} else {
|
||||
display_report(&report, config.num_mining_threads).await;
|
||||
}
|
||||
} else {
|
||||
display_report(&report, config.num_mining_threads).await;
|
||||
}
|
||||
//if config.mine_on_tip_only && reporting_timeout.elapsed() > config.validate_tip_interval() {
|
||||
validate_tip(base_node_client, report.height, cli.mine_until_height).await?;
|
||||
reporting_timeout = Instant::now();
|
||||
//}
|
||||
}
|
||||
|
||||
// Not waiting for threads to stop, they should stop in a short while after `reports` dropped
|
||||
Ok(block_submitted)
|
||||
}
|
||||
|
||||
pub async fn display_report(report: &MiningReport, num_mining_threads: usize) {
|
||||
let mut hashrate = report.hashes as f64 / report.elapsed.as_secs() as f64;
|
||||
let display_string = if hashrate > 1_000_000.0 {
|
||||
hashrate /= 1_000_000.0;
|
||||
"MH/s"
|
||||
} else {
|
||||
hashrate /= 1_000.0;
|
||||
"KH/s"
|
||||
};
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"⛏ Miner {:0>2} reported {:.2}{} with total {:.2}{} over {} threads. Height: {}. Target: {})",
|
||||
report.miner,
|
||||
hashrate,
|
||||
display_string,
|
||||
hashrate * num_mining_threads as f64,
|
||||
display_string,
|
||||
num_mining_threads,
|
||||
report.height,
|
||||
report.target_difficulty,
|
||||
);
|
||||
}
|
||||
|
||||
/// If config
|
||||
async fn validate_tip(
|
||||
node_conn: &mut BaseNodeGrpcClient,
|
||||
height: u64,
|
||||
mine_until_height: Option<u64>,
|
||||
) -> Result<(), MinerError> {
|
||||
let tip = node_conn
|
||||
.get_tip_info(minotari_app_grpc::tari_rpc::Empty {})
|
||||
.await?
|
||||
.into_inner();
|
||||
let longest_height = tip.clone().metadata.unwrap().best_block_height;
|
||||
if let Some(height) = mine_until_height {
|
||||
if longest_height >= height {
|
||||
return Err(MinerError::MineUntilHeightReached(height));
|
||||
}
|
||||
}
|
||||
if height <= longest_height {
|
||||
return Err(MinerError::MinerLostBlock(height));
|
||||
}
|
||||
if !tip.initial_sync_achieved || tip.metadata.is_none() {
|
||||
return Err(MinerError::NodeNotReady);
|
||||
}
|
||||
if height <= longest_height {
|
||||
return Err(MinerError::MinerLostBlock(height));
|
||||
}
|
||||
Ok(())
|
||||
}
|
|
@ -0,0 +1,419 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use std::{
|
||||
io::{BufRead, ErrorKind, Write},
|
||||
sync::mpsc,
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use log::*;
|
||||
|
||||
use crate::stratum::{error::Error, stratum_types as types, stream::Stream};
|
||||
|
||||
pub const LOG_TARGET: &str = "minotari::miner::stratum::controller";
|
||||
pub const LOG_TARGET_FILE: &str = "minotari::logging::miner::stratum::controller";
|
||||
|
||||
pub struct Controller {
|
||||
server_url: String,
|
||||
server_login: Option<String>,
|
||||
server_password: Option<String>,
|
||||
server_tls_enabled: Option<bool>,
|
||||
stream: Option<Stream>,
|
||||
rx: mpsc::Receiver<types::client_message::ClientMessage>,
|
||||
pub tx: mpsc::Sender<types::client_message::ClientMessage>,
|
||||
miner_tx: mpsc::Sender<types::miner_message::MinerMessage>,
|
||||
last_request_id: String,
|
||||
}
|
||||
|
||||
// fn invalid_error_response() -> types::RpcError {
|
||||
// types::RpcError {
|
||||
// code: 0,
|
||||
// message: "Invalid error response received".to_owned(),
|
||||
// }
|
||||
// }
|
||||
|
||||
impl Controller {
|
||||
pub fn new(
|
||||
server_url: &str,
|
||||
server_login: Option<String>,
|
||||
server_password: Option<String>,
|
||||
server_tls_enabled: Option<bool>,
|
||||
miner_tx: mpsc::Sender<types::miner_message::MinerMessage>,
|
||||
) -> Result<Controller, Error> {
|
||||
let (tx, rx) = mpsc::channel::<types::client_message::ClientMessage>();
|
||||
Ok(Controller {
|
||||
server_url: server_url.to_string(),
|
||||
server_login,
|
||||
server_password,
|
||||
server_tls_enabled,
|
||||
stream: None,
|
||||
tx,
|
||||
rx,
|
||||
miner_tx,
|
||||
last_request_id: "".to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_connect(&mut self) -> Result<(), Error> {
|
||||
self.stream = None;
|
||||
let stream = Stream::try_connect(&self.server_url, self.server_tls_enabled)?;
|
||||
self.stream = Some(stream);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn stream(&mut self) -> Result<&mut Stream, Error> {
|
||||
self.stream.as_mut().ok_or(Error::NotConnected)
|
||||
}
|
||||
|
||||
fn read_message(&mut self) -> Result<Option<String>, Error> {
|
||||
let mut line = String::new();
|
||||
match self.stream()?.read_line(&mut line) {
|
||||
Ok(_) => {
|
||||
// stream is not returning a proper error on disconnect
|
||||
if line.is_empty() {
|
||||
return Err(Error::Connection("broken pipe".to_string()));
|
||||
}
|
||||
Ok(Some(line))
|
||||
},
|
||||
Err(ref e) if e.kind() == ErrorKind::BrokenPipe => Err(Error::Connection("broken pipe".to_string())),
|
||||
Err(ref e) if e.kind() == ErrorKind::WouldBlock => Ok(None),
|
||||
Err(e) => {
|
||||
error!(target: LOG_TARGET, "Communication error with stratum server: {}", e);
|
||||
Err(Error::Connection("broken pipe".to_string()))
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn send_message(&mut self, message: &str) -> Result<(), Error> {
|
||||
let stream = self.stream()?;
|
||||
debug!(target: LOG_TARGET_FILE, "sending request: {}", message);
|
||||
stream.write_all(message.as_bytes())?;
|
||||
stream.write_all(b"\n")?;
|
||||
stream.flush()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn send_message_get_job_template(&mut self) -> Result<(), Error> {
|
||||
let params = types::worker_identifier::WorkerIdentifier {
|
||||
id: self.last_request_id.clone(),
|
||||
};
|
||||
let req = types::rpc_request::RpcRequest {
|
||||
id: Some(self.last_request_id.clone()),
|
||||
jsonrpc: "2.0".to_string(),
|
||||
method: "getjob".to_string(),
|
||||
params: Some(serde_json::to_value(params)?),
|
||||
};
|
||||
let req_str = serde_json::to_string(&req)?;
|
||||
self.send_message(&req_str)
|
||||
}
|
||||
|
||||
fn send_login(&mut self) -> Result<(), Error> {
|
||||
// only send the login request if a login string is configured
|
||||
let login_str = match self.server_login.clone() {
|
||||
None => "".to_string(),
|
||||
Some(server_login) => server_login,
|
||||
};
|
||||
if login_str.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
let password_str = match self.server_password.clone() {
|
||||
None => "".to_string(),
|
||||
Some(server_password) => server_password,
|
||||
};
|
||||
let params = types::login_params::LoginParams {
|
||||
login: login_str,
|
||||
pass: password_str,
|
||||
agent: "minotari-miner".to_string(),
|
||||
};
|
||||
let req_id = self.last_request_id.to_string();
|
||||
let req = types::rpc_request::RpcRequest {
|
||||
id: if req_id.is_empty() {
|
||||
Some("0".to_string())
|
||||
} else {
|
||||
Some(req_id)
|
||||
},
|
||||
jsonrpc: "2.0".to_string(),
|
||||
method: "login".to_string(),
|
||||
params: Some(serde_json::to_value(params)?),
|
||||
};
|
||||
let req_str = serde_json::to_string(&req)?;
|
||||
self.send_message(&req_str)
|
||||
}
|
||||
|
||||
fn send_keepalive(&mut self) -> Result<(), Error> {
|
||||
let req = types::rpc_request::RpcRequest {
|
||||
id: Some(self.last_request_id.to_string()),
|
||||
jsonrpc: "2.0".to_string(),
|
||||
method: "keepalive".to_string(),
|
||||
params: None,
|
||||
};
|
||||
let req_str = serde_json::to_string(&req)?;
|
||||
self.send_message(&req_str)
|
||||
}
|
||||
|
||||
fn send_message_submit(&mut self, job_id: u64, hash: String, nonce: u64) -> Result<(), Error> {
|
||||
debug!(
|
||||
target: LOG_TARGET,
|
||||
"Submitting share with hash {} and nonce {}", hash, nonce
|
||||
);
|
||||
let params_in = types::submit_params::SubmitParams {
|
||||
id: self.last_request_id.to_string(),
|
||||
job_id,
|
||||
hash,
|
||||
nonce,
|
||||
};
|
||||
let params = serde_json::to_string(¶ms_in)?;
|
||||
let req = types::rpc_request::RpcRequest {
|
||||
id: Some(self.last_request_id.to_string()),
|
||||
jsonrpc: "2.0".to_string(),
|
||||
method: "submit".to_string(),
|
||||
params: Some(serde_json::from_str(¶ms)?),
|
||||
};
|
||||
let req_str = serde_json::to_string(&req)?;
|
||||
self.send_message(&req_str)
|
||||
}
|
||||
|
||||
fn send_miner_job(&mut self, job: types::job_params::JobParams) -> Result<(), Error> {
|
||||
let blob_bytes =
|
||||
base64::decode(&job.blob).map_err(|_| Error::General("Invalid base64 byte string received".to_string()))?;
|
||||
let miner_message = types::miner_message::MinerMessage::ReceivedJob(
|
||||
job.height,
|
||||
job.job_id.parse::<u64>()?,
|
||||
job.target.parse::<u64>()?,
|
||||
blob_bytes,
|
||||
);
|
||||
self.miner_tx.send(miner_message).map_err(Error::from)
|
||||
}
|
||||
|
||||
fn send_miner_stop(&mut self) -> Result<(), Error> {
|
||||
let miner_message = types::miner_message::MinerMessage::StopJob;
|
||||
self.miner_tx.send(miner_message).map_err(Error::from)
|
||||
}
|
||||
|
||||
fn send_miner_resume(&mut self) -> Result<(), Error> {
|
||||
let miner_message = types::miner_message::MinerMessage::ResumeJob;
|
||||
self.miner_tx.send(miner_message).map_err(Error::from)
|
||||
}
|
||||
|
||||
pub fn handle_request(&mut self, req: types::rpc_request::RpcRequest) -> Result<(), Error> {
|
||||
debug!(target: LOG_TARGET_FILE, "Received request type: {}", req.method);
|
||||
match req.method.as_str() {
|
||||
"job" => match req.params {
|
||||
None => Err(Error::Request("No params in job request".to_owned())),
|
||||
Some(params) => {
|
||||
let job = serde_json::from_value::<types::job_params::JobParams>(params)?;
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"Got a new job for height {} with target difficulty {}", job.height, job.target
|
||||
);
|
||||
self.send_miner_job(job)
|
||||
},
|
||||
},
|
||||
_ => Err(Error::Request("Unknown method".to_owned())),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_error(&mut self, error: types::rpc_error::RpcError) {
|
||||
if [-1, 24].contains(&error.code) {
|
||||
// unauthorized
|
||||
let _result = self.send_login();
|
||||
} else if [21, 20, 22, 23, 25].contains(&error.code) {
|
||||
// problem with template
|
||||
let _result = self.send_message_get_job_template();
|
||||
} else {
|
||||
// unhandled
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn handle_response(&mut self, res: types::rpc_response::RpcResponse) -> Result<(), Error> {
|
||||
debug!(target: LOG_TARGET_FILE, "Received response with id: {}", res.id);
|
||||
match res.result {
|
||||
Some(result) => {
|
||||
let login_response = serde_json::from_value::<types::login_response::LoginResponse>(result.clone());
|
||||
if let Ok(st) = login_response {
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"Successful login to server, worker identifier is {}", st.id
|
||||
);
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"Got a new job for height {} with target difficulty {}", st.job.height, st.job.target
|
||||
);
|
||||
self.last_request_id = st.id;
|
||||
let _result = self.send_miner_job(st.job);
|
||||
return Ok(());
|
||||
};
|
||||
let job_response = serde_json::from_value::<types::job_params::JobParams>(result.clone());
|
||||
if let Ok(st) = job_response {
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"Got a new job for height {} with target difficulty {}", st.height, st.target
|
||||
);
|
||||
let _result = self.send_miner_job(st);
|
||||
return Ok(());
|
||||
};
|
||||
let submit_response = serde_json::from_value::<types::submit_response::SubmitResponse>(result.clone());
|
||||
if let Ok(st) = submit_response {
|
||||
let error = st.error;
|
||||
if let Some(error) = error {
|
||||
// rejected share
|
||||
self.handle_error(error);
|
||||
warn!(target: LOG_TARGET, "Rejected");
|
||||
} else {
|
||||
// accepted share
|
||||
debug!(target: LOG_TARGET, "Share accepted: {:?}", st.status);
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
let rpc_response = serde_json::from_value::<types::rpc_response::RpcResponse>(result);
|
||||
if let Ok(st) = rpc_response {
|
||||
let error = st.error;
|
||||
if let Some(error) = error {
|
||||
self.handle_error(error);
|
||||
}
|
||||
return Ok(());
|
||||
} else {
|
||||
debug!(target: LOG_TARGET_FILE, "RPC Response: {:?}", rpc_response);
|
||||
};
|
||||
},
|
||||
None => {
|
||||
error!(target: LOG_TARGET, "RPC error: {:?}", res);
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[allow(clippy::cognitive_complexity)]
|
||||
pub fn run(mut self) {
|
||||
let server_read_interval = Duration::from_secs(1);
|
||||
let server_retry_interval = Duration::from_secs(5);
|
||||
let mut next_server_read = Instant::now() + server_read_interval;
|
||||
let mut next_server_retry = Instant::now();
|
||||
// Request the first job template
|
||||
thread::sleep(Duration::from_secs(1));
|
||||
let mut was_disconnected = true;
|
||||
loop {
|
||||
// Check our connection status, and try to correct if possible
|
||||
if self.stream.is_none() {
|
||||
if !was_disconnected {
|
||||
let _result = self.send_miner_stop();
|
||||
}
|
||||
was_disconnected = true;
|
||||
if Instant::now() > next_server_retry {
|
||||
if self.try_connect().is_err() {
|
||||
let status = format!(
|
||||
"Connection Status: Can't establish server connection to {}. Will retry every {} seconds",
|
||||
self.server_url,
|
||||
server_retry_interval.as_secs()
|
||||
);
|
||||
warn!("{}", status);
|
||||
self.stream = None;
|
||||
} else {
|
||||
let status = format!("Connection Status: Connected to server at {}.", self.server_url);
|
||||
info!(target: LOG_TARGET, "{}", status);
|
||||
}
|
||||
next_server_retry = Instant::now() + server_retry_interval;
|
||||
if self.stream.is_none() {
|
||||
thread::sleep(std::time::Duration::from_secs(1));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// get new job template
|
||||
if was_disconnected {
|
||||
was_disconnected = false;
|
||||
let _result = self.send_login();
|
||||
let _result = self.send_miner_resume();
|
||||
}
|
||||
// read messages from server
|
||||
if Instant::now() > next_server_read {
|
||||
match self.read_message() {
|
||||
Ok(Some(m)) => {
|
||||
// figure out what kind of message,
|
||||
// and dispatch appropriately
|
||||
debug!(target: LOG_TARGET_FILE, "Received message: {}", m);
|
||||
// Deserialize to see what type of object it is
|
||||
if let Ok(v) = serde_json::from_str::<serde_json::Value>(&m) {
|
||||
// Is this a response or request?
|
||||
if v["method"] == "job" {
|
||||
// this is a request
|
||||
match serde_json::from_str::<types::rpc_request::RpcRequest>(&m) {
|
||||
Err(e) => error!(target: LOG_TARGET, "Error parsing request {} : {:?}", m, e),
|
||||
Ok(request) => {
|
||||
if let Err(err) = self.handle_request(request) {
|
||||
error!(target: LOG_TARGET, "Error handling request {} : :{:?}", m, err)
|
||||
}
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// this is a response
|
||||
match serde_json::from_str::<types::rpc_response::RpcResponse>(&m) {
|
||||
Err(e) => error!(target: LOG_TARGET, "Error parsing response {} : {:?}", m, e),
|
||||
Ok(response) => {
|
||||
if let Err(err) = self.handle_response(response) {
|
||||
error!(target: LOG_TARGET, "Error handling response {} : :{:?}", m, err)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
error!(target: LOG_TARGET, "Error parsing message: {}", m)
|
||||
}
|
||||
},
|
||||
Ok(None) => {
|
||||
// noop, nothing to read for this interval
|
||||
},
|
||||
Err(e) => {
|
||||
error!(target: LOG_TARGET, "Error reading message: {:?}", e);
|
||||
self.stream = None;
|
||||
continue;
|
||||
},
|
||||
}
|
||||
next_server_read = Instant::now() + server_read_interval;
|
||||
}
|
||||
}
|
||||
|
||||
// Talk to the miner algorithm
|
||||
while let Some(message) = self.rx.try_iter().next() {
|
||||
debug!(target: LOG_TARGET_FILE, "Client received message: {:?}", message);
|
||||
let result = match message {
|
||||
types::client_message::ClientMessage::FoundSolution(job_id, hash, nonce) => {
|
||||
self.send_message_submit(job_id, hash, nonce)
|
||||
},
|
||||
types::client_message::ClientMessage::KeepAlive => self.send_keepalive(),
|
||||
types::client_message::ClientMessage::Shutdown => {
|
||||
debug!(target: LOG_TARGET_FILE, "Shutting down client controller");
|
||||
return;
|
||||
},
|
||||
};
|
||||
if let Err(e) = result {
|
||||
error!(target: LOG_TARGET, "Mining Controller Error {:?}", e);
|
||||
self.stream = None;
|
||||
}
|
||||
}
|
||||
thread::sleep(Duration::from_millis(10));
|
||||
} // loop
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use tari_max_size::MaxSizeBytesError;
|
||||
use thiserror::Error;
|
||||
|
||||
#[allow(clippy::enum_variant_names)]
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
#[error("Connection error: {0}")]
|
||||
Connection(String),
|
||||
#[error("Request error: {0}")]
|
||||
Request(String),
|
||||
// ResponseError(String),
|
||||
#[error("Failed to parse JSON: {0}")]
|
||||
Json(#[from] serde_json::error::Error),
|
||||
#[error("Blob is not a valid hex value: {0}")]
|
||||
Hex(#[from] hex::FromHexError),
|
||||
#[error("System time error: {0}")]
|
||||
Time(#[from] std::time::SystemTimeError),
|
||||
#[error("Client Tx is not set")]
|
||||
ClientTxNotSet,
|
||||
#[error("Io error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[error("Can't create TLS connector: {0}")]
|
||||
Tls(#[from] native_tls::Error),
|
||||
#[error("Can't establish TLS connection: {0}")]
|
||||
Tcp(#[from] Box<native_tls::HandshakeError<std::net::TcpStream>>),
|
||||
#[error("No connected stream")]
|
||||
NotConnected,
|
||||
#[error("Can't parse int: {0}")]
|
||||
Parse(#[from] std::num::ParseIntError),
|
||||
#[error("General error: {0}")]
|
||||
General(String),
|
||||
#[error("Missing Data error: {0}")]
|
||||
MissingData(String),
|
||||
#[error("Limit exceeded error: {0}")]
|
||||
MaxSizeBytesError(#[from] MaxSizeBytesError),
|
||||
}
|
||||
|
||||
impl<T> From<std::sync::PoisonError<T>> for Error {
|
||||
fn from(error: std::sync::PoisonError<T>) -> Self {
|
||||
Error::General(format!("Failed to get lock: {:?}", error))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<std::sync::mpsc::SendError<T>> for Error {
|
||||
fn from(error: std::sync::mpsc::SendError<T>) -> Self {
|
||||
Error::General(format!("Failed to send to a channel: {:?}", error))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<native_tls::HandshakeError<std::net::TcpStream>> for Error {
|
||||
fn from(error: native_tls::HandshakeError<std::net::TcpStream>) -> Self {
|
||||
Error::General(format!("TLS handshake error: {:?}", error))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
pub mod controller;
|
||||
pub mod error;
|
||||
pub mod stratum_controller;
|
||||
pub mod stratum_types;
|
||||
pub mod stream;
|
|
@ -0,0 +1,221 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use std::{convert::TryFrom, sync::mpsc, thread, time::SystemTime};
|
||||
|
||||
use borsh::BorshDeserialize;
|
||||
use futures::stream::StreamExt;
|
||||
use log::*;
|
||||
use minotari_app_grpc::tari_rpc::BlockHeader;
|
||||
//use tari_common_types::types::FixedHash;
|
||||
use tari_max_size::MaxSizeBytes;
|
||||
use tari_utilities::{hex::Hex, ByteArray};
|
||||
|
||||
|
||||
|
||||
use crate::{
|
||||
miner::Miner,
|
||||
run_miner::display_report,
|
||||
stratum::{error::Error, stratum_types as types},
|
||||
};
|
||||
|
||||
pub const LOG_TARGET: &str = "minotari::miner::stratum::controller";
|
||||
pub const LOG_TARGET_FILE: &str = "minotari::logging::miner::stratum::controller";
|
||||
|
||||
type CurrentBlob = MaxSizeBytes<{ 4 * 1024 * 1024 }>; // 4 MiB
|
||||
|
||||
pub struct Controller {
|
||||
rx: mpsc::Receiver<types::miner_message::MinerMessage>,
|
||||
pub tx: mpsc::Sender<types::miner_message::MinerMessage>,
|
||||
client_tx: Option<mpsc::Sender<types::client_message::ClientMessage>>,
|
||||
current_height: u64,
|
||||
current_job_id: u64,
|
||||
current_difficulty_target: u64,
|
||||
current_blob: CurrentBlob,
|
||||
current_header: Option<BlockHeader>,
|
||||
keep_alive_time: SystemTime,
|
||||
num_mining_threads: usize,
|
||||
|
||||
}
|
||||
|
||||
impl Controller {
|
||||
pub fn new(num_mining_threads: usize) -> Result<Controller, String> {
|
||||
let (tx, rx) = mpsc::channel::<types::miner_message::MinerMessage>();
|
||||
Ok(Controller {
|
||||
rx,
|
||||
tx,
|
||||
client_tx: None,
|
||||
current_height: 0,
|
||||
current_job_id: 0,
|
||||
current_difficulty_target: 0,
|
||||
current_blob: CurrentBlob::default(),
|
||||
current_header: None,
|
||||
keep_alive_time: SystemTime::now(),
|
||||
num_mining_threads,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn set_client_tx(&mut self, client_tx: mpsc::Sender<types::client_message::ClientMessage>) {
|
||||
self.client_tx = Some(client_tx);
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
pub async fn run(&mut self) -> Result<(), Error> {
|
||||
let mut miner: Option<Miner> = None;
|
||||
loop {
|
||||
// lets see if we need to change the state of the miner.
|
||||
while let Some(message) = self.rx.try_iter().next() {
|
||||
debug!(target: LOG_TARGET_FILE, "Miner received message: {:?}", message);
|
||||
match message {
|
||||
types::miner_message::MinerMessage::ReceivedJob(height, job_id, diff, blob) => {
|
||||
match self.should_we_update_job(height, job_id, diff, CurrentBlob::try_from(blob)?) {
|
||||
Ok(should_we_update) => {
|
||||
if should_we_update {
|
||||
/*let header = self
|
||||
.current_header
|
||||
.clone()
|
||||
.ok_or_else(|| Error::MissingData("Header".to_string()))?;
|
||||
if let Some(acive_miner) = miner.as_mut() {
|
||||
acive_miner.kill_threads();
|
||||
}
|
||||
|
||||
miner = Some(Miner::init_mining(header, self.current_difficulty_target, self.num_mining_threads, true, FixedHash::zero(), None, ));*/
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
debug!(
|
||||
target: LOG_TARGET_FILE,
|
||||
"Miner could not decipher miner message: {:?}", e
|
||||
);
|
||||
// lets wait a second before we try again
|
||||
thread::sleep(std::time::Duration::from_millis(1000));
|
||||
continue;
|
||||
},
|
||||
}
|
||||
},
|
||||
types::miner_message::MinerMessage::StopJob => {
|
||||
debug!(target: LOG_TARGET_FILE, "Stopping jobs");
|
||||
miner = None;
|
||||
continue;
|
||||
},
|
||||
types::miner_message::MinerMessage::ResumeJob => {
|
||||
debug!(target: LOG_TARGET_FILE, "Resuming jobs");
|
||||
miner = None;
|
||||
continue;
|
||||
},
|
||||
types::miner_message::MinerMessage::Shutdown => {
|
||||
debug!(
|
||||
target: LOG_TARGET_FILE,
|
||||
"Stopping jobs and Shutting down mining controller"
|
||||
);
|
||||
miner = None;
|
||||
},
|
||||
};
|
||||
}
|
||||
let mut submit = true;
|
||||
if let Some(reporter) = miner.as_mut() {
|
||||
if let Some(report) = (*reporter).next().await {
|
||||
if let Some(header) = report.header.clone() {
|
||||
if report.difficulty < self.current_difficulty_target {
|
||||
submit = false;
|
||||
debug!(
|
||||
target: LOG_TARGET_FILE,
|
||||
"Mined difficulty {} below target difficulty {}. Not submitting.",
|
||||
report.difficulty,
|
||||
self.current_difficulty_target
|
||||
);
|
||||
}
|
||||
|
||||
if submit {
|
||||
// Mined a block fitting the difficulty
|
||||
let block_header: tari_core::blocks::BlockHeader =
|
||||
tari_core::blocks::BlockHeader::try_from(header).map_err(Error::MissingData)?;
|
||||
let hash = block_header.hash().to_hex();
|
||||
info!(
|
||||
target: LOG_TARGET,
|
||||
"Miner found share with hash {}, nonce {} and difficulty {:?}",
|
||||
hash,
|
||||
block_header.nonce,
|
||||
report.difficulty
|
||||
);
|
||||
debug!(
|
||||
target: LOG_TARGET_FILE,
|
||||
"Miner found share with hash {}, difficulty {:?} and data {:?}",
|
||||
hash,
|
||||
report.difficulty,
|
||||
block_header
|
||||
);
|
||||
self.client_tx
|
||||
.as_mut()
|
||||
.ok_or_else(|| Error::Connection("No connection to pool".to_string()))?
|
||||
.send(types::client_message::ClientMessage::FoundSolution(
|
||||
self.current_job_id,
|
||||
hash,
|
||||
block_header.nonce,
|
||||
))?;
|
||||
self.keep_alive_time = SystemTime::now();
|
||||
continue;
|
||||
} else {
|
||||
display_report(&report, self.num_mining_threads).await;
|
||||
}
|
||||
} else {
|
||||
display_report(&report, self.num_mining_threads).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.keep_alive_time.elapsed()?.as_secs() >= 30 {
|
||||
self.keep_alive_time = SystemTime::now();
|
||||
self.client_tx
|
||||
.as_mut()
|
||||
.ok_or(Error::ClientTxNotSet)?
|
||||
.send(types::client_message::ClientMessage::KeepAlive)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn should_we_update_job(
|
||||
&mut self,
|
||||
height: u64,
|
||||
job_id: u64,
|
||||
diff: u64,
|
||||
blob: CurrentBlob,
|
||||
) -> Result<bool, Error> {
|
||||
if height != self.current_height ||
|
||||
job_id != self.current_job_id ||
|
||||
diff != self.current_difficulty_target ||
|
||||
blob != self.current_blob
|
||||
{
|
||||
self.current_height = height;
|
||||
self.current_job_id = job_id;
|
||||
self.current_blob = blob.clone();
|
||||
self.current_difficulty_target = diff;
|
||||
let mut buffer = blob.as_bytes();
|
||||
let tari_header: tari_core::blocks::BlockHeader = BorshDeserialize::deserialize(&mut buffer)
|
||||
.map_err(|_| Error::General("Byte Blob is not a valid header".to_string()))?;
|
||||
self.current_header = Some(minotari_app_grpc::tari_rpc::BlockHeader::from(tari_header));
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
pub(crate) mod controller;
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum ClientMessage {
|
||||
// job_id, hash, nonce
|
||||
FoundSolution(u64, String, u64),
|
||||
KeepAlive,
|
||||
Shutdown,
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
use tari_core::blocks::Block;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Job {
|
||||
pub job_id: u64,
|
||||
pub block: Option<Block>,
|
||||
pub target: u64,
|
||||
pub height: u64,
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct JobParams {
|
||||
pub job_id: String,
|
||||
pub blob: String,
|
||||
pub target: String,
|
||||
pub height: u64,
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use derivative::Derivative;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Derivative)]
|
||||
#[derivative(Debug)]
|
||||
pub struct LoginParams {
|
||||
pub login: String,
|
||||
#[derivative(Debug = "ignore")]
|
||||
#[allow(dead_code)]
|
||||
#[serde(skip_serializing)]
|
||||
pub pass: String,
|
||||
pub agent: String,
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::stratum::stratum_types::job_params::JobParams;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct LoginResponse {
|
||||
pub id: String,
|
||||
pub job: JobParams,
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum MinerMessage {
|
||||
// Height, Id, difficulty, HeaderBlob
|
||||
ReceivedJob(u64, u64, u64, Vec<u8>),
|
||||
ResumeJob,
|
||||
StopJob,
|
||||
Shutdown,
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
pub(crate) mod client_message;
|
||||
pub(crate) mod job;
|
||||
pub(crate) mod job_params;
|
||||
pub(crate) mod login_params;
|
||||
pub(crate) mod login_response;
|
||||
pub(crate) mod miner_message;
|
||||
pub(crate) mod rpc_error;
|
||||
pub(crate) mod rpc_request;
|
||||
pub(crate) mod rpc_response;
|
||||
pub(crate) mod submit_params;
|
||||
pub(crate) mod submit_response;
|
||||
pub(crate) mod worker_identifier;
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
pub struct RpcError {
|
||||
pub code: i32,
|
||||
pub message: String,
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct RpcRequest {
|
||||
pub id: Option<String>,
|
||||
pub jsonrpc: String,
|
||||
pub method: String,
|
||||
pub params: Option<Value>,
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::stratum::stratum_types::rpc_error::RpcError;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct RpcResponse {
|
||||
pub id: String,
|
||||
pub result: Option<Value>,
|
||||
pub error: Option<RpcError>,
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SubmitParams {
|
||||
pub id: String,
|
||||
pub job_id: u64,
|
||||
pub nonce: u64,
|
||||
pub hash: String,
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::stratum::stratum_types::rpc_error::RpcError;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct SubmitResponse {
|
||||
pub status: Option<String>,
|
||||
pub error: Option<RpcError>,
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct WorkerIdentifier {
|
||||
pub id: String,
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
use std::{
|
||||
io::{self, BufRead, Read, Write},
|
||||
net::TcpStream,
|
||||
};
|
||||
|
||||
use bufstream::BufStream;
|
||||
use native_tls::{TlsConnector, TlsStream};
|
||||
|
||||
use crate::stratum::error::Error;
|
||||
|
||||
pub(crate) enum Stream {
|
||||
Stream(BufStream<TcpStream>),
|
||||
TlsStream(Box<BufStream<TlsStream<TcpStream>>>),
|
||||
}
|
||||
|
||||
impl Stream {
|
||||
pub fn try_connect(server_url: &str, tls: Option<bool>) -> Result<Self, Error> {
|
||||
let conn = TcpStream::connect(server_url)?;
|
||||
if let Some(true) = tls {
|
||||
let connector = TlsConnector::new()?;
|
||||
let url_port: Vec<&str> = server_url.split(':').collect();
|
||||
let split_url: Vec<&str> = url_port[0].split('.').collect();
|
||||
let base_host = format!("{}.{}", split_url[split_url.len() - 2], split_url[split_url.len() - 1]);
|
||||
let mut stream = connector.connect(&base_host, conn).map_err(Box::new)?;
|
||||
stream.get_mut().set_nonblocking(true)?;
|
||||
Ok(Self::TlsStream(Box::from(BufStream::new(stream))))
|
||||
} else {
|
||||
conn.set_nonblocking(true)?;
|
||||
Ok(Self::Stream(BufStream::new(conn)))
|
||||
}
|
||||
}
|
||||
|
||||
fn reader(&mut self) -> &mut dyn Read {
|
||||
match self {
|
||||
Self::TlsStream(tls_stream) => tls_stream,
|
||||
Self::Stream(stream) => stream,
|
||||
}
|
||||
}
|
||||
|
||||
fn writer(&mut self) -> &mut dyn Write {
|
||||
match self {
|
||||
Self::TlsStream(tls_stream) => tls_stream,
|
||||
Self::Stream(stream) => stream,
|
||||
}
|
||||
}
|
||||
|
||||
fn buf_reader(&mut self) -> &mut dyn BufRead {
|
||||
match self {
|
||||
Self::TlsStream(tls_stream) => tls_stream,
|
||||
Self::Stream(stream) => stream,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Write for Stream {
|
||||
fn write(&mut self, b: &[u8]) -> Result<usize, io::Error> {
|
||||
self.writer().write(b)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> Result<(), io::Error> {
|
||||
self.writer().flush()
|
||||
}
|
||||
}
|
||||
impl Read for Stream {
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.reader().read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl BufRead for Stream {
|
||||
fn fill_buf(&mut self) -> io::Result<&[u8]> {
|
||||
self.buf_reader().fill_buf()
|
||||
}
|
||||
|
||||
fn consume(&mut self, amt: usize) {
|
||||
self.buf_reader().consume(amt)
|
||||
}
|
||||
|
||||
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||
self.buf_reader().read_until(byte, buf)
|
||||
}
|
||||
|
||||
fn read_line(&mut self, string: &mut String) -> io::Result<usize> {
|
||||
self.buf_reader().read_line(string)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
@echo off
|
||||
title Minotari Miner
|
||||
|
||||
rem Verify arguments
|
||||
if ["%base_path%"]==[""] (
|
||||
echo Problem with "base_path" environment variable: '%base_path%'
|
||||
pause
|
||||
exit /b 10101
|
||||
)
|
||||
if not exist "%base_path%" (
|
||||
echo Path as per "base_path" environment variable not found: '%base_path%'
|
||||
pause
|
||||
exit /b 10101
|
||||
)
|
||||
if ["%my_exe%"]==[""] (
|
||||
echo Problem with "my_exe" environment variable: '%my_exe%'
|
||||
pause
|
||||
exit /b 10101
|
||||
)
|
||||
|
||||
rem Find the miner executable
|
||||
if exist "%my_exe_path%\%my_exe%" (
|
||||
set miner=%my_exe_path%\%my_exe%
|
||||
echo.
|
||||
echo Using "%my_exe%" found in %my_exe_path%
|
||||
echo.
|
||||
) else (
|
||||
if exist "%base_path%\%my_exe%" (
|
||||
set miner=%base_path%\%my_exe%
|
||||
echo.
|
||||
echo Using "%my_exe%" found in base_path
|
||||
echo.
|
||||
) else (
|
||||
set FOUND=
|
||||
for %%X in (%my_exe%) do (set FOUND=%%~$PATH:X)
|
||||
if defined FOUND (
|
||||
set miner=%my_exe%
|
||||
echo.
|
||||
echo Using "%my_exe%" found in system path:
|
||||
where "%my_exe%"
|
||||
echo.
|
||||
) else (
|
||||
echo.
|
||||
echo Runtime "%my_exe%" not found in %my_exe_path%, base_path or the system path
|
||||
echo.
|
||||
pause
|
||||
exit /b 10101
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
echo.
|
||||
echo.
|
||||
|
||||
cd "%base_path%"
|
||||
"%miner%" --base-path "%base_path%"
|
|
@ -0,0 +1,28 @@
|
|||
@echo off
|
||||
|
||||
echo.
|
||||
echo Set up environment variables
|
||||
echo ----------------------------
|
||||
rem These are the miner executable and SQLite dynamic link library names
|
||||
set my_exe=minotari_miner.exe
|
||||
|
||||
rem The default location for the miner executable
|
||||
set my_exe_path=%~dp0
|
||||
if %my_exe_path:~-1%==\ set my_exe_path=%my_exe_path:~0,-1%
|
||||
echo my_exe_path = %my_exe_path%
|
||||
|
||||
rem The base folder where the database and log files will be located
|
||||
set base_path=%~dp0..
|
||||
echo base_path = %base_path%
|
||||
|
||||
echo.
|
||||
echo Run the miner
|
||||
echo ----------------------
|
||||
call "%my_exe_path%\source_miner_env.bat"
|
||||
|
||||
goto END:
|
||||
|
||||
|
||||
:END
|
||||
echo.
|
||||
pause
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -1,600 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
import "types.proto";
|
||||
import "transaction.proto";
|
||||
import "block.proto";
|
||||
import "network.proto";
|
||||
import "sidechain_types.proto";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
// The gRPC interface for interacting with the base node.
|
||||
service BaseNode {
|
||||
// Lists headers in the current best chain
|
||||
rpc ListHeaders(ListHeadersRequest) returns (stream BlockHeaderResponse);
|
||||
// Get header by hash
|
||||
rpc GetHeaderByHash(GetHeaderByHashRequest) returns (BlockHeaderResponse);
|
||||
// Returns blocks in the current best chain. Currently only supports querying by height
|
||||
rpc GetBlocks(GetBlocksRequest) returns (stream HistoricalBlock);
|
||||
// Returns the block timing for the chain heights
|
||||
rpc GetBlockTiming(HeightRequest) returns (BlockTimingResponse);
|
||||
// Returns the network Constants
|
||||
rpc GetConstants(BlockHeight) returns (ConsensusConstants);
|
||||
// Returns Block Sizes
|
||||
rpc GetBlockSize (BlockGroupRequest) returns (BlockGroupResponse);
|
||||
// Returns Block Fees
|
||||
rpc GetBlockFees (BlockGroupRequest) returns (BlockGroupResponse);
|
||||
// Get Version
|
||||
rpc GetVersion(Empty) returns (StringValue);
|
||||
// Check for new updates
|
||||
rpc CheckForUpdates(Empty) returns (SoftwareUpdate);
|
||||
// Get coins in circulation
|
||||
rpc GetTokensInCirculation(GetBlocksRequest) returns (stream ValueAtHeightResponse);
|
||||
// Get network difficulties
|
||||
rpc GetNetworkDifficulty(HeightRequest) returns (stream NetworkDifficultyResponse);
|
||||
// Get the block template
|
||||
rpc GetNewBlockTemplate(NewBlockTemplateRequest) returns (NewBlockTemplateResponse);
|
||||
// Construct a new block from a provided template
|
||||
rpc GetNewBlock(NewBlockTemplate) returns (GetNewBlockResult);
|
||||
// Construct a new block from a provided template
|
||||
rpc GetNewBlockWithCoinbases(GetNewBlockWithCoinbasesRequest) returns (GetNewBlockResult);
|
||||
// Construct a new block from a provided template
|
||||
rpc GetNewBlockTemplateWithCoinbases(GetNewBlockTemplateWithCoinbasesRequest) returns (GetNewBlockResult);
|
||||
// Construct a new block and header blob from a provided template
|
||||
rpc GetNewBlockBlob(NewBlockTemplate) returns (GetNewBlockBlobResult);
|
||||
// Submit a new block for propagation
|
||||
rpc SubmitBlock(Block) returns (SubmitBlockResponse);
|
||||
// Submit a new mined block blob for propagation
|
||||
rpc SubmitBlockBlob(BlockBlobRequest) returns (SubmitBlockResponse);
|
||||
// Submit a transaction for propagation
|
||||
rpc SubmitTransaction(SubmitTransactionRequest) returns (SubmitTransactionResponse);
|
||||
// Get the base node sync information
|
||||
rpc GetSyncInfo(Empty) returns (SyncInfoResponse);
|
||||
// Get the base node sync information
|
||||
rpc GetSyncProgress(Empty) returns (SyncProgressResponse);
|
||||
// Get the base node tip information
|
||||
rpc GetTipInfo(Empty) returns (TipInfoResponse);
|
||||
// Search for blocks containing the specified kernels
|
||||
rpc SearchKernels(SearchKernelsRequest) returns (stream HistoricalBlock);
|
||||
// Search for blocks containing the specified commitments
|
||||
rpc SearchUtxos(SearchUtxosRequest) returns (stream HistoricalBlock);
|
||||
// Fetch any utxos that exist in the main chain
|
||||
rpc FetchMatchingUtxos(FetchMatchingUtxosRequest) returns (stream FetchMatchingUtxosResponse);
|
||||
// get all peers from the base node
|
||||
rpc GetPeers(GetPeersRequest) returns (stream GetPeersResponse);
|
||||
rpc GetMempoolTransactions(GetMempoolTransactionsRequest) returns (stream GetMempoolTransactionsResponse);
|
||||
rpc TransactionState(TransactionStateRequest) returns (TransactionStateResponse);
|
||||
// This returns the node's network identity
|
||||
rpc Identify (Empty) returns (NodeIdentity);
|
||||
// Get Base Node network connectivity status
|
||||
rpc GetNetworkStatus(Empty) returns (NetworkStatusResponse);
|
||||
// List currently connected peers
|
||||
rpc ListConnectedPeers(Empty) returns (ListConnectedPeersResponse);
|
||||
// Get mempool stats
|
||||
rpc GetMempoolStats(Empty) returns (MempoolStatsResponse);
|
||||
// Get VNs
|
||||
rpc GetActiveValidatorNodes(GetActiveValidatorNodesRequest) returns (stream GetActiveValidatorNodesResponse);
|
||||
rpc GetShardKey(GetShardKeyRequest) returns (GetShardKeyResponse);
|
||||
// Get templates
|
||||
rpc GetTemplateRegistrations(GetTemplateRegistrationsRequest) returns (stream GetTemplateRegistrationResponse);
|
||||
rpc GetSideChainUtxos(GetSideChainUtxosRequest) returns (stream GetSideChainUtxosResponse);
|
||||
rpc GetNetworkState(GetNetworkStateRequest) returns (GetNetworkStateResponse);
|
||||
// PayRef (Payment Reference) lookup for block explorers and external services
|
||||
rpc SearchPaymentReferences(SearchPaymentReferencesRequest) returns (stream PaymentReferenceResponse);
|
||||
}
|
||||
|
||||
message GetAssetMetadataRequest {
|
||||
bytes asset_public_key = 1;
|
||||
}
|
||||
|
||||
message GetAssetMetadataResponse {
|
||||
string name = 2;
|
||||
string description =3;
|
||||
string image = 4;
|
||||
bytes owner_commitment = 5;
|
||||
OutputFeatures features = 6;
|
||||
uint64 mined_height = 7;
|
||||
bytes mined_in_block = 8;
|
||||
}
|
||||
|
||||
message ListAssetRegistrationsRequest {
|
||||
uint64 offset = 2;
|
||||
uint64 count = 3;
|
||||
}
|
||||
|
||||
message ListAssetRegistrationsResponse {
|
||||
bytes asset_public_key = 1;
|
||||
bytes unique_id = 2;
|
||||
bytes owner_commitment = 3;
|
||||
uint64 mined_height = 4;
|
||||
bytes mined_in_block = 5;
|
||||
OutputFeatures features = 6;
|
||||
bytes script = 7;
|
||||
}
|
||||
|
||||
message GetTokensRequest {
|
||||
bytes asset_public_key = 1;
|
||||
// Optionally get a set of specific unique_ids
|
||||
repeated bytes unique_ids = 2;
|
||||
}
|
||||
|
||||
message GetTokensResponse {
|
||||
bytes unique_id = 1;
|
||||
bytes asset_public_key = 2;
|
||||
bytes owner_commitment = 3;
|
||||
bytes mined_in_block = 4;
|
||||
uint64 mined_height = 5;
|
||||
OutputFeatures features = 6;
|
||||
bytes script = 7;
|
||||
}
|
||||
|
||||
message SubmitBlockResponse {
|
||||
bytes block_hash = 1;
|
||||
}
|
||||
|
||||
message BlockBlobRequest{
|
||||
bytes header_blob = 1;
|
||||
bytes body_blob = 2;
|
||||
}
|
||||
|
||||
/// return type of GetTipInfo
|
||||
message TipInfoResponse {
|
||||
MetaData metadata = 1;
|
||||
bool initial_sync_achieved = 2;
|
||||
BaseNodeState base_node_state = 3;
|
||||
bool failed_checkpoints = 4;
|
||||
}
|
||||
|
||||
enum BaseNodeState{
|
||||
START_UP = 0;
|
||||
HEADER_SYNC = 1;
|
||||
HORIZON_SYNC = 2;
|
||||
CONNECTING = 3;
|
||||
BLOCK_SYNC = 4;
|
||||
LISTENING = 5;
|
||||
SYNC_FAILED = 6;
|
||||
}
|
||||
|
||||
/// return type of GetNewBlockTemplate
|
||||
message NewBlockTemplateResponse {
|
||||
NewBlockTemplate new_block_template = 1;
|
||||
bool initial_sync_achieved = 3;
|
||||
MinerData miner_data = 4;
|
||||
}
|
||||
|
||||
/// return type of NewBlockTemplateRequest
|
||||
message NewBlockTemplateRequest{
|
||||
PowAlgo algo = 1;
|
||||
//This field should be moved to optional once optional keyword is standard
|
||||
uint64 max_weight = 2;
|
||||
}
|
||||
|
||||
/// return type of NewBlockTemplateRequest
|
||||
message GetNewBlockTemplateWithCoinbasesRequest{
|
||||
PowAlgo algo = 1;
|
||||
//This field should be moved to optional once optional keyword is standard
|
||||
uint64 max_weight = 2;
|
||||
repeated NewBlockCoinbase coinbases = 3;
|
||||
}
|
||||
|
||||
/// request type of GetNewBlockWithCoinbasesRequest
|
||||
message GetNewBlockWithCoinbasesRequest{
|
||||
NewBlockTemplate new_template = 1;
|
||||
repeated NewBlockCoinbase coinbases = 2;
|
||||
}
|
||||
|
||||
message NewBlockCoinbase{
|
||||
string address = 1;
|
||||
uint64 value = 2;
|
||||
bool stealth_payment= 3;
|
||||
bool revealed_value_proof= 4;
|
||||
bytes coinbase_extra =5;
|
||||
}
|
||||
|
||||
// Network difficulty response
|
||||
message NetworkDifficultyResponse {
|
||||
uint64 difficulty = 1;
|
||||
uint64 estimated_hash_rate = 2;
|
||||
uint64 height = 3;
|
||||
uint64 timestamp = 4;
|
||||
uint64 pow_algo = 5;
|
||||
uint64 sha3x_estimated_hash_rate = 6;
|
||||
uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
uint64 num_coinbases = 8;
|
||||
repeated bytes coinbase_extras = 9;
|
||||
}
|
||||
|
||||
// A generic single value response for a specific height
|
||||
message ValueAtHeightResponse {
|
||||
// uint64 circulating_supply = 1; // No longer used
|
||||
// uint64 spendable_supply = 2; // No longer used
|
||||
uint64 height = 3;
|
||||
uint64 mined_rewards = 4;
|
||||
uint64 spendable_rewards = 5;
|
||||
uint64 spendable_pre_mine = 6;
|
||||
uint64 total_spendable = 7;
|
||||
}
|
||||
|
||||
// A generic uint value
|
||||
message IntegerValue {
|
||||
uint64 value = 1;
|
||||
}
|
||||
|
||||
// A generic String value
|
||||
message StringValue {
|
||||
string value = 1;
|
||||
}
|
||||
|
||||
/// GetBlockSize / GetBlockFees Request
|
||||
/// Either the starting and ending heights OR the from_tip param must be specified
|
||||
message BlockGroupRequest {
|
||||
// The height from the chain tip (optional)
|
||||
uint64 from_tip = 1;
|
||||
// The starting height (optional)
|
||||
uint64 start_height = 2;
|
||||
// The ending height (optional)
|
||||
uint64 end_height = 3;
|
||||
/// The type of calculation required (optional)
|
||||
/// Defaults to median
|
||||
/// median, mean, quartile, quantile
|
||||
CalcType calc_type = 4;
|
||||
}
|
||||
|
||||
/// GetBlockSize / GetBlockFees Response
|
||||
message BlockGroupResponse {
|
||||
repeated double value = 1;
|
||||
CalcType calc_type = 2;
|
||||
}
|
||||
|
||||
enum CalcType {
|
||||
MEAN = 0;
|
||||
MEDIAN = 1;
|
||||
QUANTILE = 2;
|
||||
QUARTILE = 3;
|
||||
}
|
||||
|
||||
// The request used for querying a function that requires a height, either between 2 points or from the chain tip
|
||||
// If start_height and end_height are set and > 0, they take precedence, otherwise from_tip is used
|
||||
message HeightRequest {
|
||||
// The height from the chain tip (optional)
|
||||
uint64 from_tip = 1;
|
||||
// The starting height (optional)
|
||||
uint64 start_height = 2;
|
||||
// The ending height (optional)
|
||||
uint64 end_height = 3;
|
||||
}
|
||||
|
||||
// The return type of the rpc GetBlockTiming
|
||||
message BlockTimingResponse {
|
||||
uint64 max = 1;
|
||||
uint64 min = 2;
|
||||
double avg = 3;
|
||||
}
|
||||
|
||||
// Request that returns a header based by hash
|
||||
message GetHeaderByHashRequest {
|
||||
// The hash of the block header
|
||||
bytes hash = 1;
|
||||
}
|
||||
|
||||
|
||||
message BlockHeaderResponse {
|
||||
// The block header
|
||||
BlockHeader header = 1;
|
||||
// The number of blocks from the tip of this block (a.k.a depth)
|
||||
uint64 confirmations = 2;
|
||||
// The block reward i.e mining reward + fees
|
||||
uint64 reward = 3;
|
||||
// Achieved difficulty
|
||||
uint64 difficulty = 4;
|
||||
// The number of transactions contained in the block
|
||||
uint32 num_transactions = 5;
|
||||
}
|
||||
|
||||
// The request used for querying headers from the base node. The parameters `from_height` and `num_headers` can be used
|
||||
// to page through the current best chain.
|
||||
message ListHeadersRequest {
|
||||
// The height to start at. Depending on sorting, will either default to use the tip or genesis block, for `SORTING_DESC`
|
||||
// and `SORTING_ASC` respectively, if a value is not provided. The first header returned will be at this height
|
||||
// followed by `num_headers` - 1 headers in the direction specified by `sorting`. If greater than the current tip,
|
||||
// the current tip will be used.
|
||||
uint64 from_height = 1;
|
||||
// The number of headers to return. If not specified, it will default to 10
|
||||
uint64 num_headers = 2;
|
||||
// The ordering to return the headers in. If not specified will default to SORTING_DESC. Note that if `from_height`
|
||||
// is not specified or is 0, if `sorting` is SORTING_DESC, the tip will be used as `from_height`, otherwise the
|
||||
// block at height 0 will be used.
|
||||
Sorting sorting = 3;
|
||||
}
|
||||
|
||||
// The request used for querying blocks in the base node's current best chain. Currently only querying by height is
|
||||
// available. Multiple blocks may be queried.e.g. [189092,100023,122424]. The order in which they are returned is not
|
||||
// guaranteed.
|
||||
message GetBlocksRequest {
|
||||
repeated uint64 heights = 1;
|
||||
}
|
||||
|
||||
// The return type of the rpc GetBlocks. Blocks are not guaranteed to be returned in the order requested.
|
||||
message GetBlocksResponse {
|
||||
repeated HistoricalBlock blocks = 1;
|
||||
}
|
||||
|
||||
enum Sorting {
|
||||
SORTING_DESC = 0;
|
||||
SORTING_ASC = 1;
|
||||
}
|
||||
|
||||
message MetaData {
|
||||
// The current chain height, or the block number of the longest valid chain, or `None` if there is no chain
|
||||
uint64 best_block_height = 1;
|
||||
// The block hash of the current tip of the longest valid chain, or `None` for an empty chain
|
||||
bytes best_block_hash = 2;
|
||||
// The current geometric mean of the pow of the chain tip, or `None` if there is no chain
|
||||
bytes accumulated_difficulty = 5;
|
||||
// This is the min height this node can provide complete blocks for. A 0 here means this node is archival and can provide complete blocks for every height.
|
||||
uint64 pruned_height = 6;
|
||||
uint64 timestamp = 7;
|
||||
}
|
||||
|
||||
message SyncInfoResponse {
|
||||
uint64 tip_height = 1;
|
||||
uint64 local_height = 2;
|
||||
repeated bytes peer_node_id = 3;
|
||||
}
|
||||
|
||||
message SyncProgressResponse {
|
||||
uint64 tip_height = 1;
|
||||
uint64 local_height = 2;
|
||||
SyncState state = 3;
|
||||
string short_desc = 4;
|
||||
uint64 initial_connected_peers = 5;
|
||||
}
|
||||
|
||||
enum SyncState {
|
||||
STARTUP = 0;
|
||||
HEADER_STARTING = 1;
|
||||
HEADER = 2;
|
||||
BLOCK_STARTING = 3;
|
||||
BLOCK = 4;
|
||||
DONE = 5;
|
||||
}
|
||||
|
||||
// This is the message that is returned for a miner after it asks for a new block.
|
||||
message GetNewBlockResult{
|
||||
// This is the header hash of the completed block
|
||||
bytes block_hash = 1;
|
||||
// This is the completed block
|
||||
Block block = 2;
|
||||
bytes merge_mining_hash =3;
|
||||
bytes tari_unique_id =4;
|
||||
MinerData miner_data = 5;
|
||||
bytes vm_key = 6;
|
||||
}
|
||||
|
||||
// This is the message that is returned for a miner after it asks for a new block.
|
||||
message GetNewBlockBlobResult{
|
||||
// This is the header hash of the completed block
|
||||
bytes block_hash = 1;
|
||||
// This is the completed block's header
|
||||
bytes header = 2;
|
||||
// This is the completed block's body
|
||||
bytes block_body = 3;
|
||||
bytes merge_mining_hash =4;
|
||||
bytes utxo_mr = 5;
|
||||
bytes tari_unique_id =6;
|
||||
}
|
||||
|
||||
// This is mining data for the miner asking for a new block
|
||||
message MinerData{
|
||||
PowAlgo algo = 1;
|
||||
uint64 target_difficulty = 2;
|
||||
uint64 reward = 3;
|
||||
// bytes merge_mining_hash =4;
|
||||
uint64 total_fees = 5;
|
||||
}
|
||||
|
||||
// This is the request type for the Search Kernels rpc
|
||||
message SearchKernelsRequest{
|
||||
repeated Signature signatures = 1;
|
||||
}
|
||||
|
||||
// This is the request type for the Search Utxo rpc
|
||||
message SearchUtxosRequest{
|
||||
repeated bytes commitments = 1;
|
||||
}
|
||||
|
||||
message FetchMatchingUtxosRequest {
|
||||
repeated bytes hashes = 1;
|
||||
}
|
||||
|
||||
message FetchMatchingUtxosResponse {
|
||||
TransactionOutput output = 1;
|
||||
}
|
||||
|
||||
// This is the request type of the get all peers rpc call
|
||||
message GetPeersResponse{
|
||||
Peer peer = 1;
|
||||
}
|
||||
|
||||
message GetPeersRequest{}
|
||||
|
||||
message SubmitTransactionRequest {
|
||||
Transaction transaction = 1;
|
||||
}
|
||||
|
||||
message SubmitTransactionResponse {
|
||||
SubmitTransactionResult result =1;
|
||||
}
|
||||
|
||||
enum SubmitTransactionResult {
|
||||
NONE = 0;
|
||||
ACCEPTED = 1;
|
||||
NOT_PROCESSABLE_AT_THIS_TIME = 2;
|
||||
ALREADY_MINED = 3;
|
||||
REJECTED = 4;
|
||||
|
||||
}
|
||||
|
||||
message GetMempoolTransactionsRequest {
|
||||
|
||||
}
|
||||
|
||||
message GetMempoolTransactionsResponse {
|
||||
Transaction transaction = 1;
|
||||
}
|
||||
|
||||
message TransactionStateRequest {
|
||||
Signature excess_sig = 1;
|
||||
}
|
||||
|
||||
message TransactionStateResponse {
|
||||
TransactionLocation result =1;
|
||||
}
|
||||
|
||||
enum TransactionLocation {
|
||||
UNKNOWN = 0;
|
||||
MEMPOOL = 1;
|
||||
MINED = 2;
|
||||
NOT_STORED = 3;
|
||||
}
|
||||
|
||||
message MempoolStatsResponse {
|
||||
uint64 unconfirmed_txs = 2;
|
||||
uint64 reorg_txs = 3;
|
||||
uint64 unconfirmed_weight = 4;
|
||||
}
|
||||
|
||||
message GetActiveValidatorNodesRequest {
|
||||
uint64 height = 1;
|
||||
}
|
||||
|
||||
message GetActiveValidatorNodesResponse {
|
||||
bytes shard_key = 1;
|
||||
bytes public_key = 2;
|
||||
}
|
||||
|
||||
message GetShardKeyRequest {
|
||||
uint64 height = 1;
|
||||
bytes public_key = 2;
|
||||
}
|
||||
|
||||
message GetShardKeyResponse {
|
||||
bytes shard_key = 1;
|
||||
bool found = 2;
|
||||
}
|
||||
|
||||
message GetTemplateRegistrationsRequest {
|
||||
bytes start_hash = 1;
|
||||
uint64 count = 2;
|
||||
}
|
||||
|
||||
message GetTemplateRegistrationResponse {
|
||||
bytes utxo_hash = 1;
|
||||
TemplateRegistration registration = 2;
|
||||
}
|
||||
|
||||
message BlockInfo {
|
||||
uint64 height = 1;
|
||||
bytes hash = 2;
|
||||
bytes next_block_hash = 3;
|
||||
}
|
||||
|
||||
message GetSideChainUtxosRequest {
|
||||
bytes start_hash = 1;
|
||||
uint64 count = 2;
|
||||
}
|
||||
|
||||
message GetSideChainUtxosResponse {
|
||||
BlockInfo block_info = 1;
|
||||
repeated TransactionOutput outputs = 2;
|
||||
}
|
||||
|
||||
message GetNetworkStateRequest {
|
||||
}
|
||||
|
||||
message GetNetworkStateResponse {
|
||||
// metadata
|
||||
MetaData metadata = 1;
|
||||
// has the base node synced
|
||||
bool initial_sync_achieved = 2;
|
||||
//current state of the base node
|
||||
BaseNodeState base_node_state = 3;
|
||||
// do we have failed checkpoints
|
||||
bool failed_checkpoints = 4;
|
||||
// The block reward of the next tip
|
||||
uint64 reward = 5;
|
||||
// estimate sha3x hash rate
|
||||
uint64 sha3x_estimated_hash_rate = 6;
|
||||
// estimate randomx hash rate
|
||||
uint64 monero_randomx_estimated_hash_rate = 7;
|
||||
uint64 tari_randomx_estimated_hash_rate = 10;
|
||||
// number of connections
|
||||
uint64 num_connections = 8;
|
||||
//liveness results
|
||||
repeated LivenessResult liveness_results = 9;
|
||||
}
|
||||
|
||||
message LivenessResult{
|
||||
// node id
|
||||
bytes peer_node_id = 1;
|
||||
// time to discover
|
||||
uint64 discover_latency = 2;
|
||||
// Dial latency
|
||||
uint64 ping_latency = 3;
|
||||
}
|
||||
|
||||
// PayRef (Payment Reference) search and lookup messages
|
||||
|
||||
// Request to search for outputs by payment reference
|
||||
message SearchPaymentReferencesRequest {
|
||||
// Payment reference as hex string (64 characters)
|
||||
repeated string payment_reference_hex = 1;
|
||||
repeated bytes payment_reference_bytes = 2;
|
||||
// Optional: include spent outputs in results
|
||||
bool include_spent = 3;
|
||||
}
|
||||
|
||||
// Response containing payment reference match
|
||||
message PaymentReferenceResponse {
|
||||
// The payment reference that was found
|
||||
string payment_reference_hex = 1;
|
||||
// Block height where the output was mined
|
||||
uint64 block_height = 2;
|
||||
// Block hash where the output was mined
|
||||
bytes block_hash = 3;
|
||||
// Timestamp when the output was mined
|
||||
uint64 mined_timestamp = 4;
|
||||
// Output commitment (32 bytes)
|
||||
bytes commitment = 5;
|
||||
// Whether this output has been spent
|
||||
bool is_spent = 6;
|
||||
// Height where output was spent (if spent)
|
||||
uint64 spent_height = 7;
|
||||
// Block hash where output was spent (if spent)
|
||||
bytes spent_block_hash = 8;
|
||||
// Transaction output amount will be 0 for non set a
|
||||
uint64 min_value_promise = 9;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,142 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
import "transaction.proto";
|
||||
|
||||
// The BlockHeader contains all the metadata for the block, including proof of work, a link to the previous block
|
||||
// and the transaction kernels.
|
||||
message BlockHeader {
|
||||
// The hash of the block
|
||||
bytes hash = 1;
|
||||
// Version of the block
|
||||
uint32 version = 2;
|
||||
// Height of this block since the genesis block (height 0)
|
||||
uint64 height = 3;
|
||||
// Hash of the block previous to this in the chain.
|
||||
bytes prev_hash = 4;
|
||||
// Timestamp at which the block was built.
|
||||
uint64 timestamp = 5;
|
||||
// This is the UTXO merkle root of the outputs in the blockchain
|
||||
bytes output_mr = 6;
|
||||
// This is the merkle root of all outputs in this block
|
||||
bytes block_output_mr = 7;
|
||||
// This is the MMR root of the kernels
|
||||
bytes kernel_mr = 8;
|
||||
// This is the Merkle root of the inputs in this block
|
||||
bytes input_mr = 9;
|
||||
// Total accumulated sum of kernel offsets since genesis block. We can derive the kernel offset sum for *this*
|
||||
// block from the total kernel offset of the previous block header.
|
||||
bytes total_kernel_offset = 10;
|
||||
// Nonce increment used to mine this block.
|
||||
uint64 nonce = 11;
|
||||
// Proof of work metadata
|
||||
ProofOfWork pow = 12;
|
||||
// Kernel MMR size
|
||||
uint64 kernel_mmr_size = 13;
|
||||
// Output MMR size
|
||||
uint64 output_mmr_size = 14;
|
||||
// Sum of script offsets for all kernels in this block.
|
||||
bytes total_script_offset = 15;
|
||||
// Merkle root of validator nodes
|
||||
bytes validator_node_mr = 16;
|
||||
// Validator size
|
||||
uint64 validator_node_size = 17;
|
||||
}
|
||||
|
||||
// The proof of work data structure that is included in the block header.
|
||||
message ProofOfWork {
|
||||
// The algorithm used to mine this block
|
||||
// 0 = Monero
|
||||
// 1 = Sha3X
|
||||
uint64 pow_algo = 1;
|
||||
// Supplemental proof of work data. For example for Sha3x, this would be empty (only the block header is
|
||||
// required), but for Monero merge mining we need the Monero block header and RandomX seed hash.
|
||||
bytes pow_data = 4;
|
||||
}
|
||||
|
||||
//This is used to request the which pow algo should be used with the block template
|
||||
message PowAlgo {
|
||||
// The permitted pow algorithms
|
||||
enum PowAlgos {
|
||||
POW_ALGOS_RANDOMXM = 0; // Accessible as `grpc::pow_algo::PowAlgos::RandomxM`
|
||||
POW_ALGOS_SHA3X = 1; // Accessible as `grpc::pow_algo::PowAlgos::Sha3x`
|
||||
POW_ALGOS_RANDOMXT = 2; // Accessible as `grpc::pow_algo::PowAlgos::RandomxT`
|
||||
}
|
||||
// The pow algo to use
|
||||
PowAlgos pow_algo = 1;
|
||||
}
|
||||
|
||||
|
||||
// A Minotari block. Blocks are linked together into a blockchain.
|
||||
message Block {
|
||||
// The BlockHeader contains all the metadata for the block, including proof of work, a link to the previous block
|
||||
// and the transaction kernels.
|
||||
BlockHeader header = 1;
|
||||
// The components of the block or transaction. The same struct can be used for either, since in Mimblewimble,
|
||||
// blocks consist of inputs, outputs and kernels, rather than transactions.
|
||||
AggregateBody body = 2;
|
||||
}
|
||||
|
||||
// The representation of a historical block in the blockchain. It is essentially identical to a protocol-defined
|
||||
// block but contains some extra metadata that clients such as Block Explorers will find interesting.
|
||||
message HistoricalBlock {
|
||||
// The number of blocks that have been mined since this block, including this one. The current tip will have one
|
||||
// confirmation.
|
||||
uint64 confirmations = 1;
|
||||
// The underlying block
|
||||
Block block = 2;
|
||||
}
|
||||
|
||||
|
||||
// The NewBlockHeaderTemplate is used for the construction of a new mine-able block. It contains all the metadata for the block that the Base Node is able to complete on behalf of a Miner.
|
||||
message NewBlockHeaderTemplate {
|
||||
// Version of the block
|
||||
uint32 version = 1;
|
||||
// Height of this block since the genesis block (height 0)
|
||||
uint64 height = 2;
|
||||
// Hash of the block previous to this in the chain.
|
||||
bytes prev_hash = 3;
|
||||
// Total accumulated sum of kernel offsets since genesis block. We can derive the kernel offset sum for *this*
|
||||
// block from the total kernel offset of the previous block header.
|
||||
bytes total_kernel_offset = 4;
|
||||
// Proof of work metadata
|
||||
ProofOfWork pow = 5;
|
||||
// Sum of script offsets for all kernels in this block.
|
||||
bytes total_script_offset = 7;
|
||||
}
|
||||
|
||||
// The new block template is used constructing a new partial block, allowing a miner to added the coinbase utxo and as a final step the Base node to add the MMR roots to the header.
|
||||
message NewBlockTemplate {
|
||||
// The NewBlockHeaderTemplate is used for the construction of a new mineable block. It contains all the metadata for
|
||||
// the block that the Base Node is able to complete on behalf of a Miner.
|
||||
NewBlockHeaderTemplate header = 1;
|
||||
// This flag indicates if the inputs, outputs and kernels have been sorted internally, that is, the sort() method
|
||||
// has been called. This may be false even if all components are sorted.
|
||||
AggregateBody body = 2;
|
||||
// Sometimes the mempool has not synced to the latest tip, this flag indicates if the mempool is out of sync.
|
||||
// In most cases the next call to get_new_block_template will return a block with the mempool in sync.
|
||||
bool is_mempool_in_sync = 3;
|
||||
}
|
||||
|
|
@ -1,783 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v3.6.1
|
||||
// source: block.proto
|
||||
|
||||
package block
|
||||
|
||||
import (
|
||||
transaction "pool/internal/gbt/tari/proto/transaction"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// The permitted pow algorithms
|
||||
type PowAlgo_PowAlgos int32
|
||||
|
||||
const (
|
||||
PowAlgo_POW_ALGOS_RANDOMXM PowAlgo_PowAlgos = 0 // Accessible as `grpc::pow_algo::PowAlgos::RandomxM`
|
||||
PowAlgo_POW_ALGOS_SHA3X PowAlgo_PowAlgos = 1 // Accessible as `grpc::pow_algo::PowAlgos::Sha3x`
|
||||
PowAlgo_POW_ALGOS_RANDOMXT PowAlgo_PowAlgos = 2 // Accessible as `grpc::pow_algo::PowAlgos::RandomxT`
|
||||
)
|
||||
|
||||
// Enum value maps for PowAlgo_PowAlgos.
|
||||
var (
|
||||
PowAlgo_PowAlgos_name = map[int32]string{
|
||||
0: "POW_ALGOS_RANDOMXM",
|
||||
1: "POW_ALGOS_SHA3X",
|
||||
2: "POW_ALGOS_RANDOMXT",
|
||||
}
|
||||
PowAlgo_PowAlgos_value = map[string]int32{
|
||||
"POW_ALGOS_RANDOMXM": 0,
|
||||
"POW_ALGOS_SHA3X": 1,
|
||||
"POW_ALGOS_RANDOMXT": 2,
|
||||
}
|
||||
)
|
||||
|
||||
func (x PowAlgo_PowAlgos) Enum() *PowAlgo_PowAlgos {
|
||||
p := new(PowAlgo_PowAlgos)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x PowAlgo_PowAlgos) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (PowAlgo_PowAlgos) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_block_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (PowAlgo_PowAlgos) Type() protoreflect.EnumType {
|
||||
return &file_block_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x PowAlgo_PowAlgos) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PowAlgo_PowAlgos.Descriptor instead.
|
||||
func (PowAlgo_PowAlgos) EnumDescriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{2, 0}
|
||||
}
|
||||
|
||||
// The BlockHeader contains all the metadata for the block, including proof of work, a link to the previous block
|
||||
// and the transaction kernels.
|
||||
type BlockHeader struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The hash of the block
|
||||
Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"`
|
||||
// Version of the block
|
||||
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
// Height of this block since the genesis block (height 0)
|
||||
Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"`
|
||||
// Hash of the block previous to this in the chain.
|
||||
PrevHash []byte `protobuf:"bytes,4,opt,name=prev_hash,json=prevHash,proto3" json:"prev_hash,omitempty"`
|
||||
// Timestamp at which the block was built.
|
||||
Timestamp uint64 `protobuf:"varint,5,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
|
||||
// This is the UTXO merkle root of the outputs in the blockchain
|
||||
OutputMr []byte `protobuf:"bytes,6,opt,name=output_mr,json=outputMr,proto3" json:"output_mr,omitempty"`
|
||||
// This is the merkle root of all outputs in this block
|
||||
BlockOutputMr []byte `protobuf:"bytes,7,opt,name=block_output_mr,json=blockOutputMr,proto3" json:"block_output_mr,omitempty"`
|
||||
// This is the MMR root of the kernels
|
||||
KernelMr []byte `protobuf:"bytes,8,opt,name=kernel_mr,json=kernelMr,proto3" json:"kernel_mr,omitempty"`
|
||||
// This is the Merkle root of the inputs in this block
|
||||
InputMr []byte `protobuf:"bytes,9,opt,name=input_mr,json=inputMr,proto3" json:"input_mr,omitempty"`
|
||||
// Total accumulated sum of kernel offsets since genesis block. We can derive the kernel offset sum for *this*
|
||||
// block from the total kernel offset of the previous block header.
|
||||
TotalKernelOffset []byte `protobuf:"bytes,10,opt,name=total_kernel_offset,json=totalKernelOffset,proto3" json:"total_kernel_offset,omitempty"`
|
||||
// Nonce increment used to mine this block.
|
||||
Nonce uint64 `protobuf:"varint,11,opt,name=nonce,proto3" json:"nonce,omitempty"`
|
||||
// Proof of work metadata
|
||||
Pow *ProofOfWork `protobuf:"bytes,12,opt,name=pow,proto3" json:"pow,omitempty"`
|
||||
// Kernel MMR size
|
||||
KernelMmrSize uint64 `protobuf:"varint,13,opt,name=kernel_mmr_size,json=kernelMmrSize,proto3" json:"kernel_mmr_size,omitempty"`
|
||||
// Output MMR size
|
||||
OutputMmrSize uint64 `protobuf:"varint,14,opt,name=output_mmr_size,json=outputMmrSize,proto3" json:"output_mmr_size,omitempty"`
|
||||
// Sum of script offsets for all kernels in this block.
|
||||
TotalScriptOffset []byte `protobuf:"bytes,15,opt,name=total_script_offset,json=totalScriptOffset,proto3" json:"total_script_offset,omitempty"`
|
||||
// Merkle root of validator nodes
|
||||
ValidatorNodeMr []byte `protobuf:"bytes,16,opt,name=validator_node_mr,json=validatorNodeMr,proto3" json:"validator_node_mr,omitempty"`
|
||||
// Validator size
|
||||
ValidatorNodeSize uint64 `protobuf:"varint,17,opt,name=validator_node_size,json=validatorNodeSize,proto3" json:"validator_node_size,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *BlockHeader) Reset() {
|
||||
*x = BlockHeader{}
|
||||
mi := &file_block_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *BlockHeader) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BlockHeader) ProtoMessage() {}
|
||||
|
||||
func (x *BlockHeader) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_block_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BlockHeader.ProtoReflect.Descriptor instead.
|
||||
func (*BlockHeader) Descriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetHash() []byte {
|
||||
if x != nil {
|
||||
return x.Hash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetHeight() uint64 {
|
||||
if x != nil {
|
||||
return x.Height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetPrevHash() []byte {
|
||||
if x != nil {
|
||||
return x.PrevHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetTimestamp() uint64 {
|
||||
if x != nil {
|
||||
return x.Timestamp
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetOutputMr() []byte {
|
||||
if x != nil {
|
||||
return x.OutputMr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetBlockOutputMr() []byte {
|
||||
if x != nil {
|
||||
return x.BlockOutputMr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetKernelMr() []byte {
|
||||
if x != nil {
|
||||
return x.KernelMr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetInputMr() []byte {
|
||||
if x != nil {
|
||||
return x.InputMr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetTotalKernelOffset() []byte {
|
||||
if x != nil {
|
||||
return x.TotalKernelOffset
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetNonce() uint64 {
|
||||
if x != nil {
|
||||
return x.Nonce
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetPow() *ProofOfWork {
|
||||
if x != nil {
|
||||
return x.Pow
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetKernelMmrSize() uint64 {
|
||||
if x != nil {
|
||||
return x.KernelMmrSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetOutputMmrSize() uint64 {
|
||||
if x != nil {
|
||||
return x.OutputMmrSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetTotalScriptOffset() []byte {
|
||||
if x != nil {
|
||||
return x.TotalScriptOffset
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetValidatorNodeMr() []byte {
|
||||
if x != nil {
|
||||
return x.ValidatorNodeMr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *BlockHeader) GetValidatorNodeSize() uint64 {
|
||||
if x != nil {
|
||||
return x.ValidatorNodeSize
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// The proof of work data structure that is included in the block header.
|
||||
type ProofOfWork struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The algorithm used to mine this block
|
||||
//
|
||||
// 0 = Monero
|
||||
// 1 = Sha3X
|
||||
PowAlgo uint64 `protobuf:"varint,1,opt,name=pow_algo,json=powAlgo,proto3" json:"pow_algo,omitempty"`
|
||||
// Supplemental proof of work data. For example for Sha3x, this would be empty (only the block header is
|
||||
// required), but for Monero merge mining we need the Monero block header and RandomX seed hash.
|
||||
PowData []byte `protobuf:"bytes,4,opt,name=pow_data,json=powData,proto3" json:"pow_data,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ProofOfWork) Reset() {
|
||||
*x = ProofOfWork{}
|
||||
mi := &file_block_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ProofOfWork) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ProofOfWork) ProtoMessage() {}
|
||||
|
||||
func (x *ProofOfWork) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_block_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ProofOfWork.ProtoReflect.Descriptor instead.
|
||||
func (*ProofOfWork) Descriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ProofOfWork) GetPowAlgo() uint64 {
|
||||
if x != nil {
|
||||
return x.PowAlgo
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ProofOfWork) GetPowData() []byte {
|
||||
if x != nil {
|
||||
return x.PowData
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is used to request the which pow algo should be used with the block template
|
||||
type PowAlgo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The pow algo to use
|
||||
PowAlgo PowAlgo_PowAlgos `protobuf:"varint,1,opt,name=pow_algo,json=powAlgo,proto3,enum=tari.rpc.PowAlgo_PowAlgos" json:"pow_algo,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *PowAlgo) Reset() {
|
||||
*x = PowAlgo{}
|
||||
mi := &file_block_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *PowAlgo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*PowAlgo) ProtoMessage() {}
|
||||
|
||||
func (x *PowAlgo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_block_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use PowAlgo.ProtoReflect.Descriptor instead.
|
||||
func (*PowAlgo) Descriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *PowAlgo) GetPowAlgo() PowAlgo_PowAlgos {
|
||||
if x != nil {
|
||||
return x.PowAlgo
|
||||
}
|
||||
return PowAlgo_POW_ALGOS_RANDOMXM
|
||||
}
|
||||
|
||||
// A Minotari block. Blocks are linked together into a blockchain.
|
||||
type Block struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The BlockHeader contains all the metadata for the block, including proof of work, a link to the previous block
|
||||
// and the transaction kernels.
|
||||
Header *BlockHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
|
||||
// The components of the block or transaction. The same struct can be used for either, since in Mimblewimble,
|
||||
// blocks consist of inputs, outputs and kernels, rather than transactions.
|
||||
Body *transaction.AggregateBody `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Block) Reset() {
|
||||
*x = Block{}
|
||||
mi := &file_block_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Block) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Block) ProtoMessage() {}
|
||||
|
||||
func (x *Block) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_block_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Block.ProtoReflect.Descriptor instead.
|
||||
func (*Block) Descriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *Block) GetHeader() *BlockHeader {
|
||||
if x != nil {
|
||||
return x.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Block) GetBody() *transaction.AggregateBody {
|
||||
if x != nil {
|
||||
return x.Body
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The representation of a historical block in the blockchain. It is essentially identical to a protocol-defined
|
||||
// block but contains some extra metadata that clients such as Block Explorers will find interesting.
|
||||
type HistoricalBlock struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The number of blocks that have been mined since this block, including this one. The current tip will have one
|
||||
// confirmation.
|
||||
Confirmations uint64 `protobuf:"varint,1,opt,name=confirmations,proto3" json:"confirmations,omitempty"`
|
||||
// The underlying block
|
||||
Block *Block `protobuf:"bytes,2,opt,name=block,proto3" json:"block,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *HistoricalBlock) Reset() {
|
||||
*x = HistoricalBlock{}
|
||||
mi := &file_block_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *HistoricalBlock) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*HistoricalBlock) ProtoMessage() {}
|
||||
|
||||
func (x *HistoricalBlock) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_block_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use HistoricalBlock.ProtoReflect.Descriptor instead.
|
||||
func (*HistoricalBlock) Descriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *HistoricalBlock) GetConfirmations() uint64 {
|
||||
if x != nil {
|
||||
return x.Confirmations
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *HistoricalBlock) GetBlock() *Block {
|
||||
if x != nil {
|
||||
return x.Block
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The NewBlockHeaderTemplate is used for the construction of a new mine-able block. It contains all the metadata for the block that the Base Node is able to complete on behalf of a Miner.
|
||||
type NewBlockHeaderTemplate struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Version of the block
|
||||
Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"`
|
||||
// Height of this block since the genesis block (height 0)
|
||||
Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"`
|
||||
// Hash of the block previous to this in the chain.
|
||||
PrevHash []byte `protobuf:"bytes,3,opt,name=prev_hash,json=prevHash,proto3" json:"prev_hash,omitempty"`
|
||||
// Total accumulated sum of kernel offsets since genesis block. We can derive the kernel offset sum for *this*
|
||||
// block from the total kernel offset of the previous block header.
|
||||
TotalKernelOffset []byte `protobuf:"bytes,4,opt,name=total_kernel_offset,json=totalKernelOffset,proto3" json:"total_kernel_offset,omitempty"`
|
||||
// Proof of work metadata
|
||||
Pow *ProofOfWork `protobuf:"bytes,5,opt,name=pow,proto3" json:"pow,omitempty"`
|
||||
// Sum of script offsets for all kernels in this block.
|
||||
TotalScriptOffset []byte `protobuf:"bytes,7,opt,name=total_script_offset,json=totalScriptOffset,proto3" json:"total_script_offset,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) Reset() {
|
||||
*x = NewBlockHeaderTemplate{}
|
||||
mi := &file_block_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NewBlockHeaderTemplate) ProtoMessage() {}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_block_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NewBlockHeaderTemplate.ProtoReflect.Descriptor instead.
|
||||
func (*NewBlockHeaderTemplate) Descriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) GetVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) GetHeight() uint64 {
|
||||
if x != nil {
|
||||
return x.Height
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) GetPrevHash() []byte {
|
||||
if x != nil {
|
||||
return x.PrevHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) GetTotalKernelOffset() []byte {
|
||||
if x != nil {
|
||||
return x.TotalKernelOffset
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) GetPow() *ProofOfWork {
|
||||
if x != nil {
|
||||
return x.Pow
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NewBlockHeaderTemplate) GetTotalScriptOffset() []byte {
|
||||
if x != nil {
|
||||
return x.TotalScriptOffset
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// The new block template is used constructing a new partial block, allowing a miner to added the coinbase utxo and as a final step the Base node to add the MMR roots to the header.
|
||||
type NewBlockTemplate struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// The NewBlockHeaderTemplate is used for the construction of a new mineable block. It contains all the metadata for
|
||||
// the block that the Base Node is able to complete on behalf of a Miner.
|
||||
Header *NewBlockHeaderTemplate `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"`
|
||||
// This flag indicates if the inputs, outputs and kernels have been sorted internally, that is, the sort() method
|
||||
// has been called. This may be false even if all components are sorted.
|
||||
Body *transaction.AggregateBody `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"`
|
||||
// Sometimes the mempool has not synced to the latest tip, this flag indicates if the mempool is out of sync.
|
||||
// In most cases the next call to get_new_block_template will return a block with the mempool in sync.
|
||||
IsMempoolInSync bool `protobuf:"varint,3,opt,name=is_mempool_in_sync,json=isMempoolInSync,proto3" json:"is_mempool_in_sync,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NewBlockTemplate) Reset() {
|
||||
*x = NewBlockTemplate{}
|
||||
mi := &file_block_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NewBlockTemplate) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NewBlockTemplate) ProtoMessage() {}
|
||||
|
||||
func (x *NewBlockTemplate) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_block_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NewBlockTemplate.ProtoReflect.Descriptor instead.
|
||||
func (*NewBlockTemplate) Descriptor() ([]byte, []int) {
|
||||
return file_block_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *NewBlockTemplate) GetHeader() *NewBlockHeaderTemplate {
|
||||
if x != nil {
|
||||
return x.Header
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NewBlockTemplate) GetBody() *transaction.AggregateBody {
|
||||
if x != nil {
|
||||
return x.Body
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NewBlockTemplate) GetIsMempoolInSync() bool {
|
||||
if x != nil {
|
||||
return x.IsMempoolInSync
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var File_block_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_block_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\vblock.proto\x12\btari.rpc\x1a\x11transaction.proto\"\xd6\x04\n" +
|
||||
"\vBlockHeader\x12\x12\n" +
|
||||
"\x04hash\x18\x01 \x01(\fR\x04hash\x12\x18\n" +
|
||||
"\aversion\x18\x02 \x01(\rR\aversion\x12\x16\n" +
|
||||
"\x06height\x18\x03 \x01(\x04R\x06height\x12\x1b\n" +
|
||||
"\tprev_hash\x18\x04 \x01(\fR\bprevHash\x12\x1c\n" +
|
||||
"\ttimestamp\x18\x05 \x01(\x04R\ttimestamp\x12\x1b\n" +
|
||||
"\toutput_mr\x18\x06 \x01(\fR\boutputMr\x12&\n" +
|
||||
"\x0fblock_output_mr\x18\a \x01(\fR\rblockOutputMr\x12\x1b\n" +
|
||||
"\tkernel_mr\x18\b \x01(\fR\bkernelMr\x12\x19\n" +
|
||||
"\binput_mr\x18\t \x01(\fR\ainputMr\x12.\n" +
|
||||
"\x13total_kernel_offset\x18\n" +
|
||||
" \x01(\fR\x11totalKernelOffset\x12\x14\n" +
|
||||
"\x05nonce\x18\v \x01(\x04R\x05nonce\x12'\n" +
|
||||
"\x03pow\x18\f \x01(\v2\x15.tari.rpc.ProofOfWorkR\x03pow\x12&\n" +
|
||||
"\x0fkernel_mmr_size\x18\r \x01(\x04R\rkernelMmrSize\x12&\n" +
|
||||
"\x0foutput_mmr_size\x18\x0e \x01(\x04R\routputMmrSize\x12.\n" +
|
||||
"\x13total_script_offset\x18\x0f \x01(\fR\x11totalScriptOffset\x12*\n" +
|
||||
"\x11validator_node_mr\x18\x10 \x01(\fR\x0fvalidatorNodeMr\x12.\n" +
|
||||
"\x13validator_node_size\x18\x11 \x01(\x04R\x11validatorNodeSize\"C\n" +
|
||||
"\vProofOfWork\x12\x19\n" +
|
||||
"\bpow_algo\x18\x01 \x01(\x04R\apowAlgo\x12\x19\n" +
|
||||
"\bpow_data\x18\x04 \x01(\fR\apowData\"\x91\x01\n" +
|
||||
"\aPowAlgo\x125\n" +
|
||||
"\bpow_algo\x18\x01 \x01(\x0e2\x1a.tari.rpc.PowAlgo.PowAlgosR\apowAlgo\"O\n" +
|
||||
"\bPowAlgos\x12\x16\n" +
|
||||
"\x12POW_ALGOS_RANDOMXM\x10\x00\x12\x13\n" +
|
||||
"\x0fPOW_ALGOS_SHA3X\x10\x01\x12\x16\n" +
|
||||
"\x12POW_ALGOS_RANDOMXT\x10\x02\"c\n" +
|
||||
"\x05Block\x12-\n" +
|
||||
"\x06header\x18\x01 \x01(\v2\x15.tari.rpc.BlockHeaderR\x06header\x12+\n" +
|
||||
"\x04body\x18\x02 \x01(\v2\x17.tari.rpc.AggregateBodyR\x04body\"^\n" +
|
||||
"\x0fHistoricalBlock\x12$\n" +
|
||||
"\rconfirmations\x18\x01 \x01(\x04R\rconfirmations\x12%\n" +
|
||||
"\x05block\x18\x02 \x01(\v2\x0f.tari.rpc.BlockR\x05block\"\xf0\x01\n" +
|
||||
"\x16NewBlockHeaderTemplate\x12\x18\n" +
|
||||
"\aversion\x18\x01 \x01(\rR\aversion\x12\x16\n" +
|
||||
"\x06height\x18\x02 \x01(\x04R\x06height\x12\x1b\n" +
|
||||
"\tprev_hash\x18\x03 \x01(\fR\bprevHash\x12.\n" +
|
||||
"\x13total_kernel_offset\x18\x04 \x01(\fR\x11totalKernelOffset\x12'\n" +
|
||||
"\x03pow\x18\x05 \x01(\v2\x15.tari.rpc.ProofOfWorkR\x03pow\x12.\n" +
|
||||
"\x13total_script_offset\x18\a \x01(\fR\x11totalScriptOffset\"\xa6\x01\n" +
|
||||
"\x10NewBlockTemplate\x128\n" +
|
||||
"\x06header\x18\x01 \x01(\v2 .tari.rpc.NewBlockHeaderTemplateR\x06header\x12+\n" +
|
||||
"\x04body\x18\x02 \x01(\v2\x17.tari.rpc.AggregateBodyR\x04body\x12+\n" +
|
||||
"\x12is_mempool_in_sync\x18\x03 \x01(\bR\x0fisMempoolInSyncB$Z\"pool/internal/gbt/tari/block;blockb\x06proto3"
|
||||
|
||||
var (
|
||||
file_block_proto_rawDescOnce sync.Once
|
||||
file_block_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_block_proto_rawDescGZIP() []byte {
|
||||
file_block_proto_rawDescOnce.Do(func() {
|
||||
file_block_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_block_proto_rawDesc), len(file_block_proto_rawDesc)))
|
||||
})
|
||||
return file_block_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_block_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_block_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
|
||||
var file_block_proto_goTypes = []any{
|
||||
(PowAlgo_PowAlgos)(0), // 0: tari.rpc.PowAlgo.PowAlgos
|
||||
(*BlockHeader)(nil), // 1: tari.rpc.BlockHeader
|
||||
(*ProofOfWork)(nil), // 2: tari.rpc.ProofOfWork
|
||||
(*PowAlgo)(nil), // 3: tari.rpc.PowAlgo
|
||||
(*Block)(nil), // 4: tari.rpc.Block
|
||||
(*HistoricalBlock)(nil), // 5: tari.rpc.HistoricalBlock
|
||||
(*NewBlockHeaderTemplate)(nil), // 6: tari.rpc.NewBlockHeaderTemplate
|
||||
(*NewBlockTemplate)(nil), // 7: tari.rpc.NewBlockTemplate
|
||||
(*transaction.AggregateBody)(nil), // 8: tari.rpc.AggregateBody
|
||||
}
|
||||
var file_block_proto_depIdxs = []int32{
|
||||
2, // 0: tari.rpc.BlockHeader.pow:type_name -> tari.rpc.ProofOfWork
|
||||
0, // 1: tari.rpc.PowAlgo.pow_algo:type_name -> tari.rpc.PowAlgo.PowAlgos
|
||||
1, // 2: tari.rpc.Block.header:type_name -> tari.rpc.BlockHeader
|
||||
8, // 3: tari.rpc.Block.body:type_name -> tari.rpc.AggregateBody
|
||||
4, // 4: tari.rpc.HistoricalBlock.block:type_name -> tari.rpc.Block
|
||||
2, // 5: tari.rpc.NewBlockHeaderTemplate.pow:type_name -> tari.rpc.ProofOfWork
|
||||
6, // 6: tari.rpc.NewBlockTemplate.header:type_name -> tari.rpc.NewBlockHeaderTemplate
|
||||
8, // 7: tari.rpc.NewBlockTemplate.body:type_name -> tari.rpc.AggregateBody
|
||||
8, // [8:8] is the sub-list for method output_type
|
||||
8, // [8:8] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
8, // [8:8] is the sub-list for extension extendee
|
||||
0, // [0:8] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_block_proto_init() }
|
||||
func file_block_proto_init() {
|
||||
if File_block_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_block_proto_rawDesc), len(file_block_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 7,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_block_proto_goTypes,
|
||||
DependencyIndexes: file_block_proto_depIdxs,
|
||||
EnumInfos: file_block_proto_enumTypes,
|
||||
MessageInfos: file_block_proto_msgTypes,
|
||||
}.Build()
|
||||
File_block_proto = out.File
|
||||
file_block_proto_goTypes = nil
|
||||
file_block_proto_depIdxs = nil
|
||||
}
|
|
@ -1,790 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v3.6.1
|
||||
// source: network.proto
|
||||
|
||||
package net_work
|
||||
|
||||
import (
|
||||
_ "github.com/golang/protobuf/ptypes/timestamp"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type ConnectivityStatus int32
|
||||
|
||||
const (
|
||||
ConnectivityStatus_Initializing ConnectivityStatus = 0
|
||||
ConnectivityStatus_Online ConnectivityStatus = 1
|
||||
ConnectivityStatus_Degraded ConnectivityStatus = 2
|
||||
ConnectivityStatus_Offline ConnectivityStatus = 3
|
||||
)
|
||||
|
||||
// Enum value maps for ConnectivityStatus.
|
||||
var (
|
||||
ConnectivityStatus_name = map[int32]string{
|
||||
0: "Initializing",
|
||||
1: "Online",
|
||||
2: "Degraded",
|
||||
3: "Offline",
|
||||
}
|
||||
ConnectivityStatus_value = map[string]int32{
|
||||
"Initializing": 0,
|
||||
"Online": 1,
|
||||
"Degraded": 2,
|
||||
"Offline": 3,
|
||||
}
|
||||
)
|
||||
|
||||
func (x ConnectivityStatus) Enum() *ConnectivityStatus {
|
||||
p := new(ConnectivityStatus)
|
||||
*p = x
|
||||
return p
|
||||
}
|
||||
|
||||
func (x ConnectivityStatus) String() string {
|
||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||
}
|
||||
|
||||
func (ConnectivityStatus) Descriptor() protoreflect.EnumDescriptor {
|
||||
return file_network_proto_enumTypes[0].Descriptor()
|
||||
}
|
||||
|
||||
func (ConnectivityStatus) Type() protoreflect.EnumType {
|
||||
return &file_network_proto_enumTypes[0]
|
||||
}
|
||||
|
||||
func (x ConnectivityStatus) Number() protoreflect.EnumNumber {
|
||||
return protoreflect.EnumNumber(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ConnectivityStatus.Descriptor instead.
|
||||
func (ConnectivityStatus) EnumDescriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
type NodeIdentity struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||
PublicAddresses []string `protobuf:"bytes,2,rep,name=public_addresses,json=publicAddresses,proto3" json:"public_addresses,omitempty"`
|
||||
NodeId []byte `protobuf:"bytes,3,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NodeIdentity) Reset() {
|
||||
*x = NodeIdentity{}
|
||||
mi := &file_network_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NodeIdentity) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NodeIdentity) ProtoMessage() {}
|
||||
|
||||
func (x *NodeIdentity) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NodeIdentity.ProtoReflect.Descriptor instead.
|
||||
func (*NodeIdentity) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *NodeIdentity) GetPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NodeIdentity) GetPublicAddresses() []string {
|
||||
if x != nil {
|
||||
return x.PublicAddresses
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *NodeIdentity) GetNodeId() []byte {
|
||||
if x != nil {
|
||||
return x.NodeId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type Peer struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// / Public key of the peer
|
||||
PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||
// / NodeId of the peer
|
||||
NodeId []byte `protobuf:"bytes,2,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
|
||||
// / Peer's addresses
|
||||
Addresses []*Address `protobuf:"bytes,3,rep,name=addresses,proto3" json:"addresses,omitempty"`
|
||||
// / Last connection attempt to peer
|
||||
LastConnection uint64 `protobuf:"varint,4,opt,name=last_connection,json=lastConnection,proto3" json:"last_connection,omitempty"`
|
||||
// / Flags for the peer.
|
||||
Flags uint32 `protobuf:"varint,5,opt,name=flags,proto3" json:"flags,omitempty"`
|
||||
BannedUntil uint64 `protobuf:"varint,6,opt,name=banned_until,json=bannedUntil,proto3" json:"banned_until,omitempty"`
|
||||
BannedReason string `protobuf:"bytes,7,opt,name=banned_reason,json=bannedReason,proto3" json:"banned_reason,omitempty"`
|
||||
OfflineAt uint64 `protobuf:"varint,8,opt,name=offline_at,json=offlineAt,proto3" json:"offline_at,omitempty"`
|
||||
// / Features supported by the peer
|
||||
Features uint32 `protobuf:"varint,9,opt,name=features,proto3" json:"features,omitempty"`
|
||||
// / used as information for more efficient protocol negotiation.
|
||||
SupportedProtocols [][]byte `protobuf:"bytes,11,rep,name=supported_protocols,json=supportedProtocols,proto3" json:"supported_protocols,omitempty"`
|
||||
// / User agent advertised by the peer
|
||||
UserAgent string `protobuf:"bytes,12,opt,name=user_agent,json=userAgent,proto3" json:"user_agent,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Peer) Reset() {
|
||||
*x = Peer{}
|
||||
mi := &file_network_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Peer) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Peer) ProtoMessage() {}
|
||||
|
||||
func (x *Peer) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Peer.ProtoReflect.Descriptor instead.
|
||||
func (*Peer) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Peer) GetPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Peer) GetNodeId() []byte {
|
||||
if x != nil {
|
||||
return x.NodeId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Peer) GetAddresses() []*Address {
|
||||
if x != nil {
|
||||
return x.Addresses
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Peer) GetLastConnection() uint64 {
|
||||
if x != nil {
|
||||
return x.LastConnection
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Peer) GetFlags() uint32 {
|
||||
if x != nil {
|
||||
return x.Flags
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Peer) GetBannedUntil() uint64 {
|
||||
if x != nil {
|
||||
return x.BannedUntil
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Peer) GetBannedReason() string {
|
||||
if x != nil {
|
||||
return x.BannedReason
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Peer) GetOfflineAt() uint64 {
|
||||
if x != nil {
|
||||
return x.OfflineAt
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Peer) GetFeatures() uint32 {
|
||||
if x != nil {
|
||||
return x.Features
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Peer) GetSupportedProtocols() [][]byte {
|
||||
if x != nil {
|
||||
return x.SupportedProtocols
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Peer) GetUserAgent() string {
|
||||
if x != nil {
|
||||
return x.UserAgent
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type NetworkStatusResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Status ConnectivityStatus `protobuf:"varint,1,opt,name=status,proto3,enum=tari.rpc.ConnectivityStatus" json:"status,omitempty"`
|
||||
AvgLatencyMs uint32 `protobuf:"varint,2,opt,name=avg_latency_ms,json=avgLatencyMs,proto3" json:"avg_latency_ms,omitempty"`
|
||||
NumNodeConnections uint32 `protobuf:"varint,3,opt,name=num_node_connections,json=numNodeConnections,proto3" json:"num_node_connections,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *NetworkStatusResponse) Reset() {
|
||||
*x = NetworkStatusResponse{}
|
||||
mi := &file_network_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *NetworkStatusResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*NetworkStatusResponse) ProtoMessage() {}
|
||||
|
||||
func (x *NetworkStatusResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use NetworkStatusResponse.ProtoReflect.Descriptor instead.
|
||||
func (*NetworkStatusResponse) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *NetworkStatusResponse) GetStatus() ConnectivityStatus {
|
||||
if x != nil {
|
||||
return x.Status
|
||||
}
|
||||
return ConnectivityStatus_Initializing
|
||||
}
|
||||
|
||||
func (x *NetworkStatusResponse) GetAvgLatencyMs() uint32 {
|
||||
if x != nil {
|
||||
return x.AvgLatencyMs
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *NetworkStatusResponse) GetNumNodeConnections() uint32 {
|
||||
if x != nil {
|
||||
return x.NumNodeConnections
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Address []byte `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"`
|
||||
LastSeen string `protobuf:"bytes,2,opt,name=last_seen,json=lastSeen,proto3" json:"last_seen,omitempty"`
|
||||
ConnectionAttempts uint32 `protobuf:"varint,3,opt,name=connection_attempts,json=connectionAttempts,proto3" json:"connection_attempts,omitempty"`
|
||||
AvgLatency *AverageLatency `protobuf:"bytes,5,opt,name=avg_latency,json=avgLatency,proto3" json:"avg_latency,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *Address) Reset() {
|
||||
*x = Address{}
|
||||
mi := &file_network_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *Address) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Address) ProtoMessage() {}
|
||||
|
||||
func (x *Address) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Address.ProtoReflect.Descriptor instead.
|
||||
func (*Address) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *Address) GetAddress() []byte {
|
||||
if x != nil {
|
||||
return x.Address
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Address) GetLastSeen() string {
|
||||
if x != nil {
|
||||
return x.LastSeen
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Address) GetConnectionAttempts() uint32 {
|
||||
if x != nil {
|
||||
return x.ConnectionAttempts
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Address) GetAvgLatency() *AverageLatency {
|
||||
if x != nil {
|
||||
return x.AvgLatency
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type AverageLatency struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Latency uint64 `protobuf:"varint,1,opt,name=latency,proto3" json:"latency,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AverageLatency) Reset() {
|
||||
*x = AverageLatency{}
|
||||
mi := &file_network_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AverageLatency) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AverageLatency) ProtoMessage() {}
|
||||
|
||||
func (x *AverageLatency) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AverageLatency.ProtoReflect.Descriptor instead.
|
||||
func (*AverageLatency) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *AverageLatency) GetLatency() uint64 {
|
||||
if x != nil {
|
||||
return x.Latency
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type ListConnectedPeersResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ConnectedPeers []*Peer `protobuf:"bytes,1,rep,name=connected_peers,json=connectedPeers,proto3" json:"connected_peers,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ListConnectedPeersResponse) Reset() {
|
||||
*x = ListConnectedPeersResponse{}
|
||||
mi := &file_network_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ListConnectedPeersResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ListConnectedPeersResponse) ProtoMessage() {}
|
||||
|
||||
func (x *ListConnectedPeersResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ListConnectedPeersResponse.ProtoReflect.Descriptor instead.
|
||||
func (*ListConnectedPeersResponse) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *ListConnectedPeersResponse) GetConnectedPeers() []*Peer {
|
||||
if x != nil {
|
||||
return x.ConnectedPeers
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SoftwareUpdate struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
HasUpdate bool `protobuf:"varint,1,opt,name=has_update,json=hasUpdate,proto3" json:"has_update,omitempty"`
|
||||
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
Sha string `protobuf:"bytes,3,opt,name=sha,proto3" json:"sha,omitempty"`
|
||||
DownloadUrl string `protobuf:"bytes,4,opt,name=download_url,json=downloadUrl,proto3" json:"download_url,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *SoftwareUpdate) Reset() {
|
||||
*x = SoftwareUpdate{}
|
||||
mi := &file_network_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *SoftwareUpdate) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SoftwareUpdate) ProtoMessage() {}
|
||||
|
||||
func (x *SoftwareUpdate) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SoftwareUpdate.ProtoReflect.Descriptor instead.
|
||||
func (*SoftwareUpdate) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
func (x *SoftwareUpdate) GetHasUpdate() bool {
|
||||
if x != nil {
|
||||
return x.HasUpdate
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *SoftwareUpdate) GetVersion() string {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SoftwareUpdate) GetSha() string {
|
||||
if x != nil {
|
||||
return x.Sha
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *SoftwareUpdate) GetDownloadUrl() string {
|
||||
if x != nil {
|
||||
return x.DownloadUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type GetIdentityRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetIdentityRequest) Reset() {
|
||||
*x = GetIdentityRequest{}
|
||||
mi := &file_network_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetIdentityRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetIdentityRequest) ProtoMessage() {}
|
||||
|
||||
func (x *GetIdentityRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[7]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetIdentityRequest.ProtoReflect.Descriptor instead.
|
||||
func (*GetIdentityRequest) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
type GetIdentityResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||
PublicAddress string `protobuf:"bytes,2,opt,name=public_address,json=publicAddress,proto3" json:"public_address,omitempty"`
|
||||
NodeId []byte `protobuf:"bytes,3,opt,name=node_id,json=nodeId,proto3" json:"node_id,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *GetIdentityResponse) Reset() {
|
||||
*x = GetIdentityResponse{}
|
||||
mi := &file_network_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *GetIdentityResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*GetIdentityResponse) ProtoMessage() {}
|
||||
|
||||
func (x *GetIdentityResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_network_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use GetIdentityResponse.ProtoReflect.Descriptor instead.
|
||||
func (*GetIdentityResponse) Descriptor() ([]byte, []int) {
|
||||
return file_network_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *GetIdentityResponse) GetPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *GetIdentityResponse) GetPublicAddress() string {
|
||||
if x != nil {
|
||||
return x.PublicAddress
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *GetIdentityResponse) GetNodeId() []byte {
|
||||
if x != nil {
|
||||
return x.NodeId
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_network_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_network_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\rnetwork.proto\x12\btari.rpc\x1a\x1fgoogle/protobuf/timestamp.proto\"q\n" +
|
||||
"\fNodeIdentity\x12\x1d\n" +
|
||||
"\n" +
|
||||
"public_key\x18\x01 \x01(\fR\tpublicKey\x12)\n" +
|
||||
"\x10public_addresses\x18\x02 \x03(\tR\x0fpublicAddresses\x12\x17\n" +
|
||||
"\anode_id\x18\x03 \x01(\fR\x06nodeId\"\x81\x03\n" +
|
||||
"\x04Peer\x12\x1d\n" +
|
||||
"\n" +
|
||||
"public_key\x18\x01 \x01(\fR\tpublicKey\x12\x17\n" +
|
||||
"\anode_id\x18\x02 \x01(\fR\x06nodeId\x12/\n" +
|
||||
"\taddresses\x18\x03 \x03(\v2\x11.tari.rpc.AddressR\taddresses\x12'\n" +
|
||||
"\x0flast_connection\x18\x04 \x01(\x04R\x0elastConnection\x12\x14\n" +
|
||||
"\x05flags\x18\x05 \x01(\rR\x05flags\x12!\n" +
|
||||
"\fbanned_until\x18\x06 \x01(\x04R\vbannedUntil\x12#\n" +
|
||||
"\rbanned_reason\x18\a \x01(\tR\fbannedReason\x12\x1d\n" +
|
||||
"\n" +
|
||||
"offline_at\x18\b \x01(\x04R\tofflineAt\x12\x1a\n" +
|
||||
"\bfeatures\x18\t \x01(\rR\bfeatures\x12/\n" +
|
||||
"\x13supported_protocols\x18\v \x03(\fR\x12supportedProtocols\x12\x1d\n" +
|
||||
"\n" +
|
||||
"user_agent\x18\f \x01(\tR\tuserAgent\"\xa5\x01\n" +
|
||||
"\x15NetworkStatusResponse\x124\n" +
|
||||
"\x06status\x18\x01 \x01(\x0e2\x1c.tari.rpc.ConnectivityStatusR\x06status\x12$\n" +
|
||||
"\x0eavg_latency_ms\x18\x02 \x01(\rR\favgLatencyMs\x120\n" +
|
||||
"\x14num_node_connections\x18\x03 \x01(\rR\x12numNodeConnections\"\xac\x01\n" +
|
||||
"\aAddress\x12\x18\n" +
|
||||
"\aaddress\x18\x01 \x01(\fR\aaddress\x12\x1b\n" +
|
||||
"\tlast_seen\x18\x02 \x01(\tR\blastSeen\x12/\n" +
|
||||
"\x13connection_attempts\x18\x03 \x01(\rR\x12connectionAttempts\x129\n" +
|
||||
"\vavg_latency\x18\x05 \x01(\v2\x18.tari.rpc.AverageLatencyR\n" +
|
||||
"avgLatency\"*\n" +
|
||||
"\x0eAverageLatency\x12\x18\n" +
|
||||
"\alatency\x18\x01 \x01(\x04R\alatency\"U\n" +
|
||||
"\x1aListConnectedPeersResponse\x127\n" +
|
||||
"\x0fconnected_peers\x18\x01 \x03(\v2\x0e.tari.rpc.PeerR\x0econnectedPeers\"~\n" +
|
||||
"\x0eSoftwareUpdate\x12\x1d\n" +
|
||||
"\n" +
|
||||
"has_update\x18\x01 \x01(\bR\thasUpdate\x12\x18\n" +
|
||||
"\aversion\x18\x02 \x01(\tR\aversion\x12\x10\n" +
|
||||
"\x03sha\x18\x03 \x01(\tR\x03sha\x12!\n" +
|
||||
"\fdownload_url\x18\x04 \x01(\tR\vdownloadUrl\"\x14\n" +
|
||||
"\x12GetIdentityRequest\"t\n" +
|
||||
"\x13GetIdentityResponse\x12\x1d\n" +
|
||||
"\n" +
|
||||
"public_key\x18\x01 \x01(\fR\tpublicKey\x12%\n" +
|
||||
"\x0epublic_address\x18\x02 \x01(\tR\rpublicAddress\x12\x17\n" +
|
||||
"\anode_id\x18\x03 \x01(\fR\x06nodeId*M\n" +
|
||||
"\x12ConnectivityStatus\x12\x10\n" +
|
||||
"\fInitializing\x10\x00\x12\n" +
|
||||
"\n" +
|
||||
"\x06Online\x10\x01\x12\f\n" +
|
||||
"\bDegraded\x10\x02\x12\v\n" +
|
||||
"\aOffline\x10\x03B*Z(pool/internal/gbt/tari/net_work;net_workb\x06proto3"
|
||||
|
||||
var (
|
||||
file_network_proto_rawDescOnce sync.Once
|
||||
file_network_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_network_proto_rawDescGZIP() []byte {
|
||||
file_network_proto_rawDescOnce.Do(func() {
|
||||
file_network_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_network_proto_rawDesc), len(file_network_proto_rawDesc)))
|
||||
})
|
||||
return file_network_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_network_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||
var file_network_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||
var file_network_proto_goTypes = []any{
|
||||
(ConnectivityStatus)(0), // 0: tari.rpc.ConnectivityStatus
|
||||
(*NodeIdentity)(nil), // 1: tari.rpc.NodeIdentity
|
||||
(*Peer)(nil), // 2: tari.rpc.Peer
|
||||
(*NetworkStatusResponse)(nil), // 3: tari.rpc.NetworkStatusResponse
|
||||
(*Address)(nil), // 4: tari.rpc.Address
|
||||
(*AverageLatency)(nil), // 5: tari.rpc.AverageLatency
|
||||
(*ListConnectedPeersResponse)(nil), // 6: tari.rpc.ListConnectedPeersResponse
|
||||
(*SoftwareUpdate)(nil), // 7: tari.rpc.SoftwareUpdate
|
||||
(*GetIdentityRequest)(nil), // 8: tari.rpc.GetIdentityRequest
|
||||
(*GetIdentityResponse)(nil), // 9: tari.rpc.GetIdentityResponse
|
||||
}
|
||||
var file_network_proto_depIdxs = []int32{
|
||||
4, // 0: tari.rpc.Peer.addresses:type_name -> tari.rpc.Address
|
||||
0, // 1: tari.rpc.NetworkStatusResponse.status:type_name -> tari.rpc.ConnectivityStatus
|
||||
5, // 2: tari.rpc.Address.avg_latency:type_name -> tari.rpc.AverageLatency
|
||||
2, // 3: tari.rpc.ListConnectedPeersResponse.connected_peers:type_name -> tari.rpc.Peer
|
||||
4, // [4:4] is the sub-list for method output_type
|
||||
4, // [4:4] is the sub-list for method input_type
|
||||
4, // [4:4] is the sub-list for extension type_name
|
||||
4, // [4:4] is the sub-list for extension extendee
|
||||
0, // [0:4] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_network_proto_init() }
|
||||
func file_network_proto_init() {
|
||||
if File_network_proto != nil {
|
||||
return
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_network_proto_rawDesc), len(file_network_proto_rawDesc)),
|
||||
NumEnums: 1,
|
||||
NumMessages: 9,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_network_proto_goTypes,
|
||||
DependencyIndexes: file_network_proto_depIdxs,
|
||||
EnumInfos: file_network_proto_enumTypes,
|
||||
MessageInfos: file_network_proto_msgTypes,
|
||||
}.Build()
|
||||
File_network_proto = out.File
|
||||
file_network_proto_goTypes = nil
|
||||
file_network_proto_depIdxs = nil
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message NodeIdentity {
|
||||
bytes public_key = 1;
|
||||
repeated string public_addresses = 2;
|
||||
bytes node_id = 3;
|
||||
}
|
||||
|
||||
message Peer {
|
||||
/// Public key of the peer
|
||||
bytes public_key =1;
|
||||
/// NodeId of the peer
|
||||
bytes node_id =2;
|
||||
/// Peer's addresses
|
||||
repeated Address addresses = 3;
|
||||
/// Last connection attempt to peer
|
||||
uint64 last_connection = 4;
|
||||
/// Flags for the peer.
|
||||
uint32 flags = 5;
|
||||
uint64 banned_until= 6;
|
||||
string banned_reason= 7;
|
||||
uint64 offline_at = 8;
|
||||
/// Features supported by the peer
|
||||
uint32 features = 9;
|
||||
/// used as information for more efficient protocol negotiation.
|
||||
repeated bytes supported_protocols = 11;
|
||||
/// User agent advertised by the peer
|
||||
string user_agent = 12;
|
||||
}
|
||||
|
||||
enum ConnectivityStatus {
|
||||
Initializing = 0;
|
||||
Online = 1;
|
||||
Degraded = 2;
|
||||
Offline = 3;
|
||||
}
|
||||
|
||||
message NetworkStatusResponse {
|
||||
ConnectivityStatus status = 1;
|
||||
uint32 avg_latency_ms = 2;
|
||||
uint32 num_node_connections = 3;
|
||||
}
|
||||
|
||||
message Address{
|
||||
bytes address =1;
|
||||
string last_seen = 2;
|
||||
uint32 connection_attempts = 3;
|
||||
AverageLatency avg_latency = 5;
|
||||
}
|
||||
|
||||
message AverageLatency {
|
||||
uint64 latency = 1;
|
||||
}
|
||||
|
||||
message ListConnectedPeersResponse {
|
||||
repeated Peer connected_peers = 1;
|
||||
}
|
||||
|
||||
message SoftwareUpdate {
|
||||
bool has_update = 1;
|
||||
string version = 2;
|
||||
string sha = 3;
|
||||
string download_url = 4;
|
||||
}
|
||||
|
||||
message GetIdentityRequest { }
|
||||
|
||||
message GetIdentityResponse {
|
||||
bytes public_key = 1;
|
||||
string public_address = 2;
|
||||
bytes node_id = 3;
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
// Copyright 2024. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
import "base_node.proto";
|
||||
import "block.proto";
|
||||
|
||||
service ShaP2Pool {
|
||||
rpc GetTipInfo(GetTipInfoRequest) returns(GetTipInfoResponse);
|
||||
rpc GetNewBlock(GetNewBlockRequest) returns(GetNewBlockResponse);
|
||||
rpc SubmitBlock(SubmitBlockRequest) returns(tari.rpc.SubmitBlockResponse);
|
||||
}
|
||||
|
||||
message GetTipInfoRequest {
|
||||
}
|
||||
|
||||
message GetTipInfoResponse {
|
||||
uint64 node_height = 1;
|
||||
bytes node_tip_hash = 2;
|
||||
uint64 p2pool_rx_height = 3;
|
||||
bytes p2pool_rx_tip_hash = 4;
|
||||
uint64 p2pool_sha_height = 5;
|
||||
bytes p2pool_sha_tip_hash = 6;
|
||||
}
|
||||
|
||||
message GetNewBlockRequest {
|
||||
tari.rpc.PowAlgo pow = 1;
|
||||
string coinbase_extra = 2;
|
||||
string wallet_payment_address = 3;
|
||||
}
|
||||
|
||||
message GetNewBlockResponse {
|
||||
tari.rpc.GetNewBlockResult block = 1;
|
||||
uint64 target_difficulty = 2;
|
||||
}
|
||||
|
||||
message SubmitBlockRequest {
|
||||
tari.rpc.Block block = 1;
|
||||
string wallet_payment_address = 2;
|
||||
}
|
|
@ -1,77 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
import "types.proto";
|
||||
|
||||
message SideChainFeature {
|
||||
oneof side_chain_feature {
|
||||
ValidatorNodeRegistration validator_node_registration = 1;
|
||||
TemplateRegistration template_registration = 2;
|
||||
ConfidentialOutputData confidential_output = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message ValidatorNodeRegistration {
|
||||
bytes public_key = 1;
|
||||
Signature signature = 2;
|
||||
}
|
||||
|
||||
message TemplateRegistration {
|
||||
bytes author_public_key = 1;
|
||||
Signature author_signature = 2;
|
||||
string template_name = 3;
|
||||
uint32 template_version = 4;
|
||||
TemplateType template_type = 5;
|
||||
BuildInfo build_info = 6;
|
||||
bytes binary_sha = 7;
|
||||
string binary_url = 8;
|
||||
}
|
||||
|
||||
message ConfidentialOutputData {
|
||||
bytes claim_public_key = 1;
|
||||
}
|
||||
|
||||
message TemplateType {
|
||||
oneof template_type {
|
||||
WasmInfo wasm = 1;
|
||||
FlowInfo flow = 2;
|
||||
ManifestInfo manifest = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message WasmInfo {
|
||||
uint32 abi_version = 1;
|
||||
}
|
||||
|
||||
message FlowInfo {
|
||||
}
|
||||
|
||||
message ManifestInfo {
|
||||
}
|
||||
|
||||
message BuildInfo {
|
||||
string repo_url = 1;
|
||||
bytes commit_hash = 2;
|
||||
}
|
|
@ -1,727 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.36.6
|
||||
// protoc v3.6.1
|
||||
// source: sidechain_types.proto
|
||||
|
||||
package sidechain_types
|
||||
|
||||
import (
|
||||
types "pool/internal/gbt/tari/proto/types"
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
unsafe "unsafe"
|
||||
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type SideChainFeature struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to SideChainFeature:
|
||||
//
|
||||
// *SideChainFeature_ValidatorNodeRegistration
|
||||
// *SideChainFeature_TemplateRegistration
|
||||
// *SideChainFeature_ConfidentialOutput
|
||||
SideChainFeature isSideChainFeature_SideChainFeature `protobuf_oneof:"side_chain_feature"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *SideChainFeature) Reset() {
|
||||
*x = SideChainFeature{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *SideChainFeature) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SideChainFeature) ProtoMessage() {}
|
||||
|
||||
func (x *SideChainFeature) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[0]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SideChainFeature.ProtoReflect.Descriptor instead.
|
||||
func (*SideChainFeature) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *SideChainFeature) GetSideChainFeature() isSideChainFeature_SideChainFeature {
|
||||
if x != nil {
|
||||
return x.SideChainFeature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SideChainFeature) GetValidatorNodeRegistration() *ValidatorNodeRegistration {
|
||||
if x != nil {
|
||||
if x, ok := x.SideChainFeature.(*SideChainFeature_ValidatorNodeRegistration); ok {
|
||||
return x.ValidatorNodeRegistration
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SideChainFeature) GetTemplateRegistration() *TemplateRegistration {
|
||||
if x != nil {
|
||||
if x, ok := x.SideChainFeature.(*SideChainFeature_TemplateRegistration); ok {
|
||||
return x.TemplateRegistration
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SideChainFeature) GetConfidentialOutput() *ConfidentialOutputData {
|
||||
if x != nil {
|
||||
if x, ok := x.SideChainFeature.(*SideChainFeature_ConfidentialOutput); ok {
|
||||
return x.ConfidentialOutput
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isSideChainFeature_SideChainFeature interface {
|
||||
isSideChainFeature_SideChainFeature()
|
||||
}
|
||||
|
||||
type SideChainFeature_ValidatorNodeRegistration struct {
|
||||
ValidatorNodeRegistration *ValidatorNodeRegistration `protobuf:"bytes,1,opt,name=validator_node_registration,json=validatorNodeRegistration,proto3,oneof"`
|
||||
}
|
||||
|
||||
type SideChainFeature_TemplateRegistration struct {
|
||||
TemplateRegistration *TemplateRegistration `protobuf:"bytes,2,opt,name=template_registration,json=templateRegistration,proto3,oneof"`
|
||||
}
|
||||
|
||||
type SideChainFeature_ConfidentialOutput struct {
|
||||
ConfidentialOutput *ConfidentialOutputData `protobuf:"bytes,3,opt,name=confidential_output,json=confidentialOutput,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*SideChainFeature_ValidatorNodeRegistration) isSideChainFeature_SideChainFeature() {}
|
||||
|
||||
func (*SideChainFeature_TemplateRegistration) isSideChainFeature_SideChainFeature() {}
|
||||
|
||||
func (*SideChainFeature_ConfidentialOutput) isSideChainFeature_SideChainFeature() {}
|
||||
|
||||
type ValidatorNodeRegistration struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
PublicKey []byte `protobuf:"bytes,1,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"`
|
||||
Signature *types.Signature `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ValidatorNodeRegistration) Reset() {
|
||||
*x = ValidatorNodeRegistration{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ValidatorNodeRegistration) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ValidatorNodeRegistration) ProtoMessage() {}
|
||||
|
||||
func (x *ValidatorNodeRegistration) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[1]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ValidatorNodeRegistration.ProtoReflect.Descriptor instead.
|
||||
func (*ValidatorNodeRegistration) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *ValidatorNodeRegistration) GetPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.PublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ValidatorNodeRegistration) GetSignature() *types.Signature {
|
||||
if x != nil {
|
||||
return x.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type TemplateRegistration struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AuthorPublicKey []byte `protobuf:"bytes,1,opt,name=author_public_key,json=authorPublicKey,proto3" json:"author_public_key,omitempty"`
|
||||
AuthorSignature *types.Signature `protobuf:"bytes,2,opt,name=author_signature,json=authorSignature,proto3" json:"author_signature,omitempty"`
|
||||
TemplateName string `protobuf:"bytes,3,opt,name=template_name,json=templateName,proto3" json:"template_name,omitempty"`
|
||||
TemplateVersion uint32 `protobuf:"varint,4,opt,name=template_version,json=templateVersion,proto3" json:"template_version,omitempty"`
|
||||
TemplateType *TemplateType `protobuf:"bytes,5,opt,name=template_type,json=templateType,proto3" json:"template_type,omitempty"`
|
||||
BuildInfo *BuildInfo `protobuf:"bytes,6,opt,name=build_info,json=buildInfo,proto3" json:"build_info,omitempty"`
|
||||
BinarySha []byte `protobuf:"bytes,7,opt,name=binary_sha,json=binarySha,proto3" json:"binary_sha,omitempty"`
|
||||
BinaryUrl string `protobuf:"bytes,8,opt,name=binary_url,json=binaryUrl,proto3" json:"binary_url,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) Reset() {
|
||||
*x = TemplateRegistration{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*TemplateRegistration) ProtoMessage() {}
|
||||
|
||||
func (x *TemplateRegistration) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[2]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use TemplateRegistration.ProtoReflect.Descriptor instead.
|
||||
func (*TemplateRegistration) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetAuthorPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.AuthorPublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetAuthorSignature() *types.Signature {
|
||||
if x != nil {
|
||||
return x.AuthorSignature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetTemplateName() string {
|
||||
if x != nil {
|
||||
return x.TemplateName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetTemplateVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.TemplateVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetTemplateType() *TemplateType {
|
||||
if x != nil {
|
||||
return x.TemplateType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetBuildInfo() *BuildInfo {
|
||||
if x != nil {
|
||||
return x.BuildInfo
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetBinarySha() []byte {
|
||||
if x != nil {
|
||||
return x.BinarySha
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateRegistration) GetBinaryUrl() string {
|
||||
if x != nil {
|
||||
return x.BinaryUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ConfidentialOutputData struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
ClaimPublicKey []byte `protobuf:"bytes,1,opt,name=claim_public_key,json=claimPublicKey,proto3" json:"claim_public_key,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ConfidentialOutputData) Reset() {
|
||||
*x = ConfidentialOutputData{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ConfidentialOutputData) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ConfidentialOutputData) ProtoMessage() {}
|
||||
|
||||
func (x *ConfidentialOutputData) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[3]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ConfidentialOutputData.ProtoReflect.Descriptor instead.
|
||||
func (*ConfidentialOutputData) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *ConfidentialOutputData) GetClaimPublicKey() []byte {
|
||||
if x != nil {
|
||||
return x.ClaimPublicKey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type TemplateType struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to TemplateType:
|
||||
//
|
||||
// *TemplateType_Wasm
|
||||
// *TemplateType_Flow
|
||||
// *TemplateType_Manifest
|
||||
TemplateType isTemplateType_TemplateType `protobuf_oneof:"template_type"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *TemplateType) Reset() {
|
||||
*x = TemplateType{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *TemplateType) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*TemplateType) ProtoMessage() {}
|
||||
|
||||
func (x *TemplateType) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[4]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use TemplateType.ProtoReflect.Descriptor instead.
|
||||
func (*TemplateType) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *TemplateType) GetTemplateType() isTemplateType_TemplateType {
|
||||
if x != nil {
|
||||
return x.TemplateType
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateType) GetWasm() *WasmInfo {
|
||||
if x != nil {
|
||||
if x, ok := x.TemplateType.(*TemplateType_Wasm); ok {
|
||||
return x.Wasm
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateType) GetFlow() *FlowInfo {
|
||||
if x != nil {
|
||||
if x, ok := x.TemplateType.(*TemplateType_Flow); ok {
|
||||
return x.Flow
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *TemplateType) GetManifest() *ManifestInfo {
|
||||
if x != nil {
|
||||
if x, ok := x.TemplateType.(*TemplateType_Manifest); ok {
|
||||
return x.Manifest
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isTemplateType_TemplateType interface {
|
||||
isTemplateType_TemplateType()
|
||||
}
|
||||
|
||||
type TemplateType_Wasm struct {
|
||||
Wasm *WasmInfo `protobuf:"bytes,1,opt,name=wasm,proto3,oneof"`
|
||||
}
|
||||
|
||||
type TemplateType_Flow struct {
|
||||
Flow *FlowInfo `protobuf:"bytes,2,opt,name=flow,proto3,oneof"`
|
||||
}
|
||||
|
||||
type TemplateType_Manifest struct {
|
||||
Manifest *ManifestInfo `protobuf:"bytes,3,opt,name=manifest,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*TemplateType_Wasm) isTemplateType_TemplateType() {}
|
||||
|
||||
func (*TemplateType_Flow) isTemplateType_TemplateType() {}
|
||||
|
||||
func (*TemplateType_Manifest) isTemplateType_TemplateType() {}
|
||||
|
||||
type WasmInfo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
AbiVersion uint32 `protobuf:"varint,1,opt,name=abi_version,json=abiVersion,proto3" json:"abi_version,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *WasmInfo) Reset() {
|
||||
*x = WasmInfo{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *WasmInfo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*WasmInfo) ProtoMessage() {}
|
||||
|
||||
func (x *WasmInfo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[5]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use WasmInfo.ProtoReflect.Descriptor instead.
|
||||
func (*WasmInfo) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *WasmInfo) GetAbiVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.AbiVersion
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type FlowInfo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *FlowInfo) Reset() {
|
||||
*x = FlowInfo{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[6]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *FlowInfo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*FlowInfo) ProtoMessage() {}
|
||||
|
||||
func (x *FlowInfo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[6]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use FlowInfo.ProtoReflect.Descriptor instead.
|
||||
func (*FlowInfo) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{6}
|
||||
}
|
||||
|
||||
type ManifestInfo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *ManifestInfo) Reset() {
|
||||
*x = ManifestInfo{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[7]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *ManifestInfo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ManifestInfo) ProtoMessage() {}
|
||||
|
||||
func (x *ManifestInfo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[7]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ManifestInfo.ProtoReflect.Descriptor instead.
|
||||
func (*ManifestInfo) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{7}
|
||||
}
|
||||
|
||||
type BuildInfo struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
RepoUrl string `protobuf:"bytes,1,opt,name=repo_url,json=repoUrl,proto3" json:"repo_url,omitempty"`
|
||||
CommitHash []byte `protobuf:"bytes,2,opt,name=commit_hash,json=commitHash,proto3" json:"commit_hash,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *BuildInfo) Reset() {
|
||||
*x = BuildInfo{}
|
||||
mi := &file_sidechain_types_proto_msgTypes[8]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *BuildInfo) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*BuildInfo) ProtoMessage() {}
|
||||
|
||||
func (x *BuildInfo) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_sidechain_types_proto_msgTypes[8]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use BuildInfo.ProtoReflect.Descriptor instead.
|
||||
func (*BuildInfo) Descriptor() ([]byte, []int) {
|
||||
return file_sidechain_types_proto_rawDescGZIP(), []int{8}
|
||||
}
|
||||
|
||||
func (x *BuildInfo) GetRepoUrl() string {
|
||||
if x != nil {
|
||||
return x.RepoUrl
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *BuildInfo) GetCommitHash() []byte {
|
||||
if x != nil {
|
||||
return x.CommitHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_sidechain_types_proto protoreflect.FileDescriptor
|
||||
|
||||
const file_sidechain_types_proto_rawDesc = "" +
|
||||
"\n" +
|
||||
"\x15sidechain_types.proto\x12\btari.rpc\x1a\vtypes.proto\"\xbb\x02\n" +
|
||||
"\x10SideChainFeature\x12e\n" +
|
||||
"\x1bvalidator_node_registration\x18\x01 \x01(\v2#.tari.rpc.ValidatorNodeRegistrationH\x00R\x19validatorNodeRegistration\x12U\n" +
|
||||
"\x15template_registration\x18\x02 \x01(\v2\x1e.tari.rpc.TemplateRegistrationH\x00R\x14templateRegistration\x12S\n" +
|
||||
"\x13confidential_output\x18\x03 \x01(\v2 .tari.rpc.ConfidentialOutputDataH\x00R\x12confidentialOutputB\x14\n" +
|
||||
"\x12side_chain_feature\"m\n" +
|
||||
"\x19ValidatorNodeRegistration\x12\x1d\n" +
|
||||
"\n" +
|
||||
"public_key\x18\x01 \x01(\fR\tpublicKey\x121\n" +
|
||||
"\tsignature\x18\x02 \x01(\v2\x13.tari.rpc.SignatureR\tsignature\"\x81\x03\n" +
|
||||
"\x14TemplateRegistration\x12*\n" +
|
||||
"\x11author_public_key\x18\x01 \x01(\fR\x0fauthorPublicKey\x12>\n" +
|
||||
"\x10author_signature\x18\x02 \x01(\v2\x13.tari.rpc.SignatureR\x0fauthorSignature\x12#\n" +
|
||||
"\rtemplate_name\x18\x03 \x01(\tR\ftemplateName\x12)\n" +
|
||||
"\x10template_version\x18\x04 \x01(\rR\x0ftemplateVersion\x12;\n" +
|
||||
"\rtemplate_type\x18\x05 \x01(\v2\x16.tari.rpc.TemplateTypeR\ftemplateType\x122\n" +
|
||||
"\n" +
|
||||
"build_info\x18\x06 \x01(\v2\x13.tari.rpc.BuildInfoR\tbuildInfo\x12\x1d\n" +
|
||||
"\n" +
|
||||
"binary_sha\x18\a \x01(\fR\tbinarySha\x12\x1d\n" +
|
||||
"\n" +
|
||||
"binary_url\x18\b \x01(\tR\tbinaryUrl\"B\n" +
|
||||
"\x16ConfidentialOutputData\x12(\n" +
|
||||
"\x10claim_public_key\x18\x01 \x01(\fR\x0eclaimPublicKey\"\xa9\x01\n" +
|
||||
"\fTemplateType\x12(\n" +
|
||||
"\x04wasm\x18\x01 \x01(\v2\x12.tari.rpc.WasmInfoH\x00R\x04wasm\x12(\n" +
|
||||
"\x04flow\x18\x02 \x01(\v2\x12.tari.rpc.FlowInfoH\x00R\x04flow\x124\n" +
|
||||
"\bmanifest\x18\x03 \x01(\v2\x16.tari.rpc.ManifestInfoH\x00R\bmanifestB\x0f\n" +
|
||||
"\rtemplate_type\"+\n" +
|
||||
"\bWasmInfo\x12\x1f\n" +
|
||||
"\vabi_version\x18\x01 \x01(\rR\n" +
|
||||
"abiVersion\"\n" +
|
||||
"\n" +
|
||||
"\bFlowInfo\"\x0e\n" +
|
||||
"\fManifestInfo\"G\n" +
|
||||
"\tBuildInfo\x12\x19\n" +
|
||||
"\brepo_url\x18\x01 \x01(\tR\arepoUrl\x12\x1f\n" +
|
||||
"\vcommit_hash\x18\x02 \x01(\fR\n" +
|
||||
"commitHashB8Z6pool/internal/gbt/tari/sidechain_types;sidechain_typesb\x06proto3"
|
||||
|
||||
var (
|
||||
file_sidechain_types_proto_rawDescOnce sync.Once
|
||||
file_sidechain_types_proto_rawDescData []byte
|
||||
)
|
||||
|
||||
func file_sidechain_types_proto_rawDescGZIP() []byte {
|
||||
file_sidechain_types_proto_rawDescOnce.Do(func() {
|
||||
file_sidechain_types_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_sidechain_types_proto_rawDesc), len(file_sidechain_types_proto_rawDesc)))
|
||||
})
|
||||
return file_sidechain_types_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_sidechain_types_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
|
||||
var file_sidechain_types_proto_goTypes = []any{
|
||||
(*SideChainFeature)(nil), // 0: tari.rpc.SideChainFeature
|
||||
(*ValidatorNodeRegistration)(nil), // 1: tari.rpc.ValidatorNodeRegistration
|
||||
(*TemplateRegistration)(nil), // 2: tari.rpc.TemplateRegistration
|
||||
(*ConfidentialOutputData)(nil), // 3: tari.rpc.ConfidentialOutputData
|
||||
(*TemplateType)(nil), // 4: tari.rpc.TemplateType
|
||||
(*WasmInfo)(nil), // 5: tari.rpc.WasmInfo
|
||||
(*FlowInfo)(nil), // 6: tari.rpc.FlowInfo
|
||||
(*ManifestInfo)(nil), // 7: tari.rpc.ManifestInfo
|
||||
(*BuildInfo)(nil), // 8: tari.rpc.BuildInfo
|
||||
(*types.Signature)(nil), // 9: tari.rpc.Signature
|
||||
}
|
||||
var file_sidechain_types_proto_depIdxs = []int32{
|
||||
1, // 0: tari.rpc.SideChainFeature.validator_node_registration:type_name -> tari.rpc.ValidatorNodeRegistration
|
||||
2, // 1: tari.rpc.SideChainFeature.template_registration:type_name -> tari.rpc.TemplateRegistration
|
||||
3, // 2: tari.rpc.SideChainFeature.confidential_output:type_name -> tari.rpc.ConfidentialOutputData
|
||||
9, // 3: tari.rpc.ValidatorNodeRegistration.signature:type_name -> tari.rpc.Signature
|
||||
9, // 4: tari.rpc.TemplateRegistration.author_signature:type_name -> tari.rpc.Signature
|
||||
4, // 5: tari.rpc.TemplateRegistration.template_type:type_name -> tari.rpc.TemplateType
|
||||
8, // 6: tari.rpc.TemplateRegistration.build_info:type_name -> tari.rpc.BuildInfo
|
||||
5, // 7: tari.rpc.TemplateType.wasm:type_name -> tari.rpc.WasmInfo
|
||||
6, // 8: tari.rpc.TemplateType.flow:type_name -> tari.rpc.FlowInfo
|
||||
7, // 9: tari.rpc.TemplateType.manifest:type_name -> tari.rpc.ManifestInfo
|
||||
10, // [10:10] is the sub-list for method output_type
|
||||
10, // [10:10] is the sub-list for method input_type
|
||||
10, // [10:10] is the sub-list for extension type_name
|
||||
10, // [10:10] is the sub-list for extension extendee
|
||||
0, // [0:10] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_sidechain_types_proto_init() }
|
||||
func file_sidechain_types_proto_init() {
|
||||
if File_sidechain_types_proto != nil {
|
||||
return
|
||||
}
|
||||
file_sidechain_types_proto_msgTypes[0].OneofWrappers = []any{
|
||||
(*SideChainFeature_ValidatorNodeRegistration)(nil),
|
||||
(*SideChainFeature_TemplateRegistration)(nil),
|
||||
(*SideChainFeature_ConfidentialOutput)(nil),
|
||||
}
|
||||
file_sidechain_types_proto_msgTypes[4].OneofWrappers = []any{
|
||||
(*TemplateType_Wasm)(nil),
|
||||
(*TemplateType_Flow)(nil),
|
||||
(*TemplateType_Manifest)(nil),
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_sidechain_types_proto_rawDesc), len(file_sidechain_types_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 9,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_sidechain_types_proto_goTypes,
|
||||
DependencyIndexes: file_sidechain_types_proto_depIdxs,
|
||||
MessageInfos: file_sidechain_types_proto_msgTypes,
|
||||
}.Build()
|
||||
File_sidechain_types_proto = out.File
|
||||
file_sidechain_types_proto_goTypes = nil
|
||||
file_sidechain_types_proto_depIdxs = nil
|
||||
}
|
|
@ -1,188 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
import "types.proto";
|
||||
import "sidechain_types.proto";
|
||||
|
||||
// The transaction kernel tracks the excess for a given transaction. For an explanation of what the excess is, and
|
||||
// why it is necessary, refer to the
|
||||
// [Mimblewimble TLU post](https://tlu.tarilabs.com/protocols/mimblewimble-1/sources/PITCHME.link.html?highlight=mimblewimble#mimblewimble).
|
||||
// The kernel also tracks other transaction metadata, such as the lock height for the transaction (i.e. the earliest
|
||||
// this transaction can be mined) and the transaction fee, in cleartext.
|
||||
message TransactionKernel {
|
||||
// Options for a kernel's structure or use
|
||||
uint32 features = 1;
|
||||
/// Fee originally included in the transaction this proof is for (in MicroMinotari)
|
||||
uint64 fee = 2;
|
||||
// This kernel is not valid earlier than lock_height blocks
|
||||
// The max lock_height of all *inputs* to this transaction
|
||||
uint64 lock_height = 3;
|
||||
// Remainder of the sum of all transaction commitments. If the transaction
|
||||
// is well formed, amounts components should sum to zero and the excess
|
||||
// is hence a valid public key.
|
||||
bytes excess = 6;
|
||||
// The signature proving the excess is a valid public key, which signs
|
||||
// the transaction fee.
|
||||
Signature excess_sig = 7;
|
||||
// The hash of the kernel, as it appears in the MMR
|
||||
bytes hash = 8;
|
||||
// Version
|
||||
uint32 version = 9;
|
||||
// Optional burned commitment
|
||||
bytes burn_commitment = 10;
|
||||
}
|
||||
|
||||
// A transaction input.
|
||||
//
|
||||
// Primarily a reference to an output being spent by the transaction.
|
||||
message TransactionInput {
|
||||
// The features of the output being spent. We will check maturity for all outputs.
|
||||
OutputFeatures features = 1;
|
||||
// The commitment referencing the output being spent.
|
||||
bytes commitment = 2;
|
||||
// Hash of the input, as it appears in the MMR
|
||||
bytes hash = 3;
|
||||
// The serialised script
|
||||
bytes script = 4;
|
||||
// The script input data, if any
|
||||
bytes input_data = 5;
|
||||
// A signature with k_s, signing the script, input data, and mined height
|
||||
ComAndPubSignature script_signature = 7;
|
||||
// The offset public key, K_O
|
||||
bytes sender_offset_public_key = 8;
|
||||
// The hash of the output this input is spending
|
||||
bytes output_hash = 9;
|
||||
// Covenant
|
||||
bytes covenant = 10;
|
||||
// Version
|
||||
uint32 version = 11;
|
||||
// The encrypted data
|
||||
bytes encrypted_data = 12;
|
||||
// The minimum value of the commitment that is proven by the range proof (in MicroMinotari)
|
||||
uint64 minimum_value_promise = 13;
|
||||
// The metadata signature for output this input is spending
|
||||
ComAndPubSignature metadata_signature = 14;
|
||||
// The rangeproof hash for output this input is spending
|
||||
bytes rangeproof_hash = 15;
|
||||
}
|
||||
|
||||
// Output for a transaction, defining the new ownership of coins that are being transferred. The commitment is a
|
||||
// blinded value for the output while the range proof guarantees the commitment includes a positive value without
|
||||
// overflow and the ownership of the private key.
|
||||
message TransactionOutput {
|
||||
// Options for an output's structure or use
|
||||
OutputFeatures features = 1;
|
||||
// The homomorphic commitment representing the output amount
|
||||
bytes commitment = 2;
|
||||
// A proof that the commitment is in the right range
|
||||
RangeProof range_proof = 3;
|
||||
// The hash of the output, as it appears in the MMR
|
||||
bytes hash = 4;
|
||||
// Tari script serialised script
|
||||
bytes script = 5;
|
||||
// Tari script offset public key, K_O
|
||||
bytes sender_offset_public_key = 6;
|
||||
// Metadata signature with the homomorphic commitment private values (amount and blinding factor) and the sender
|
||||
// offset private key
|
||||
ComAndPubSignature metadata_signature = 7;
|
||||
// Covenant
|
||||
bytes covenant = 8;
|
||||
// Version
|
||||
uint32 version = 9;
|
||||
// Encrypted Pedersen commitment openings (value and mask) for the output
|
||||
bytes encrypted_data = 10;
|
||||
// The minimum value of the commitment that is proven by the range proof (in MicroMinotari)
|
||||
uint64 minimum_value_promise = 11;
|
||||
// Payment reference (PayRef) - 32-byte Blake2b hash of (block_hash || output_hash)
|
||||
// This provides a unique, deterministic reference for the output that can be used
|
||||
// for payment verification without revealing wallet ownership
|
||||
bytes payment_reference = 12;
|
||||
}
|
||||
|
||||
// Options for UTXOs
|
||||
message OutputFeatures {
|
||||
// Version
|
||||
uint32 version = 1;
|
||||
// The type of output, eg Coinbase, all of which have different consensus rules
|
||||
uint32 output_type = 2;
|
||||
// The maturity of the specific UTXO. This is the min lock height at which an UTXO can be spend. Coinbase UTXO
|
||||
// require a min maturity of the Coinbase_lock_height, this should be checked on receiving new blocks.
|
||||
uint64 maturity = 3;
|
||||
// Additional arbitrary info in coinbase transactions supplied by miners
|
||||
bytes coinbase_extra = 4;
|
||||
// Features that are specific to a side chain
|
||||
SideChainFeature sidechain_feature = 5;
|
||||
// The type of range proof used in the output
|
||||
uint32 range_proof_type = 6;
|
||||
}
|
||||
|
||||
// The components of the block or transaction. The same struct can be used for either, since in Mimblewimble,
|
||||
// cut-through means that blocks and transactions have the same structure. The inputs, outputs and kernels should
|
||||
// be sorted by their Blake2b-256bit digest hash
|
||||
message AggregateBody {
|
||||
// List of inputs spent by the transaction.
|
||||
repeated TransactionInput inputs = 1;
|
||||
// List of outputs the transaction produces.
|
||||
repeated TransactionOutput outputs = 2;
|
||||
// Kernels contain the excesses and their signatures for transaction
|
||||
repeated TransactionKernel kernels = 3;
|
||||
}
|
||||
|
||||
// A transaction which consists of a kernel offset and an aggregate body made up of inputs, outputs and kernels.
|
||||
message Transaction {
|
||||
bytes offset = 1;
|
||||
AggregateBody body = 2;
|
||||
bytes script_offset = 3;
|
||||
}
|
||||
|
||||
message UnblindedOutput {
|
||||
// Value of the output
|
||||
uint64 value = 1;
|
||||
// Spending key of the output
|
||||
bytes spending_key = 2;
|
||||
// Options for an output's structure or use
|
||||
OutputFeatures features = 3;
|
||||
// Tari script serialised script
|
||||
bytes script = 4;
|
||||
// Tari script input data for spending
|
||||
bytes input_data = 5;
|
||||
// Tari script private key
|
||||
bytes script_private_key = 7;
|
||||
// Tari script offset pubkey, K_O
|
||||
bytes sender_offset_public_key = 8;
|
||||
// UTXO signature with the script offset private key, k_O
|
||||
ComAndPubSignature metadata_signature = 9;
|
||||
// The minimum height the script allows this output to be spent
|
||||
uint64 script_lock_height = 10;
|
||||
// Covenant
|
||||
bytes covenant = 11;
|
||||
// Encrypted data
|
||||
bytes encrypted_data = 12;
|
||||
// The minimum value of the commitment that is proven by the range proof (in MicroMinotari)
|
||||
uint64 minimum_value_promise = 13;
|
||||
// The range proof
|
||||
RangeProof range_proof = 14;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,147 +0,0 @@
|
|||
// Copyright 2020. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
/// An unsigned range interface to more accurately represent Rust native Range's
|
||||
message Range {
|
||||
uint64 min = 1;
|
||||
uint64 max = 2;
|
||||
}
|
||||
|
||||
/// An Empty placeholder for endpoints without request parameters
|
||||
message Empty {}
|
||||
|
||||
/// Define an interface for block height
|
||||
message BlockHeight {
|
||||
uint64 block_height = 1;
|
||||
}
|
||||
|
||||
// Define the explicit Signature implementation for the Minotari base layer. A different signature scheme can be
|
||||
// employed by redefining this type.
|
||||
message Signature {
|
||||
bytes public_nonce = 1;
|
||||
bytes signature = 2;
|
||||
}
|
||||
|
||||
// Define the explicit ComAndPubSignature implementation for the Minotari base layer. A different signature scheme can be
|
||||
// employed by redefining this type.
|
||||
message ComAndPubSignature {
|
||||
bytes ephemeral_commitment = 1;
|
||||
bytes ephemeral_pubkey = 2;
|
||||
bytes u_a = 3;
|
||||
bytes u_x = 4;
|
||||
bytes u_y = 5;
|
||||
}
|
||||
|
||||
// Define the explicit CommitmentSignature implementation for the Minotari base layer. A different signature scheme can be
|
||||
// employed by redefining this type
|
||||
message CommitmentSignature {
|
||||
bytes public_nonce = 1;
|
||||
bytes u = 2;
|
||||
bytes v = 3;
|
||||
}
|
||||
|
||||
/// PoW Algorithm constants
|
||||
message PowAlgorithmConstants {
|
||||
uint64 min_difficulty = 2;
|
||||
uint64 max_difficulty = 3;
|
||||
uint64 target_time = 4;
|
||||
}
|
||||
|
||||
/// Weight params
|
||||
message WeightParams {
|
||||
uint64 kernel_weight = 1;
|
||||
uint64 input_weight = 2;
|
||||
uint64 output_weight = 3;
|
||||
uint64 features_and_scripts_bytes_per_gram = 4;
|
||||
}
|
||||
|
||||
/// Output version
|
||||
message OutputsVersion {
|
||||
Range outputs = 1;
|
||||
Range features = 2;
|
||||
}
|
||||
|
||||
/// Output types
|
||||
enum OutputType {
|
||||
STANDARD = 0;
|
||||
COINBASE = 1;
|
||||
BURN = 2;
|
||||
VALIDATOR_NODE_REGISTRATION = 3;
|
||||
CODE_TEMPLATE_REGISTRATION = 4;
|
||||
}
|
||||
|
||||
/// Range proof types
|
||||
enum RangeProofType {
|
||||
BULLETPROOF_PLUS = 0;
|
||||
REVEALED_VALUE = 1;
|
||||
}
|
||||
|
||||
message PermittedRangeProofs {
|
||||
OutputType output_type = 1;
|
||||
repeated RangeProofType range_proof_types = 2;
|
||||
}
|
||||
|
||||
/// Range proof
|
||||
message RangeProof {
|
||||
bytes proof_bytes = 1;
|
||||
}
|
||||
|
||||
/// Consensus Constants response
|
||||
message ConsensusConstants {
|
||||
uint64 coinbase_min_maturity = 1;
|
||||
uint32 blockchain_version = 2;
|
||||
uint64 future_time_limit = 3;
|
||||
uint64 difficulty_block_window = 5;
|
||||
uint64 max_block_transaction_weight = 7;
|
||||
uint64 pow_algo_count = 8;
|
||||
uint64 median_timestamp_count = 9;
|
||||
uint64 emission_initial = 10;
|
||||
repeated uint64 emission_decay = 11;
|
||||
uint64 emission_tail = 12 [deprecated=true];
|
||||
uint64 min_sha3x_pow_difficulty = 13;
|
||||
uint64 block_weight_inputs = 14;
|
||||
uint64 block_weight_outputs = 15;
|
||||
uint64 block_weight_kernels = 16;
|
||||
uint64 pre_mine_value = 17;
|
||||
uint64 max_script_byte_size = 18;
|
||||
uint64 validator_node_validity_period = 19;
|
||||
uint64 effective_from_height = 20;
|
||||
Range valid_blockchain_version_range = 21;
|
||||
uint64 max_randomx_seed_height = 22;
|
||||
map<uint32, PowAlgorithmConstants> proof_of_work = 23;
|
||||
WeightParams transaction_weight = 24;
|
||||
Range input_version_range = 26;
|
||||
OutputsVersion output_version_range = 27;
|
||||
Range kernel_version_range = 28;
|
||||
repeated OutputType permitted_output_types = 29;
|
||||
uint64 epoch_length = 30;
|
||||
uint64 validator_node_registration_min_deposit_amount = 31;
|
||||
uint64 validator_node_registration_min_lock_height = 32;
|
||||
uint64 validator_node_registration_shuffle_interval_epoch = 33;
|
||||
repeated PermittedRangeProofs permitted_range_proof_types = 34;
|
||||
uint64 inflation_bips = 35;
|
||||
uint64 tail_epoch_length = 36;
|
||||
uint64 max_block_coinbase_count = 37;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,132 +0,0 @@
|
|||
// Copyright 2021. The Tari Project
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
|
||||
// following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
|
||||
// disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
|
||||
// following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
|
||||
// products derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
syntax = "proto3";
|
||||
|
||||
import "types.proto";
|
||||
import "network.proto";
|
||||
import "transaction.proto";
|
||||
|
||||
package tari.rpc;
|
||||
|
||||
service ValidatorNode {
|
||||
rpc GetIdentity(GetIdentityRequest) returns (GetIdentityResponse);
|
||||
rpc GetMetadata(GetMetadataRequest) returns (GetMetadataResponse);
|
||||
rpc GetTokenData(GetTokenDataRequest) returns (GetTokenDataResponse);
|
||||
// rpc ExecuteInstruction(ExecuteInstructionRequest) returns (ExecuteInstructionResponse);
|
||||
rpc InvokeReadMethod(InvokeReadMethodRequest) returns (InvokeReadMethodResponse);
|
||||
rpc InvokeMethod(InvokeMethodRequest) returns (InvokeMethodResponse);
|
||||
rpc GetConstitutionRequests(GetConstitutionRequestsRequest) returns (stream TransactionOutput);
|
||||
rpc PublishContractAcceptance(PublishContractAcceptanceRequest) returns (PublishContractAcceptanceResponse);
|
||||
rpc PublishContractUpdateProposalAcceptance(PublishContractUpdateProposalAcceptanceRequest) returns (PublishContractUpdateProposalAcceptanceResponse);
|
||||
}
|
||||
|
||||
message GetConstitutionRequestsRequest {
|
||||
// empty
|
||||
}
|
||||
|
||||
message GetMetadataRequest {
|
||||
// empty
|
||||
}
|
||||
|
||||
message PublishContractAcceptanceRequest {
|
||||
bytes contract_id = 1;
|
||||
}
|
||||
|
||||
message PublishContractAcceptanceResponse {
|
||||
string status = 1;
|
||||
uint64 tx_id = 2;
|
||||
}
|
||||
|
||||
message PublishContractUpdateProposalAcceptanceRequest {
|
||||
bytes contract_id = 1;
|
||||
uint64 proposal_id = 2;
|
||||
}
|
||||
|
||||
message PublishContractUpdateProposalAcceptanceResponse {
|
||||
string status = 1;
|
||||
uint64 tx_id = 2;
|
||||
}
|
||||
|
||||
message GetMetadataResponse {
|
||||
repeated SidechainMetadata sidechains = 1;
|
||||
}
|
||||
|
||||
message SidechainMetadata {
|
||||
bytes asset_public_key =1;
|
||||
uint64 committed_height = 2;
|
||||
bytes committed_hash = 3;
|
||||
}
|
||||
|
||||
message GetTokenDataRequest {
|
||||
bytes asset_pub_key = 1;
|
||||
bytes unique_id = 2;
|
||||
}
|
||||
|
||||
message GetTokenDataResponse {
|
||||
|
||||
}
|
||||
|
||||
//message ExecuteInstructionRequest{
|
||||
// bytes asset_public_key = 1;
|
||||
// uint32 template_id = 2;
|
||||
// string method = 3;
|
||||
// bytes args = 4;
|
||||
//// bytes token_id = 5;
|
||||
//// bytes signature = 6;
|
||||
//}
|
||||
//
|
||||
//message ExecuteInstructionResponse {
|
||||
// string status = 1;
|
||||
// optional bytes result = 2;
|
||||
//}
|
||||
|
||||
message InvokeReadMethodRequest{
|
||||
bytes contract_id = 1;
|
||||
uint32 template_id = 2;
|
||||
string method = 3;
|
||||
bytes args = 4;
|
||||
bytes sender = 5;
|
||||
}
|
||||
|
||||
message InvokeReadMethodResponse {
|
||||
bytes result = 1;
|
||||
Authority authority = 2;
|
||||
}
|
||||
|
||||
message Authority {
|
||||
bytes node_public_key =1;
|
||||
bytes signature = 2;
|
||||
bytes proxied_by = 3;
|
||||
}
|
||||
|
||||
message InvokeMethodRequest {
|
||||
bytes contract_id = 1;
|
||||
uint32 template_id = 2;
|
||||
string method = 3;
|
||||
bytes args = 4;
|
||||
bytes sender = 5;
|
||||
}
|
||||
|
||||
message InvokeMethodResponse {
|
||||
string status = 1;
|
||||
bytes result = 2;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,385 +0,0 @@
|
|||
package sha3x
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"database/sql"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"pool/internal/db"
|
||||
"pool/internal/gbt/coin"
|
||||
"pool/internal/gbt/dbif"
|
||||
"pool/internal/gbt/tari"
|
||||
"pool/internal/msg"
|
||||
"pool/internal/utility"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
const GBT_SHA3X_VERSION string = "sha3x v1.0"
|
||||
|
||||
type Sha3xAddrConfig struct {
|
||||
Addr string `json:"addr"`
|
||||
}
|
||||
|
||||
type Sha3xConfig struct {
|
||||
Monero Sha3xAddrConfig `json:"sha3x"`
|
||||
}
|
||||
|
||||
type GbtSha3xContext struct {
|
||||
Config Sha3xConfig
|
||||
GbtCtx *coin.GbtContext
|
||||
Ctx context.Context
|
||||
last_time time.Time
|
||||
last_gbt tari.TariBlockTemplate
|
||||
last_blockhash string
|
||||
|
||||
last_height uint64
|
||||
|
||||
Submits float64
|
||||
|
||||
addressIndex int
|
||||
|
||||
Target []byte
|
||||
Header []byte
|
||||
last_body string
|
||||
|
||||
Jobs sync.Map
|
||||
JobIds []string
|
||||
JobGenCount int
|
||||
new_block_chan chan int
|
||||
new_block_index int
|
||||
}
|
||||
|
||||
var logg *zap.Logger
|
||||
var GbtSha3xCtx GbtSha3xContext
|
||||
|
||||
func configInit(config *Sha3xConfig) {
|
||||
data, err := ioutil.ReadFile("gbt.conf")
|
||||
if err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
if err = json.Unmarshal(data, &config); err != nil {
|
||||
panic(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func Init(GbtCtx *coin.GbtContext, DbCtx *db.DbContext) {
|
||||
GbtSha3xCtx.GbtCtx = GbtCtx
|
||||
|
||||
GbtSha3xCtx.last_height = 0
|
||||
|
||||
configInit(&GbtSha3xCtx.Config)
|
||||
GbtSha3xCtx.JobGenCount = 0
|
||||
GbtSha3xCtx.Target = make([]byte, 32)
|
||||
GbtSha3xCtx.Header = make([]byte, 49)
|
||||
GbtSha3xCtx.last_time = time.Now()
|
||||
GbtSha3xCtx.Ctx = context.Background()
|
||||
logg = GbtCtx.Log
|
||||
GbtSha3xCtx.new_block_chan = make(chan int, 256)
|
||||
GbtSha3xCtx.new_block_index = 0
|
||||
logg.Info("[gbt]", zap.String("gbt_sha3x_version", GBT_SHA3X_VERSION))
|
||||
|
||||
}
|
||||
|
||||
func Start() {
|
||||
go gbt_running(&GbtSha3xCtx)
|
||||
go gbt_notify_running(&GbtSha3xCtx)
|
||||
go submit_block_running(&GbtSha3xCtx)
|
||||
}
|
||||
|
||||
func Stop() {
|
||||
defer close(GbtSha3xCtx.new_block_chan)
|
||||
}
|
||||
|
||||
func update_block_confirm(gbt *GbtSha3xContext) {
|
||||
|
||||
}
|
||||
|
||||
func randomxJobId() string {
|
||||
// 生成4个字节
|
||||
bytes := make([]byte, 4)
|
||||
_, err := rand.Read(bytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 转成 hex 字符串
|
||||
hexStr := hex.EncodeToString(bytes)
|
||||
return hexStr
|
||||
}
|
||||
|
||||
func removeJobs(gbt *GbtSha3xContext, clean bool) {
|
||||
if !clean {
|
||||
if len(gbt.JobIds) > 10 {
|
||||
end := len(gbt.JobIds) - 10
|
||||
for i := 0; i < end; i++ {
|
||||
gbt.Jobs.Delete(gbt.JobIds[i])
|
||||
}
|
||||
gbt.JobIds = gbt.JobIds[end:]
|
||||
}
|
||||
} else {
|
||||
gbt.Jobs.Range(func(key, value interface{}) bool {
|
||||
gbt.Jobs.Delete(key)
|
||||
return true
|
||||
})
|
||||
gbt.JobIds = nil
|
||||
gbt.JobGenCount = 0
|
||||
}
|
||||
}
|
||||
|
||||
func gbt_running(gbt *GbtSha3xContext) {
|
||||
ticker := time.NewTicker(1000 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
|
||||
for gbt.GbtCtx.Started {
|
||||
select {
|
||||
case <-ticker.C:
|
||||
// 获取区块模板
|
||||
blockTemplate, err := gbt.GbtCtx.TariClient.GetBlockTemplate(gbt.Ctx, 1)
|
||||
if err != nil || len(blockTemplate.Header) != 638 {
|
||||
fmt.Println("任务模板中的区块头长度:", len(blockTemplate.Header))
|
||||
return
|
||||
}
|
||||
|
||||
// 初始化 ZMQ 发布通道
|
||||
if gbt.GbtCtx.PubCh == nil {
|
||||
gbt.GbtCtx.PubCh = utility.InitZmqPub(gbt.GbtCtx.Config.Zmq.Pub)
|
||||
continue
|
||||
}
|
||||
|
||||
height := blockTemplate.Height
|
||||
|
||||
if height == gbt.last_height {
|
||||
removeJobs(gbt, false)
|
||||
if gbt.JobGenCount >= 10 {
|
||||
generateJob(gbt, &blockTemplate)
|
||||
gbt.JobGenCount = 0 // 成功生成 Job 后重置计数器
|
||||
}
|
||||
} else {
|
||||
removeJobs(gbt, true)
|
||||
generateJob(gbt, &blockTemplate)
|
||||
gbt.last_height = height
|
||||
gbt.JobGenCount = 0 // 高度变化也重置计数器
|
||||
}
|
||||
// 标记存活
|
||||
atomic.StoreInt32(&(gbt.GbtCtx.FlagAliving), 1)
|
||||
// 无论是否需要发布新任务,计数均+1,保持至少10秒更新一次任务
|
||||
gbt.JobGenCount += 1
|
||||
case blkIdx := <-gbt.new_block_chan:
|
||||
log.Println("new block chan", blkIdx)
|
||||
update_block_confirm(gbt)
|
||||
|
||||
case <-gbt.GbtCtx.ExitGbtChan:
|
||||
logg.Error("[gbt]", zap.String("gbt", "exit"))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateJob(gbt *GbtSha3xContext, blockTemplate *tari.TariBlockTemplate) {
|
||||
for trycnt := 0; trycnt < 3; trycnt++ {
|
||||
job := msg.Sha3xJob{
|
||||
JobId: randomxJobId(),
|
||||
MiningHash: blockTemplate.MiningHash,
|
||||
Header: blockTemplate.Header,
|
||||
Body: blockTemplate.Body,
|
||||
TargetDifficulty: blockTemplate.TargetDifficulty,
|
||||
Height: blockTemplate.Height,
|
||||
}
|
||||
|
||||
sendMsg := msg.Sha3xStratumJob{
|
||||
JobId: job.JobId,
|
||||
Header: job.MiningHash,
|
||||
U64target: job.TargetDifficulty,
|
||||
Height: uint32(job.Height),
|
||||
}
|
||||
|
||||
bt, err := json.Marshal(sendMsg)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 保存 Job
|
||||
gbt.Jobs.LoadOrStore(job.JobId, job)
|
||||
gbt.JobIds = append(gbt.JobIds, job.JobId)
|
||||
|
||||
// 发布 Job
|
||||
if err := gbt.GbtCtx.PubCh.SendMessage([][]byte{[]byte("jobsha3x"), bt}); err != nil {
|
||||
logg.Warn("[gbt]", zap.String("job", err.Error()))
|
||||
continue
|
||||
}
|
||||
|
||||
logg.Warn("[gbt]", zap.String("job", "sent"))
|
||||
gbt.JobGenCount++
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
func gbt_notify_running(gbt *GbtSha3xContext) {
|
||||
for {
|
||||
|
||||
if !gbt.GbtCtx.Started {
|
||||
break
|
||||
}
|
||||
if gbt.GbtCtx.MoneroNewBlockSubCh == nil {
|
||||
gbt.GbtCtx.MoneroNewBlockSubCh = utility.InitZmqSub(gbt.GbtCtx.Config.Rpc.ZmqSub, utility.BITCOIND_ZMQ_HASHBLOCK)
|
||||
}
|
||||
if gbt.GbtCtx.MoneroNewBlockSubCh != nil {
|
||||
cmsg_sub, err := gbt.GbtCtx.MoneroNewBlockSubCh.RecvMessage()
|
||||
if err != nil {
|
||||
if !gbt.GbtCtx.Started {
|
||||
break
|
||||
}
|
||||
gbt.GbtCtx.MoneroNewBlockSubCh.SetSubscribe(utility.BITCOIND_ZMQ_HASHBLOCK)
|
||||
gbt.GbtCtx.MoneroNewBlockSubCh.Connect(gbt.GbtCtx.Config.Rpc.ZmqSub)
|
||||
continue
|
||||
}
|
||||
if len(cmsg_sub) >= 2 {
|
||||
if string(cmsg_sub[0]) == "hashblock" {
|
||||
GbtSha3xCtx.new_block_index = GbtSha3xCtx.new_block_index + 1
|
||||
//log.Println("gbt_notify_running", hex.EncodeToString(cmsg_sub[1]), GbtNexaCtx.new_block_index)
|
||||
gbt.new_block_chan <- GbtSha3xCtx.new_block_index
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logg.Error("[gbt]", zap.String("notify", "NodeSubCh fail!"))
|
||||
time.Sleep(time.Duration(1) * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ServerSubmitBlock struct {
|
||||
JobId string
|
||||
Header []byte
|
||||
Body []byte
|
||||
Nonce string
|
||||
}
|
||||
|
||||
func submit_block_running(block *GbtSha3xContext) {
|
||||
logg.Info("[block]", zap.String("submit_block_running", "Start."))
|
||||
for {
|
||||
if !block.GbtCtx.Started {
|
||||
break
|
||||
}
|
||||
if block.GbtCtx.SubCh == nil {
|
||||
block.GbtCtx.SubCh = utility.InitZmqSub(block.GbtCtx.Config.Zmq.Sub, "blk"+block.GbtCtx.Coin)
|
||||
}
|
||||
if block.GbtCtx.SubCh != nil {
|
||||
cmsg_sub, err := block.GbtCtx.SubCh.RecvMessage()
|
||||
if err != nil {
|
||||
if !block.GbtCtx.Started {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Duration(1) * time.Second)
|
||||
block.GbtCtx.SubCh.SetSubscribe("blk" + block.GbtCtx.Coin)
|
||||
block.GbtCtx.SubCh.Connect(block.GbtCtx.Config.Zmq.Sub)
|
||||
continue
|
||||
}
|
||||
if len(cmsg_sub) >= 2 {
|
||||
if string(cmsg_sub[0]) == "blksha3x" {
|
||||
cmsg := cmsg_sub[1]
|
||||
//block data
|
||||
msgb := make([]byte, len(cmsg)-16)
|
||||
copy(msgb, cmsg)
|
||||
var submitMsg msg.BlockSha3xMsg
|
||||
if err := json.Unmarshal(msgb, &submitMsg); err != nil {
|
||||
//block.Consumer.MarkOffset(cmsg, "")
|
||||
logg.Error("[block]", zap.String("failed to Unmarshal job", err.Error()))
|
||||
continue
|
||||
}
|
||||
|
||||
var height = submitMsg.Height
|
||||
logg.Warn("[block]", zap.Uint64("height", height))
|
||||
|
||||
if height <= block.last_height {
|
||||
continue
|
||||
}
|
||||
block.last_height = height
|
||||
|
||||
indexb, err1 := hex.DecodeString(string(cmsg[len(msgb)+8:]))
|
||||
if err1 != nil {
|
||||
logg.Error("[block]", zap.String("failed to decode index", err1.Error()))
|
||||
continue
|
||||
}
|
||||
var index uint32 = utility.ByteToUint32(indexb)
|
||||
logg.Warn("[block]", zap.Uint32("index", index))
|
||||
logg.Debug("[block]", zap.String("msg", string(cmsg)), zap.String("blk", string(msgb)))
|
||||
if v, ok := block.Jobs.Load(submitMsg.Id); ok {
|
||||
job := v.(*msg.Sha3xJob) // 类型断言
|
||||
headerStr, bodyStr := job.Header, job.Body
|
||||
header, err := hex.DecodeString(headerStr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
body, err := hex.DecodeString(bodyStr)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
nonceByte := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(nonceByte, submitMsg.Nonce)
|
||||
copy(header[311:319], nonceByte)
|
||||
blockHash_byte, _ := block.GbtCtx.TariClient.SubmitBlock(block.Ctx, header, body)
|
||||
nonceStr := fmt.Sprintf("%x", submitMsg.Nonce)
|
||||
blockHash := hex.EncodeToString(blockHash_byte)
|
||||
dbif.NotifyPoolBlkStatsSubmitResult(block.GbtCtx, int64(height), blockHash, "OK", nonceStr, submitMsg.SubIdx)
|
||||
block.Submits += 1
|
||||
logg.Warn("[block]", zap.Float64("total submits", block.Submits), zap.Int64("SubIdx", submitMsg.SubIdx))
|
||||
new_block_into_db(block, submitMsg.User, submitMsg.Miner, submitMsg.Index, int64(height), nonceStr, blockHash, submitMsg.SubIdx)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logg.Error("[block]", zap.String("block", "SubCh failed! retry"))
|
||||
time.Sleep(time.Duration(1) * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func new_block_into_db(block *GbtSha3xContext, user string, miner string, minerid string, height int64, nonce string, hash string, subidx int64) bool {
|
||||
db, err := sql.Open("sqlite3", "./blocks.db")
|
||||
if err != nil {
|
||||
log.Printf("Error opening database: %v", err)
|
||||
return false
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
createTableSQL := `
|
||||
CREATE TABLE IF NOT EXISTS blocks (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
user TEXT NOT NULL,
|
||||
miner TEXT NOT NULL,
|
||||
minerid TEXT NOT NULL,
|
||||
height INTEGER,
|
||||
nonce TEXT NOT NULL,
|
||||
hash TEXT NOT NULL,
|
||||
subidx INTEGER,
|
||||
checked INTEGER,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||
);`
|
||||
_, err = db.Exec(createTableSQL)
|
||||
if err != nil {
|
||||
log.Printf("Error creating table: %v", err)
|
||||
return false
|
||||
}
|
||||
|
||||
insertSQL := `INSERT INTO blocks (user, miner, minerid, height, nonce, checked, hash, subidx) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`
|
||||
_, err = db.Exec(insertSQL, user, miner, minerid, height, nonce, 0, hash, subidx)
|
||||
if err != nil {
|
||||
log.Printf("Error inserting data from blocks %s: %v", fmt.Sprint(height), err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
package tari
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
base_node "pool/internal/gbt/tari/proto"
|
||||
block "pool/internal/gbt/tari/proto/block"
|
||||
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
// var PowAlgoMap = []string{"randomxM", "sha3x", "randomxT"}
|
||||
|
||||
type BaseNodeClient struct {
|
||||
Conn *grpc.ClientConn
|
||||
Client base_node.BaseNodeClient
|
||||
}
|
||||
|
||||
// 创建BaseNode客户端
|
||||
func NewBaseNodeClient(address string) (*BaseNodeClient, error) {
|
||||
conn, err := grpc.Dial(address, grpc.WithInsecure())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to connect to base node: %v", err)
|
||||
}
|
||||
// 移除 defer conn.Close(),让连接保持打开状态
|
||||
|
||||
client := base_node.NewBaseNodeClient(conn)
|
||||
|
||||
return &BaseNodeClient{
|
||||
Conn: conn,
|
||||
Client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close 关闭GRPC连接
|
||||
func (c *BaseNodeClient) Close() error {
|
||||
if c.Conn != nil {
|
||||
return c.Conn.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type TariBlockTemplate struct {
|
||||
MiningHash string
|
||||
Header string
|
||||
Body string
|
||||
Height uint64
|
||||
TargetDifficulty uint64
|
||||
}
|
||||
|
||||
func base64ToHex(data string) (string, error) {
|
||||
result, err := base64.StdEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(result), nil
|
||||
}
|
||||
|
||||
func (nc *BaseNodeClient) GetBlockTemplate(ctx context.Context, powIndex uint32) (TariBlockTemplate, error) {
|
||||
var pow_algo block.PowAlgo_PowAlgos
|
||||
switch powIndex {
|
||||
case 0:
|
||||
pow_algo = block.PowAlgo_POW_ALGOS_RANDOMXM
|
||||
case 1:
|
||||
pow_algo = block.PowAlgo_POW_ALGOS_SHA3X
|
||||
case 2:
|
||||
pow_algo = block.PowAlgo_POW_ALGOS_RANDOMXT
|
||||
default:
|
||||
fmt.Println("不支持", powIndex, "算法")
|
||||
}
|
||||
templateReq := &base_node.NewBlockTemplateRequest{
|
||||
Algo: &block.PowAlgo{
|
||||
PowAlgo: pow_algo,
|
||||
},
|
||||
MaxWeight: 0x00,
|
||||
}
|
||||
templateResp, err := nc.Client.GetNewBlockTemplate(ctx, templateReq)
|
||||
if err != nil {
|
||||
fmt.Println(pow_algo, "获取区块模板失败:", err)
|
||||
return TariBlockTemplate{}, err
|
||||
}
|
||||
// 节点未同步完成
|
||||
if !templateResp.InitialSyncAchieved {
|
||||
fmt.Println("节点还未完成同步")
|
||||
return TariBlockTemplate{}, err
|
||||
}
|
||||
blk_template, miner_data := templateResp.NewBlockTemplate, templateResp.MinerData
|
||||
targetDifficulty := miner_data.TargetDifficulty
|
||||
height := blk_template.Header.Height
|
||||
blockBlob, err := nc.Client.GetNewBlockBlob(ctx, blk_template)
|
||||
if err != nil {
|
||||
fmt.Println("获得block blob失败:", err)
|
||||
return TariBlockTemplate{}, err
|
||||
}
|
||||
mining_hash, header, body := blockBlob.BlockHash, blockBlob.Header, blockBlob.BlockBody
|
||||
var t_bt = TariBlockTemplate{
|
||||
MiningHash: hex.EncodeToString(mining_hash),
|
||||
Header: hex.EncodeToString(header),
|
||||
Body: hex.EncodeToString(body),
|
||||
TargetDifficulty: targetDifficulty,
|
||||
Height: height,
|
||||
}
|
||||
return t_bt, nil
|
||||
}
|
||||
|
||||
func (nc *BaseNodeClient) SubmitBlock(ctx context.Context, header, body []byte) ([]byte, error) {
|
||||
submitReq := &base_node.BlockBlobRequest{
|
||||
HeaderBlob: header,
|
||||
BodyBlob: body,
|
||||
}
|
||||
submitResp, err := nc.Client.SubmitBlockBlob(ctx, submitReq)
|
||||
if err != nil {
|
||||
fmt.Println("提交区块失败:", err)
|
||||
return nil, err
|
||||
}
|
||||
blockHash := submitResp.BlockHash
|
||||
return blockHash, nil
|
||||
}
|
|
@ -64,7 +64,6 @@ type Sha3xStratumJob struct {
|
|||
Header string `json:"header, omitempty"`
|
||||
NBits string `json:"nBits, omitempty"`
|
||||
Id uint64 `json:"id, omitempty"`
|
||||
JobId string `json:"job_id", omitempty`
|
||||
CurTime uint64 `json:"timestamp, omitempty"`
|
||||
Target string `json:"target, omitempty"`
|
||||
Height uint32 `json:"height, omitempty"`
|
||||
|
@ -89,29 +88,6 @@ type BlockSha3xMsg struct {
|
|||
SubmitIdx uint64 `json:"submitidx"`
|
||||
}
|
||||
|
||||
type Sha3xJob struct {
|
||||
JobId string
|
||||
MiningHash string
|
||||
Height uint64
|
||||
Header string
|
||||
Body string
|
||||
TargetDifficulty uint64
|
||||
}
|
||||
|
||||
type GbtSendMsg struct {
|
||||
Id uint64
|
||||
JobId string
|
||||
MiningHash string
|
||||
Header string
|
||||
TargetDifficulty uint64
|
||||
Height uint64
|
||||
Target string
|
||||
Nonce string
|
||||
Extranonce1 string `json:"extranonce1, omitempty"`
|
||||
Extranonce2_size uint64 `json:"extranonce2_size, omitempty"`
|
||||
Extranonce2 string `json:"extranonce2, omitempty"`
|
||||
}
|
||||
|
||||
type MonoreBlockTemplate struct {
|
||||
BlockhashingBlob string `json:"blockhashing_blob"`
|
||||
BlocktemplateBlob string `json:"blocktemplate_blob"`
|
||||
|
|
Loading…
Reference in New Issue