From 8cc56a489ea70ce3f2b9c02f91d96ee378bab86d Mon Sep 17 00:00:00 2001 From: lzx <393768033@qq.com> Date: Thu, 4 Sep 2025 16:09:36 +0800 Subject: [PATCH] add tari-gbt(rust) --- README.md | 2 +- go.mod | 3 +- internal/gbt/gbt.go | 16 +- internal/gbt/tari/config.toml | 1267 +++++ internal/gbt/tari/miner/log4rs.yml | 62 + internal/gbt/tari/minotari_miner/Cargo.toml | 68 + internal/gbt/tari/minotari_miner/README.md | 39 + internal/gbt/tari/minotari_miner/build.rs | 33 + internal/gbt/tari/minotari_miner/icon.ico | Bin 0 -> 285478 bytes internal/gbt/tari/minotari_miner/icon.rc | 1 + internal/gbt/tari/minotari_miner/icon.res | Bin 0 -> 285684 bytes .../linux/runtime/start_minotari_miner.sh | 53 + .../minotari_miner/linux/start_minotari_miner | 1 + .../gbt/tari/minotari_miner/log4rs_sample.yml | 62 + .../osx/runtime/start_minotari_miner.sh | 63 + .../minotari_miner/osx/start_minotari_miner | 1 + internal/gbt/tari/minotari_miner/src/cli.rs | 70 + .../gbt/tari/minotari_miner/src/config.rs | 184 + .../gbt/tari/minotari_miner/src/difficulty.rs | 163 + .../gbt/tari/minotari_miner/src/errors.rs | 72 + internal/gbt/tari/minotari_miner/src/lib.rs | 39 + internal/gbt/tari/minotari_miner/src/main.rs | 76 + internal/gbt/tari/minotari_miner/src/miner.rs | 505 ++ .../gbt/tari/minotari_miner/src/run_miner.rs | 735 +++ .../minotari_miner/src/stratum/controller.rs | 419 ++ .../tari/minotari_miner/src/stratum/error.rs | 76 + .../tari/minotari_miner/src/stratum/mod.rs | 26 + .../stratum/stratum_controller/controller.rs | 221 + .../src/stratum/stratum_controller/mod.rs | 22 + .../stratum/stratum_types/client_message.rs | 30 + .../src/stratum/stratum_types/job.rs | 31 + .../src/stratum/stratum_types/job_params.rs | 30 + .../src/stratum/stratum_types/login_params.rs | 34 + .../stratum/stratum_types/login_response.rs | 30 + .../stratum/stratum_types/miner_message.rs | 31 + .../src/stratum/stratum_types/mod.rs | 33 + .../src/stratum/stratum_types/rpc_error.rs | 28 + .../src/stratum/stratum_types/rpc_request.rs | 31 + .../src/stratum/stratum_types/rpc_response.rs | 32 + .../stratum/stratum_types/submit_params.rs | 30 + .../stratum/stratum_types/submit_response.rs | 30 + .../stratum_types/worker_identifier.rs | 27 + .../tari/minotari_miner/src/stratum/stream.rs | 107 + .../windows/runtime/source_miner_env.bat | 56 + .../windows/runtime/start_minotari_miner.bat | 28 + .../windows/start_minotari_miner.lnk | Bin 0 -> 2426 bytes internal/gbt/tari/proto/base_node.pb.go | 4609 ----------------- internal/gbt/tari/proto/base_node.proto | 600 --- internal/gbt/tari/proto/base_node_grpc.pb.go | 1666 ------ internal/gbt/tari/proto/block.proto | 142 - internal/gbt/tari/proto/block/block.pb.go | 783 --- .../gbt/tari/proto/net_work/network.pb.go | 790 --- internal/gbt/tari/proto/network.proto | 97 - internal/gbt/tari/proto/p2pool.proto | 61 - internal/gbt/tari/proto/sidechain_types.proto | 77 - .../sidechain_types/sidechain_types.pb.go | 727 --- internal/gbt/tari/proto/transaction.proto | 188 - .../tari/proto/transaction/transaction.pb.go | 1012 ---- internal/gbt/tari/proto/types.proto | 147 - internal/gbt/tari/proto/types/types.pb.go | 1239 ----- internal/gbt/tari/proto/validator_node.proto | 132 - internal/gbt/tari/proto/wallet.proto | 1582 ------ internal/gbt/tari/sha3x/sha3x.go | 385 -- internal/gbt/tari/tari.go | 120 - internal/msg/msg.go | 24 - 65 files changed, 4851 insertions(+), 14397 deletions(-) create mode 100644 internal/gbt/tari/config.toml create mode 100644 internal/gbt/tari/miner/log4rs.yml create mode 100644 internal/gbt/tari/minotari_miner/Cargo.toml create mode 100644 internal/gbt/tari/minotari_miner/README.md create mode 100644 internal/gbt/tari/minotari_miner/build.rs create mode 100644 internal/gbt/tari/minotari_miner/icon.ico create mode 100644 internal/gbt/tari/minotari_miner/icon.rc create mode 100644 internal/gbt/tari/minotari_miner/icon.res create mode 100644 internal/gbt/tari/minotari_miner/linux/runtime/start_minotari_miner.sh create mode 100644 internal/gbt/tari/minotari_miner/linux/start_minotari_miner create mode 100644 internal/gbt/tari/minotari_miner/log4rs_sample.yml create mode 100644 internal/gbt/tari/minotari_miner/osx/runtime/start_minotari_miner.sh create mode 100644 internal/gbt/tari/minotari_miner/osx/start_minotari_miner create mode 100644 internal/gbt/tari/minotari_miner/src/cli.rs create mode 100644 internal/gbt/tari/minotari_miner/src/config.rs create mode 100644 internal/gbt/tari/minotari_miner/src/difficulty.rs create mode 100644 internal/gbt/tari/minotari_miner/src/errors.rs create mode 100644 internal/gbt/tari/minotari_miner/src/lib.rs create mode 100644 internal/gbt/tari/minotari_miner/src/main.rs create mode 100644 internal/gbt/tari/minotari_miner/src/miner.rs create mode 100644 internal/gbt/tari/minotari_miner/src/run_miner.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/controller.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/error.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/mod.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/controller.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/mod.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/client_message.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job_params.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_params.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_response.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/miner_message.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/mod.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_error.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_request.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_response.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_params.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_response.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stratum_types/worker_identifier.rs create mode 100644 internal/gbt/tari/minotari_miner/src/stratum/stream.rs create mode 100644 internal/gbt/tari/minotari_miner/windows/runtime/source_miner_env.bat create mode 100644 internal/gbt/tari/minotari_miner/windows/runtime/start_minotari_miner.bat create mode 100644 internal/gbt/tari/minotari_miner/windows/start_minotari_miner.lnk delete mode 100644 internal/gbt/tari/proto/base_node.pb.go delete mode 100644 internal/gbt/tari/proto/base_node.proto delete mode 100644 internal/gbt/tari/proto/base_node_grpc.pb.go delete mode 100644 internal/gbt/tari/proto/block.proto delete mode 100644 internal/gbt/tari/proto/block/block.pb.go delete mode 100644 internal/gbt/tari/proto/net_work/network.pb.go delete mode 100644 internal/gbt/tari/proto/network.proto delete mode 100644 internal/gbt/tari/proto/p2pool.proto delete mode 100644 internal/gbt/tari/proto/sidechain_types.proto delete mode 100644 internal/gbt/tari/proto/sidechain_types/sidechain_types.pb.go delete mode 100644 internal/gbt/tari/proto/transaction.proto delete mode 100644 internal/gbt/tari/proto/transaction/transaction.pb.go delete mode 100644 internal/gbt/tari/proto/types.proto delete mode 100644 internal/gbt/tari/proto/types/types.pb.go delete mode 100644 internal/gbt/tari/proto/validator_node.proto delete mode 100644 internal/gbt/tari/proto/wallet.proto delete mode 100644 internal/gbt/tari/sha3x/sha3x.go delete mode 100644 internal/gbt/tari/tari.go diff --git a/README.md b/README.md index 6b1e8f4..ec830b8 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# tari-server +# m2pool-mining-core 一个基于 Go 的轻量化挖矿池服务内核,包含 Job 生成/分发与 Stratum 矿工端接入两大模块: - gbt:区块模板生成与同步(GetBlockTemplate/Job Producer),通过 ZMQ 向服务端发布新任务 diff --git a/go.mod b/go.mod index df01694..6700d36 100644 --- a/go.mod +++ b/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 ( diff --git a/internal/gbt/gbt.go b/internal/gbt/gbt.go index 2932e69..df83218 100644 --- a/internal/gbt/gbt.go +++ b/internal/gbt/gbt.go @@ -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) { diff --git a/internal/gbt/tari/config.toml b/internal/gbt/tari/config.toml new file mode 100644 index 0000000..043f8f7 --- /dev/null +++ b/internal/gbt/tari/config.toml @@ -0,0 +1,1267 @@ + +######################################################################################################################## +# # +# Common Configuration Options (CommonConfig, AutoUpdateConfig, MetricsConfig) # +# # +######################################################################################################################## + +[common] +#override_from="stagenet" +#base_path="/.tari" + +[stagenet.auto_update] +# Customize the hosts that are used to check for updates. These hosts must contain update information in DNS TXT records. +update_uris = ["updates.stagenet.taripulse.com"] + +[auto_update] +# Name server for auto update (default = "1.1.1.1:53/cloudflare.net") +#name_server = "1.1.1.1:53/cloudflare.net" + +# Customize the hosts that are used to check for updates. These hosts must contain update information in DNS TXT +# records. (default = []) +#update_uris = [] + +#use_dnssec = false + +#download_base_url = "" + +# Customize the location of the update SHA hashes and maintainer-signed signature. +#hashes_url = "https://
/hashes.txt" +#hashes_sig_url = "https://
/hashes.txt.sig" + +# This interval in seconds to check for software updates. Setting this to 0 disables checking. +check_interval = 300 + +[metrics] +# server_bind_address = "127.0.0.1:5577" +# push_endpoint = http://localhost:9091/metrics/job/base-node + + +######################################################################################################################## +# # +# Peer Seeds Configuration Options (PeerSeedsConfig) # +# # +######################################################################################################################## + +[p2p.seeds] +# DNS name servers to use for DNS seeds, in order of preference. +# (default: dns_seed_name_servers = [ +# "system", +# "1.1.1.1:853/cloudflare-dns.com", +# "8.8.8.8:853/dns.google", +# "9.9.9.9:853/dns.quad9.net" +#] +#dns_seed_name_servers = [ +# "system", +# "1.1.1.1:853/cloudflare-dns.com", +# "8.8.8.8:853/dns.google", +# "9.9.9.9:853/dns.quad9.net" +#] + +# All DNS seed records must pass DNSSEC validation (default: dns_seeds_use_dnssec = false) +#dns_seeds_use_dnssec = false + +[nextnet.p2p.seeds] +# DNS seeds hosts - DNS TXT records are queried from these hosts and the resulting peers added to the comms peer list. +# (Default: peer_seeds = []) +dns_seeds = ["seeds.nextnet.tari.com"] +peer_seeds = [ + "18a07e52ef6616d74a31b4c26d34fb7debdbe6d8b0261f6fff67e5801da8ee5d::/onion3/6huatttx2xvnhg7pui22rqweegmyjp7mr6wkppqjwrcqgzqqnv2okfad:18141", + "928b89d44afcebd5ae305113409f0d0c6237278a6451e19e270245358d945b1e::/ip6/2001:41d0:701:1000::4716/tcp/18189", + "0c42312a2bdd7d17b12047b515d36c982e56573cc5e9d6d19cf29210624ec02b::/ip4/148.113.143.145/tcp/18189", + "0c42312a2bdd7d17b12047b515d36c982e56573cc5e9d6d19cf29210624ec02b::/onion3/on77pvjtgvpsyrfzzmusvtdknuy6l44av5ifxaeo2hvaarcanccta4qd:18141", + "0e99cc89439546d3a59d02fb498d6e1bd7dbeee17c2cecea1966244b8f83b77d::/onion3/kjwvw4tg4pvgqrzaks7atnf7kjesteoxt5wpjd4b6lusezkqxgiktoqd:18141", + "928b89d44afcebd5ae305113409f0d0c6237278a6451e19e270245358d945b1e::/ip4/51.75.94.140/tcp/18189", + "463cb7d9238a30901b88370dac817da738a722f5fb0d340ab4eb52b747f3e149::/onion3/qugw4hf5zsopghjlrbcm6crggzbozp4tfbu4duadrf55nyb5dijm6pqd:18141", + "0e99cc89439546d3a59d02fb498d6e1bd7dbeee17c2cecea1966244b8f83b77d::/ip4/57.128.24.58/tcp/18189", +] + +[stagenet.p2p.seeds] +# DNS seeds hosts - DNS TXT records are queried from these hosts and the resulting peers added to the comms peer list. +# (Default: peer_seeds = []) +dns_seeds = ["seeds.stagenet.tari.com"] +# Custom specified peer seed nodes (Default: peer_seeds = []) +#peer_seeds = ["a062ae2345b0db0df9fb1504b99511e23d98f8513f9b5503efcc6dad8eca7e47::/ip4/54.77.66.39/tcp/18189"] + +[esmeralda.p2p.seeds] +# DNS seeds hosts - DNS TXT records are queried from these hosts and the resulting peers added to the comms peer list. +# (Default: peer_seeds = []) +dns_seeds = ["seeds.esmeralda.tari.com"] +# Custom specified peer seed nodes (Default: peer_seeds = []) +peer_seeds = [ + "1e08628960f75b7e324f010b2ee609a9e28097e9101f4d769d474a38b6ee2d76::/ip4/51.83.102.25/tcp/18189", + "1e08628960f75b7e324f010b2ee609a9e28097e9101f4d769d474a38b6ee2d76::/ip6/2001:41d0:303:a619::1/tcp/18189", + "1e08628960f75b7e324f010b2ee609a9e28097e9101f4d769d474a38b6ee2d76::/onion3/tadnxyokalnqjtvu6mlhxndcq4v2tlolotpvrflscdmi7lcautao3had:18141", + "4cdfb70e0b38b60c6a3573b2870e32bc3d846419c606ea379f43650b80f38409::/ip4/51.83.4.85/tcp/18189", + "4cdfb70e0b38b60c6a3573b2870e32bc3d846419c606ea379f43650b80f38409::/ip6/2001:41d0:303:9a55::1/tcp/18189", + "4cdfb70e0b38b60c6a3573b2870e32bc3d846419c606ea379f43650b80f38409::/onion3/mhfptgpcj6htjkr5zwurom32wvt7x76ovqzn2ttnwo2bnku6baeaaiyd:18141", +] + +[igor.p2p.seeds] +# DNS seeds hosts - DNS TXT records are queried from these hosts and the resulting peers added to the comms peer list. +# (Default: peer_seeds = []) +dns_seeds = ["seeds.igor.tari.com"] +# Custom specified peer seed nodes (Default: peer_seeds = []) +#peer_seeds = ["a062ae2345b0db0df9fb1504b99511e23d98f8513f9b5503efcc6dad8eca7e47::/ip4/54.77.66.39/tcp/18189"] + +[mainnet.p2p.seeds] +# DNS seeds hosts - DNS TXT records are queried from these hosts and the resulting peers added to the comms peer list. +# (Default: peer_seeds = []) +dns_seeds = ["seeds.tari.com"] +# Custom specified peer seed nodes (Default: peer_seeds = []) +peer_seeds = [ + "44c1ebed4ec5a6b3b325601e83ff3924f89e8943e15c5e82dfffe83754482b26::/ip4/54.36.113.0/tcp/18189", + "c00684151e75650c63a5d3e4fd4221ce19c4fbffd1a921caaecf06f8a4a65f0f::/ip4/15.235.48.4/tcp/18189", + "02577fd02c9f1fdef52c8de153c17c1af4f29ede2495ee008b334479456e1a5c::/ip4/54.36.117.26/tcp/18189", + "8cc21698e3930da90fd8a9663fedf9d4d56d6ecd7dedec07f8b3590e82061503::/ip4/54.36.112.71/tcp/18189", + "94a4b29148621479b1c1dffb1a2f5680dcf2c0cfb901152e245d6ec299821f61::/ip4/91.134.83.67/tcp/18189", + "1850155828616111f97cc739bf5f3d433d7f07edd477cbf5a3eec0dfe7547c61::/ip4/54.36.117.109/tcp/18189", + "5819ba1c9ddc57d8c82d60b6b3e8c1d8dd369c3336c47112b7483f4ca5fef315::/ip4/15.235.44.167/tcp/18189", + "d6a0d9c3f75ae3cb4d06e314a5f5dceb9cc7ad34f7e8be4126ee25253b039726::/ip4/15.235.44.135/tcp/18189", + "de568a57a62bff39322fff935523c5f670e379783293c88b1c525b776b568d41::/ip4/15.235.49.151/tcp/18189", + "fabf65440daa00a8033a7d0c966d68815f17feb6a25bc60c75bc5d4a84c41123::/ip4/15.235.49.169/tcp/18189", + "7c8e6530294e8bb7ff45b0f39e8bf8ea4e461b3df15a2df1ba3fa3a9bcc9ef71::/ip4/15.235.224.202/tcp/18189", + "ecf3f88c40d0b299cf0d0ff30e7ce8dd5a021c0806b8487426f0de89e4766177::/ip4/141.95.111.150/tcp/18189", + "54e491e0d88633170a98898f5d89ccc6b4f7ec22252afc23fe645d5bab453734::/ip4/198.244.203.249/tcp/18189", + "54e491e0d88633170a98898f5d89ccc6b4f7ec22252afc23fe645d5bab453734::/ip6/2001:41d0:803:f900::/tcp/18189", + "94a4b29148621479b1c1dffb1a2f5680dcf2c0cfb901152e245d6ec299821f61::/ip6/2001:41d0:40d:4300::/tcp/18189", + "7c8e6530294e8bb7ff45b0f39e8bf8ea4e461b3df15a2df1ba3fa3a9bcc9ef71::/ip6/2402:1f00:8005:ca00::/tcp/18189", + "c00684151e75650c63a5d3e4fd4221ce19c4fbffd1a921caaecf06f8a4a65f0f::/ip6/2607:5300:205:300::d28/tcp/18189", + "d6a0d9c3f75ae3cb4d06e314a5f5dceb9cc7ad34f7e8be4126ee25253b039726::/ip6/2607:5300:205:300::afc/tcp/18189", + "fabf65440daa00a8033a7d0c966d68815f17feb6a25bc60c75bc5d4a84c41123::/ip6/2607:5300:205:300::5f4/tcp/18189", + "02577fd02c9f1fdef52c8de153c17c1af4f29ede2495ee008b334479456e1a5c::/ip6/2001:41d0:701:1000::5bf/tcp/18189", + "1850155828616111f97cc739bf5f3d433d7f07edd477cbf5a3eec0dfe7547c61::/ip6/2001:41d0:701:1000::f36/tcp/18189", + "5819ba1c9ddc57d8c82d60b6b3e8c1d8dd369c3336c47112b7483f4ca5fef315::/ip6/2607:5300:205:300::196b/tcp/18189", + "de568a57a62bff39322fff935523c5f670e379783293c88b1c525b776b568d41::/ip6/2607:5300:205:300::2396/tcp/18189", + "ecf3f88c40d0b299cf0d0ff30e7ce8dd5a021c0806b8487426f0de89e4766177::/ip6/2001:41d0:701:1000::3dd/tcp/18189", + "44c1ebed4ec5a6b3b325601e83ff3924f89e8943e15c5e82dfffe83754482b26::/ip6/2001:41d0:701:1000::43ca/tcp/18189", + "8cc21698e3930da90fd8a9663fedf9d4d56d6ecd7dedec07f8b3590e82061503::/ip6/2001:41d0:701:1000::3e6d/tcp/18189", + "02577fd02c9f1fdef52c8de153c17c1af4f29ede2495ee008b334479456e1a5c::/onion3/bukg4svrs4r3hdtx4s2vle6ekipi4v7bshenfwjalymvax7akivyhkyd:18141", + "1850155828616111f97cc739bf5f3d433d7f07edd477cbf5a3eec0dfe7547c61::/onion3/miubwm3dbl5uh4ci7jgvq5jeyhr6sora4fivjm5fkjflyt543cqx2kqd:18141", + "44c1ebed4ec5a6b3b325601e83ff3924f89e8943e15c5e82dfffe83754482b26::/onion3/kimfu5ch2lwo4wm4y6xgi5kvuqnrobdgiyis2okcc27alf3qavuruxqd:18141", + "54e491e0d88633170a98898f5d89ccc6b4f7ec22252afc23fe645d5bab453734::/onion3/b5zgqd6emm6p2zmj7gdniysbxvmtvltrwshsyfxjoq26xqfjoicge5id:18141", + "5819ba1c9ddc57d8c82d60b6b3e8c1d8dd369c3336c47112b7483f4ca5fef315::/onion3/f4n5yh62a3aml5y4lrf7xhqjzgqen2r75ubze2aritezw73qk2uzirad:18141", + "7c8e6530294e8bb7ff45b0f39e8bf8ea4e461b3df15a2df1ba3fa3a9bcc9ef71::/onion3/5husjyv2zskwjh2wzbuirbq4gk5uiyx4gnn277r3yoxv4oucn72tmeyd:18141", + "8cc21698e3930da90fd8a9663fedf9d4d56d6ecd7dedec07f8b3590e82061503::/onion3/yur5nsnkbpfvs4f5h65y652igcqjfv35okchify44kr77evkyfpnleqd:18141", + "94a4b29148621479b1c1dffb1a2f5680dcf2c0cfb901152e245d6ec299821f61::/onion3/x4cc7t4z5bhzz2qoj5qkfje6jnisz5gvzixeygvzwgi6sg3rhpo5rlqd:18141", + "c00684151e75650c63a5d3e4fd4221ce19c4fbffd1a921caaecf06f8a4a65f0f::/onion3/xfa5ijw7747cmjwkbjx6fhobgy4rgx5uozc3dnp7lif7gw7c3dzg6kad:18141", + "d6a0d9c3f75ae3cb4d06e314a5f5dceb9cc7ad34f7e8be4126ee25253b039726::/onion3/kuibpj4742riknkddi4vlrdgklipf6uf5f6b4vdwsklr4iigxrm367qd:18141", + "de568a57a62bff39322fff935523c5f670e379783293c88b1c525b776b568d41::/onion3/xwsoa6q4ijugfar22uoggu22wt6ttmtg2egkyo4fs6ptfjtq3kbrulid:18141", + "ecf3f88c40d0b299cf0d0ff30e7ce8dd5a021c0806b8487426f0de89e4766177::/onion3/3dcfberbstruf3g2g5slacw2ls3nj6qmad2fxumqop3m65llagnhj6yd:18141", + "fabf65440daa00a8033a7d0c966d68815f17feb6a25bc60c75bc5d4a84c41123::/onion3/k7egeg7alhhgr5vbjgatdd6g2rlvy3l6pd3kxvget2q437jqh7q6cuid:18141", +] # Custom specified peer seed nodes (Default: peer_seeds = []) + + +######################################################################################################################## +# # +# Base Node Configuration Options (BaseNodeConfig) # +# # +######################################################################################################################## + +# A Minotari base node is core to the network, providing several functions such as propogation, validation and management. +# These options configure how the base node operates (e.g. gRPC settings, database type, timeout periods, etc.) +# All base node configuration options can be commented out if you do not wish to run a base node. +# While users can use remote nodes, running your own base node adds resilience to the network, provides additional security, +# and direct access to the blockchain. + +[igor.base_node] +# A path to the file that stores your node identity and secret key (default = "config/base_node_id.json") +identity_file = "config/base_node_id_igor.json" + +[esmeralda.base_node] +# A path to the file that stores your node identity and secret key (default = "config/base_node_id.json") +identity_file = "config/base_node_id_esmeralda.json" + +[stagenet.base_node] +# A path to the file that stores your node identity and secret key (default = "config/base_node_id.json") +identity_file = "config/base_node_id_stagenet.json" + +[nextnet.base_node] +# A path to the file that stores your node identity and secret key (default = "config/base_node_id.json") +identity_file = "config/base_node_id_nextnet.json" + +[base_node] +#mining_enabled = false +#second_layer_grpc_enabled = false +# Set to false to disable the base node GRPC server (default = true) +grpc_enabled = true + +# The socket to expose for the gRPC base node server (default = "http://127.0.0.1:18142") +#grpc_address = "/ip4/127.0.0.1/tcp/18142" + +# gRPC authentication method (default = "none") +#grpc_authentication = { username = "admin", password = "xxxx" } + +# Use gRPC over TLS (default = false) +#grpc_tls_enabled = false + +# Uncomment all gRPC server methods that should be allowed (only active when `grpc_enabled = true`) +grpc_server_allow_methods = [ + "get_version", + #"check_for_updates", + #"get_sync_info", + #"get_sync_progress", + "get_tip_info", + "identify", + #"get_network_status", + "list_headers", + #"get_header_by_hash", + #"get_blocks", + #"get_block_timing", + #"get_constants", + #"get_block_size", + #"get_block_fees", + "get_tokens_in_circulation", + "get_network_difficulty", + "get_new_block_template", + "get_new_block", + "get_new_block_with_coinbases", + "get_new_block_template_with_coinbases", + "get_new_block_blob", + "submit_block", + "submit_block_blob", + "submit_transaction", + "search_kernels", + "search_utxos", + "fetch_matching_utxos", + #"get_peers", + #"get_mempool_transactions", + "transaction_state", + "list_connected_peers", + "get_mempool_stats", + "get_active_validator_nodes", + "get_validator_node_changes", + "get_shard_key", + "get_template_registrations", + "get_side_chain_utxos", + "search_payment_references", + "search_payment_references_via_output_hash", +] + +# A path to the file that stores your node identity and secret key (default = "config/base_node_id.json") +#identity_file = "config/base_node_id.json" + +# Spin up and use a built-in Tor instance, only works on macos/linux and must comment out 'tor.control_address' below. +# This requires that the base node was built with the optional "libtor" feature flag. (default = true) +#use_libtor = false + +# A path to the file that stores the tor hidden service private key, if using the tor transport. +# (default = "config/tor_id.json") +#tor_identity_file = "config/base_node_tor_id.json" + +# The type of database backend to use. Currently supported options are "memory" and "lmdb". LMDB is recommnded for +# almost all use cases. (default = "lmdb") +#db_type = "lmdb" + +# The relative path to store persistent data (default = "data/base_node") +#data_dir = "data/base_node" + +# The relative path to store the lmdb blockchain data (default = "db") +#lmdb_path = "db" + +# The maximum amount of VMs that RandomX will be use (default = 5) +#max_randomx_vms = 5 + +# Bypass range proof verification to speed up validation (default = false) +#bypass_range_proof_verification = false + +# This allowlist provides a method to force syncing from any known nodes you may choose, for example if you have a +# couple of nodes that you always want to have in sync. If set this node will only sync to the nodes in this set. +# force_sync_peers = ["public_key1::address1", "public_key2::address2",... ] + +# The maximum amount of seconds wait for remote base node responses for messaging-based requests. +#messaging_request_timeout = 60 + +# The time interval between status line updates in the CLI (default = 5 s) +#status_line_interval = 5 + +# The buffer size constants for the publish/subscribe connector channel, connecting comms messages to the domain layer: +# (min value = 30, default value = 1500). +#buffer_size = 1500 + +# Liveness metadata auto ping interval between peers (default = 30 s) +#metadata_auto_ping_interval = 30 + +# Obscure GRPC error responses (default = false) +#report_grpc_error = false + +# Interval between each request to the dns server for hte checkpoints to compare it with the local blockchain (default = 120 s) +# tari_pulse_interval = 120 + +# Interval which the node will use to discover and dial the seed peers. +# tari_pulse_health_check = 600 # 10 mins + +[base_node.lmdb] +#init_size_bytes = 16_777_216 # 16 *1024 * 1024 +#grow_size_bytes = 16_777_216 # 16 *1024 * 1024 +#resize_threshold_bytes = 4_194_304 # 4 *1024 * 1024 + +[base_node.storage] +# The maximum number of orphans that can be stored in the Orphan block pool. +#orphan_storage_capacity = 720 +# The pruning horizon that is set for a default configuration of the blockchain db. +#pruning_horizon = 0 +# The chain height interval used to determine when a pruned node should perform pruning. +#pruning_interval = 50 +# Set to true to record all reorgs. Recorded reorgs can be viewed using the list-reorgs command. Default = false +track_reorgs = true +# Clean out +#cleanup_orphans_at_startup = false + +[base_node.mempool] +# The maximum number of transactions that can be stored in the Unconfirmed Transaction pool +#unconfirmed_pool.storage_capacity = 40_000 +# The maximum number of transactions that can be skipped when compiling a set of highest priority transactions, +# skipping over large transactions are performed in an attempt to fit more transactions into the remaining space. +#unconfirmed_pool.weight_tx_skip_count = 20 +# The minimum fee accepted by the mempool +#unconfirmed_pool.min_fee = 50, + +# The height horizon to clear transactions from the reorg pool. +#reorg_pool.expiry_height = 5 + +# Number of peers from which to initiate a sync. Once this many peers have successfully synced, this node will +# not initiate any more mempool syncs. Default: 2 +#service.initial_sync_num_peers = 2 +# The maximum number of transactions to sync in a single sync session Default: 10_000 +#service.initial_sync_max_transactions = 10_000 +# The maximum number of blocks added via sync or re-org to triggering a sync +#service.block_sync_trigger = 5 + +[base_node.state_machine] +# The initial max sync latency (seconds). If a peer fails to stream a header/block within this deadline another sync +# peer will be selected. If there are no further peers the sync will be restarted with an increased by +# `max_latency_increase`. [default = 240] +blockchain_sync_config.initial_max_sync_latency = 240 +# If all sync peers exceed latency increase allowed latency by this value (seconds) [default = 10] +blockchain_sync_config.max_latency_increase = 10 +# Longer ban period (seconds) for potentially malicious infractions (protocol violations etc.) [default = 2 hours] +#blockchain_sync_config.ban_period = 7_200 # 2 * 60 * 60 +# Short ban period (seconds) for infractions that are likely not malicious (slow to respond spotty connections etc) +# [default = 4 minutes] +#blockchain_sync_config.short_ban_period = 240 +# An allowlist of sync peers from which to sync. No other peers will be selected for sync. If empty sync peers +# are chosen based on their advertised chain metadata. [default = []] +#blockchain_sync_config.forced_sync_peers = [] +# Number of threads to use for validation [default = 6] +#blockchain_sync_config.validation_concurrency = 6 +# The RPC deadline to set on sync clients. If this deadline is reached, a new sync peer will be selected for sync. +# [default = 240] +blockchain_sync_config.rpc_deadline = 240 + +# The maximum amount of VMs that RandomX will be use (default = 0) +#max_randomx_vms = 0 +# The amount of blocks this node can be behind a peer before considered to be lagging (to test the block +# propagation by delaying lagging, but also to give it time to receive the block via propagation, which is more network +# efficient) +# Note that time_before_considered_lagging will override this setting if the node sees a stronger chain for longer than +# that configured time. +# (default = 1) +#blocks_behind_before_considered_lagging = 1 +# The amount of time this node can know about a stronger chain before considered to be lagging. +# This is to give a node time to receive the block via propagation, which is usually less network +# intensive. Be careful of setting this higher than the block time, which would potentially cause it +# to always be behind the network (default = 10) (in seconds) +#time_before_considered_lagging = 10 +#This is the amount of metadata events that a node will wait for before decide to start syncing for a peer, choosing the best peer out of the list +#initial_sync_peer_count = 5, + +[base_node.p2p] +# The node's publicly-accessible hostname. This is the host name that is advertised on the network so that +# peers can find you. +# _NOTE_: If using the `tor` transport type, public_addresses will be ignored and an onion address will be +# automatically configured +#public_addresses = ["/ip4/172.2.3.4/tcp/18189",] + +# Optionally bind an additional TCP socket for inbound Tari P2P protocol commms. +# Use cases include: +# - allowing wallets to locally connect to their base node, rather than through tor, when used in conjunction with +# `tor_proxy_bypass_addresses` +# - multiple P2P addresses, one public over DNS and one private over TOR +# - a "bridge" between TOR and TCP-only nodes +# auxiliary_tcp_listener_address = "/ip4/127.0.0.1/tcp/9998" + +# Path to the SQLite databasse (relative to data_dir) used for the peer database. +#datastore_path = "peer_db" + +# Name to use for the peer database +#peer_database_name = "peers" + +# The maximum number of concurrent Inbound tasks allowed before back-pressure is applied to peers +#max_concurrent_inbound_tasks = 100 + +# The maximum number of concurrent outbound tasks allowed before back-pressure is applied to outbound messaging queue +#max_concurrent_outbound_tasks = 100 + +# Set to true to allow peers to provide test addresses (loopback, memory etc.). If set to false, memory +# addresses, loopback, local-link (i.e addresses used in local tests) will not be accepted from peers. This +# should always be false for non-test nodes. +#allow_test_addresses = false + +# CIDR for addresses allowed to enter into liveness check mode on the listener. +#listener_liveness_allowlist_cidrs = [] +# Enables periodic socket-level liveness checks. Default: Disabled +listener_self_liveness_check_interval = 15 + +# The maximum simultaneous comms RPC sessions allowed (default value = 100). Setting this to -1 will allow unlimited +# sessions. +#rpc_max_simultaneous_sessions = 100 +# The maximum comms RPC sessions allowed per peer (default value = 10). +#rpc_max_sessions_per_peer = 10 +# If true, and the maximum per peer RPC sessions is reached, the RPC server will close an old session and replace it +# with a new session. If false, the RPC server will reject the new session and preserve the older session. +# (default value = true). +#pub cull_oldest_peer_rpc_connection_on_full = true + +[base_node.p2p.transport] +# -------------- Transport configuration -------------- +# Use TCP to connect to the Tari network. This transport can only communicate with TCP/IP addresses, so peers with +# e.g. tor onion addresses will not be contactable. (default = "tor") +#type = "tor" + +# The address and port to listen for peer connections over TCP. (use: type = "tcp") +#tcp.listener_address = "/ip4/0.0.0.0/tcp/18189" +# Configures a tor proxy used to connect to onion addresses. All other traffic uses direct TCP connections. +# This setting is optional however, if it is not specified, this node will not be able to connect to nodes that +# only advertise an onion address. (default = ) +#tcp.tor_socks_address = +# Optional tor SOCKS proxy authentication (default = "none") +#tcp.tor_socks_auth = "none" + +# Configures the node to run over a tor hidden service using the Tor proxy. This transport recognises ip/tcp, +# onion v2, onion v3 and dns addresses. (use: type = "tor") +# Address of the tor control server +#tor.control_address = "/ip4/127.0.0.1/tcp/9051" +# SOCKS proxy auth (default = "none") +#tor.socks_auth = "none" +# Use this socks address instead of getting it from the tor proxy. (default = ) +#tor.socks_address_override = +# Authentication to use for the tor control server (default = "auto") +#tor.control_auth = "auto" # or "password=xxxxxx" +# The onion port to use. +#tor.onion_port = 18141 +# When these peer addresses are encountered when dialing another peer, the tor proxy is bypassed and the connection is +# made directly over TCP. /ip4, /ip6, /dns, /dns4 and /dns6 are supported. (e.g. ["/dns4/my-foo-base-node/tcp/9998"]) +#tor.proxy_bypass_addresses = [] +# When using the tor transport and set to true, outbound TCP connections bypass the tor proxy. Defaults to 'true' for +# better network performance for TCP nodes; set it to 'false' for better privacy. +#tor.proxy_bypass_for_outbound_tcp = true +# If set, instructs tor to forward traffic the provided address. (e.g. "/dns4/my-base-node/tcp/32123") (default = OS-assigned port) +#tor.forward_address = +# If set, the listener will bind to this address instead of the forward_address. You need to make sure that this listener is connectable from the forward_address. +#tor.listener_address_override = + +# Use a SOCKS5 proxy transport. This transport recognises any addresses supported by the proxy. +# (use: type = "socks5") +# The address of the SOCKS5 proxy. Traffic will be forwarded to tcp.listener_address. +# (Default = "/ip4/127.0.0.1/tcp/8080") +#socks.proxy_address = "/ip4/127.0.0.1/tcp/9050" +# SOCKS proxy auth (Default = "none", or assign "username_password=username:xxxxxxx") +#socks.auth = "none" + +# Use a Memory proxy transport. (use: type = "memory") +#memory.listener_address = "/memory/0" + +[base_node.p2p.dht] +# The `DbConnectionUrl` for the Dht database. Default: In-memory database +database_url = "data/base_node/dht.db" +# The maximum number of peer nodes that a message has to be closer to, to be considered a neighbour. Default: 8 +#num_neighbouring_nodes = 6 +# Number of random peers to include. Default: 4 +#num_random_nodes = 6 +# Connections above the configured number of neighbouring and random nodes will be removed (default: false) +#minimize_connections = false +# Send to this many peers when using the broadcast strategy. Default: 8 +#broadcast_factor = 8 +# Send to this many peers when using the propagate strategy. Default: 4 +#propagation_factor = 4 + +# The amount of time added to the current time will be used to check if the message has expired or not. Default: 3 hours +#saf.msg_validity = 10_800 # 3 * 60 * 60 // 3 hours +# The maximum number of messages that can be stored using the Store-and-forward middleware. Default: 100,000 +#saf.msg_storage_capacity = 100_000 +# A request to retrieve stored messages will be ignored if the requesting node is not within one of this nodes _n_ +# closest nodes. Default 10 +#saf.num_closest_nodes = 10 +# The maximum number of messages to return from a store and forward retrieval request. Default: 100 +#saf.max_returned_messages = 50 +# The time-to-live duration used for storage of low priority messages by the Store-and-forward middleware. +# Default: 6 hours +#saf.low_priority_msg_storage_ttl = 21_600 # 6 * 60 * 60 // 6 hours +# The time-to-live duration used for storage of high priority messages by the Store-and-forward middleware. +# Default: 3 days +#saf.high_priority_msg_storage_ttl = 259_200 # 3 * 24 * 60 * 60 // 3 days +# The limit on the message size to store in SAF storage in bytes. Default 500 KiB +#saf.max_message_size = 524_288 # 512 * 1024 +# When true, store and forward messages are requested from peers on connect (Default: true) +#saf.auto_request = true +# The maximum allowed time between asking for a message and accepting a response +#saf.max_inflight_request_age = 120 +# The maximum number of peer nodes that a message must be closer than to get stored by SAF. Default: 8 +#saf.num_neighbouring_nodes = 8 + +# The max capacity of the message hash cache. Default: 2,500 +#dedup_cache_capacity = 2_500 +# The periodic trim interval for items in the message hash cache. Default: 300s (5 mins) +#dedup_cache_trim_interval = 300 # 5 * 60 +# The number of occurrences of a message is allowed to pass through the DHT pipeline before being deduped/discarded +# Default: 1 +#dedup_allowed_message_occurrences = 1 +# The duration to wait for a peer discovery to complete before giving up. Default: 2 minutes +#discovery_request_timeout = 120 # 2 * 60 +# Set to true to automatically broadcast a join message when ready, otherwise false. Default: false +#auto_join = true +# The minimum time between sending a Join message to the network. Joins are only sent when the node establishes +# enough connections to the network as determined by comms ConnectivityManager. If a join was sent and then state +# change happens again after this period, another join will be sent. Default: 10 minutes +#join_cooldown_interval = 120 # 10 * 60 + +# The interval to update the neighbouring and random pools, if necessary. Default: 2 minutes +#connectivity.update_interval = 120 # 2 * 60 +# The interval to change the random pool peers. Default = 2 hours +#connectivity.random_pool_refresh_interval = 7_200 # 2 * 60 * 60 +# Length of cooldown when high connection failure rates are encountered. Default: 45s +#connectivity.high_failure_rate_cooldown = 45 +# The minimum desired ratio of TCPv4 to Tor connections. TCPv4 addresses have some significant cost to create, +# making sybil attacks costly. This setting does not guarantee this ratio is maintained. +# Currently, it only emits a warning if the ratio is below this setting. Default: 0.1 (10%) +#connectivity.minimum_desired_tcpv4_node_ratio = 0.1 + +# True to enable network discovery, false to disable it. Default: true +#network_discovery.enabled = true +# A threshold for the minimum number of peers this node should ideally be aware of. If below this threshold a +# more "aggressive" strategy is employed. Default: 50 +#network_discovery.min_desired_peers = 50 +# The period to wait once the number of rounds given by `idle_after_num_rounds` has completed. Default: 30 mins +#network_discovery.idle_period = 1_800 # 30 * 60 +# The minimum number of network discovery rounds to perform before idling (going to sleep). If there are less +# than `min_desired_peers` then the actual number of rounds performed will exceed this value. Default: 10 +#network_discovery.idle_after_num_rounds = 10 +# Time to idle after a failed round. Default: 5 secs +#network_discovery.on_failure_idle_period = 5 +# The maximum number of sync peer to select for each round. The selection strategy varies depending on the current state. +# Default: 5 +#network_discovery.max_sync_peers = 5 +# The maximum number of peers we allow per round of sync. (Default: 500) +#network_discovery.max_peers_to_sync_per_round = 500 +# Initial refresh sync peers delay period, when a configured connection needs preference. (Default: Disabled) +#network_discovery.initial_peer_sync_delay = 0 + +# Length of time to ban a peer if the peer misbehaves at the DHT-level. Default: 6 hrs +#ban_duration = 21_600 # 6 * 60 * 60 +# Length of time to ban a peer for a "short" duration. Default: 60 mins +#ban_duration_short = 3_600 # 60 * 60 +# The maximum number of messages over `flood_ban_timespan` to allow before banning the peer (for `ban_duration_short`) +# Default: 100_000 messages +#flood_ban_max_msg_count = 100_000 +# The timespan over which to calculate the max message rate. +# `flood_ban_max_count / flood_ban_timespan (as seconds) = avg. messages per second over the timespan` +# Default: 100 seconds +#flood_ban_timespan = 100 +# Once a peer has been marked as offline, wait at least this length of time before reconsidering them. +# In a situation where a node is not well-connected and many nodes are locally marked as offline, we can retry +# peers that were previously tried. Default: 2 hours +#offline_peer_cooldown = 7_200 # 2 * 60 * 60 +# Addresses that should never be dialed (default value = []). This can be a specific address or an IPv4/TCP range. +# Example: When used in conjunction with `allow_test_addresses = true` (but it could be any other range) +# `excluded_dial_addresses = ["/ip4/127.*.0:49.*/tcp/*", "/ip4/127.*.101:255.*/tcp/*"]` +# or +# `excluded_dial_addresses = ["/ip4/127.0:0.1/tcp/122", "/ip4/127.0:0.1/tcp/1000:2000"]` +excluded_dial_addresses = [] +# Enables the DHT to forward messages to other nodes in the network - communication nodes only (Default: false) +#enable_forwarding = false + +# setting this to some version will reject peers that dont meet the min version or the agent string in the correct string. +# peer string should match X/X/X/X/{VERSION} where the last segment is the version in semer versioning scheme +#peer_validator_config.min_peer_version = "" + +# Wallet Query HTTP service details +# `external_address` is optional, but if not set, then wallet wont be able to call our endpoint. +# This address must be accessible by the wallet (on a global scale over the internet). +[base_node.http_wallet_query_service] +#port = 9000 +#external_address = "http://127.0.0.1:9000" +######################################################################################################################## +# # +# Wallet Configuration Options (WalletConfig) # +# # +######################################################################################################################## + +[wallet] +# The buffer size constants for the publish/subscribe connector channel, connecting comms messages to the domain layer: +# (min value = 300, default value = 50000). +#buffer_size = 50000 + +# The relative path to store persistent data (default = "data/wallet") +#data_dir = "data/wallet" + +# The relative folder to store your local key data and transaction history. (default = "db/console_wallet.db") +# DO NOT EVER DELETE THIS FILE unless you (a) have backed up your seed phrase and (b) know what you are doing! +#db_file = "db/console_wallet.db" + +# The main wallet db sqlite database backend connection pool size for concurrent reads (default = 16) +#db_connection_pool_size = 16 + +# Console wallet password. Should you wish to start your console wallet without typing in your password, the following +# options are available: +# 1. Start the console wallet with the --password=secret argument, or +# 2. Set the environment variable MINOTARI_WALLET_PASSWORD=secret before starting the console wallet, or +# 3. Set the "password" key in this [wallet] section of the config +# (default = ) +#password = "secret" + +# The auto ping interval to use for contacts liveness data (default = 30 s) +#contacts_auto_ping_interval = 30 + +# How long a contact may be not seen before being determined to be offline (default = 30 s) +#contacts_online_ping_window = 30 + +# When running the console wallet in command mode, use these values to determine what "stage" and timeout to wait +# for sent transactions. +# The stages are: +# - "DirectSendOrSaf" - The transaction was initiated and was accepted via Direct Send or Store And Forward. +# - "Negotiated" - The recipient replied and the transaction was negotiated. +# - "Broadcast" - The transaction was broadcast to the base node mempool. +# - "MinedUnconfirmed" - The transaction was successfully detected as mined but unconfirmed on the blockchain. +# - "Mined" - The transaction was successfully detected as mined and confirmed on the blockchain. +# The default values are: "Broadcast", 300 +#command_send_wait_timeout = 300 +#command_send_wait_stage = "Broadcast" + +# Wallets currently will choose the best outputs as inputs when spending, however since a lurking base node can +# generate a transaction graph of inputs to outputs with relative ease, a wallet may reveal its transaction +# history by including a (non-stealth address) one-sided payment. +# If set to `true`, then outputs received via simple one-sided transactions, won't be automatically selected as +# further transactions, but can still be selected individually as specific outputs. +#autoignore_onesided_utxos = false + +# Set to true to enable grpc. (default = false) +#grpc_enabled = false +# The socket to expose for the gRPC base node server (default = "http://127.0.0.1:18143") +#grpc_address = "/ip4/127.0.0.1/tcp/18143" +# gRPC authentication method (default = "none") +#grpc_authentication = { username = "admin", password = "xxxx" } + +# A custom base node peer that will be used to obtain metadata from, example +# "0eefb45a4de9484eca74846a4f47d2c8d38e76be1fec63b0112bd00d297c0928::/ip4/13.40.98.39/tcp/18189" +# (default = ) +#custom_base_node = "none" + +# A list of base node peers that the wallet should use for service requests and tracking chain state in the form +# ["public_key::net_address", ...] (default = []) +#base_node_service_peers = [] + +# The amount of times wallet recovery will be retried before being abandoned (default = 3) +#recovery_retry_limit = 3 + +# The default uT fee per gram to use for transaction fees (default = 5) +#fee_per_gram = 5 + +# Number of required transaction confirmations used for UI purposes (default = 3) +#num_required_confirmations = 3 + +# Spin up and use a built-in Tor instance, only works on macos/linux and must comment out 'tor.control_address' below. +# This requires that the base node was built with the optional "libtor" feature flag. (default = true) +#use_libtor = false + +# A path to the file that stores your node identity and secret key (default = "none") +#identity_file = "none" + +# Notification script file for a notifier service. Allows you to execute a script or program when these transaction +# events are received by the console wallet (default = "none"): +# - transaction received +# - transaction sent +# - transaction cancelled +# - transaction mined but unconfirmed +# - transaction mined and confirmed +# An example script is available here: applications/minotari_console_wallet/src/notifier/notify_example.sh +#notify_file = "/path/to/script" + +# The cool down period between balance enquiry checks in seconds; requests faster than this will be ignored. +# For specialized wallets processing many batch transactions this setting could be increased to 60 s to retain +# responsiveness of the wallet with slightly delayed balance updates (default = 5): +#balance_enquiry_cooldown_period = 5 +#The defaul offset for scanning from the birthday, it will start at the birthday - the offset +#birthday_offset = 2 +#The scanning interval in secs to poll the base node for new blocks +#scanning_interval = 60 +# The URL of the HTTP client to use for base node service requests +#http_server_url="http://127.0.0.1:9000" +# The fallback url address to use if the base node at http_server_url does not respond +#fallback_http_server_url = "https://rpc.esmeralda.tari.com" + +[wallet.transactions] +# This is the timeout period that will be used for base node broadcast monitoring tasks (default = 30) +broadcast_monitoring_timeout = 180 +# This is the timeout period that will be used for chain monitoring tasks (default = 60) +chain_monitoring_timeout = 60 +# This is the timeout period that will be used for sending transactions directly (default = 20) +direct_send_timeout = 180 +# This is the timeout period that will be used for sending transactions via broadcast mode (default = 60) +broadcast_send_timeout = 180 +# This is the timeout period that will be used for low power moded polling tasks (default = 300) +#low_power_polling_timeout = 300 +# This is the timeout period that will be used to resend transactions that did not make any progress (default = 600) +#transaction_resend_period = 600 +# This is the timeout period that will be used to ignore repeated transactions (default = 300) +#resend_response_cooldown = 300 +# This is the timeout period that will be used to expire pending transactions (default = 259200) +#pending_transaction_cancellation_timeout = 259200 # 3 days +# This is the number of block confirmations required for a transaction to be considered completely mined and +# confirmed. (default = 3) +#num_confirmations_required = 3 +# The number of batches the unconfirmed transactions will be divided into before being queried from the base node +# (default = 20) +#max_tx_query_batch_size = 20 +# This option specifies the transaction routing mechanism as being directly between wallets, making +# use of store and forward or using any combination of these. +# (options: "DirectOnly", "StoreAndForwardOnly", DirectAndStoreAndForward". default: "DirectAndStoreAndForward"). +#transaction_routing_mechanism = "DirectAndStoreAndForward" +# This is the size of the event channel used to communicate transaction status events to the wallet's UI. A busy console +# wallet doing thousands of bulk payments or used for stress testing needs a fairly big size (>10000) (default = 1000). +transaction_event_channel_size = 25000 +# This is the timeout period that will be used to re-submit transactions not found in the mempool (default = 600) +#transaction_mempool_resubmission_window = 600 + +[wallet.outputs] +# If a large amount of tiny valued uT UTXOs are used as inputs to a transaction, the fee may be larger than the +# transaction amount. Set this value to `false` to allow spending of "dust" UTXOs for small valued transactions +# (default = true). +prevent_fee_gt_amount = false +# Ignores dust below this value, value in micro MinoTari, defaults to 100 +# dust_ignore_value: 100, +# This is the size of the event channel used to communicate output manager events to the wallet. A busy console +# wallet doing thousands of bulk payments or used for stress testing needs a fairly big size (>3000) (default = 250). +event_channel_size = 3500 +# The number of confirmations (difference between tip height and mined height) required for the output to be marked as +# mined confirmed (default = 3) +#num_confirmations_required = 3 +# The number of batches the unconfirmed outputs will be divided into before being queried from the base node +# (default = 100) +#tx_validator_batch_size = 100 +# Number of seconds that have to pass for the wallet to run revalidation of invalid UTXOs on startup. +# If you set it to zero, the revalidation will be on every wallet rerun. Default is 3 days. +#num_of_seconds_to_revalidate_invalid_utxos = 259200 + + +[wallet.base_node] +# Configuration for the wallet's base node service +# The refresh interval +#base_node_monitor_max_refresh_interval = 30 +# The RPC client pool size (default = 5) +#base_node_rpc_pool_size = 5 +# This is the size of the event channel used to communicate base node events to the wallet. (default = 250). +#event_channel_size = 250 + +[wallet.p2p] +# The node's publicly-accessible hostname. This is the host name that is advertised on the network so that +# peers can find you. +# _NOTE_: If using the `tor` transport type, public_address will be ignored and an onion address will be +# automatically configured +#public_addresses = ["/ip4/172.2.3.4/tcp/18188",] + +# Optionally bind an additional TCP socket for inbound Tari P2P protocol commms. +# Use cases include: +# - allowing wallets to locally connect to their base node, rather than through tor, when used in conjunction with +# `tor_proxy_bypass_addresses` +# - multiple P2P addresses, one public over DNS and one private over TOR +# - a "bridge" between TOR and TCP-only nodes +#auxiliary_tcp_listener_address = "/ip4/127.0.0.1/tcp/9998" + +# Path to the SQLite databasse (relative to data_dir) used for the peer database. +#datastore_path = "peer_db" + +# Name to use for the peer database +#peer_database_name = "peers" + +# The maximum number of concurrent Inbound tasks allowed before back-pressure is applied to peers +#max_concurrent_inbound_tasks = 100 + +# The maximum number of concurrent outbound tasks allowed before back-pressure is applied to outbound messaging queue +#max_concurrent_outbound_tasks = 100 + +# Set to true to allow peers to provide test addresses (loopback, memory etc.). If set to false, memory +# addresses, loopback, local-link (i.e addresses used in local tests) will not be accepted from peers. This +# should always be false for non-test nodes. +#allow_test_addresses = false + +# CIDR for addresses allowed to enter into liveness check mode on the listener. +#listener_liveness_allowlist_cidrs = [] +# Enables periodic socket-level liveness checks. Default: Disabled +# listener_self_liveness_check_interval = 15 + +# User agent string for this node +#user_agent = "" + +# The maximum simultaneous comms RPC sessions allowed (default value = 100). Setting this to -1 will allow unlimited +# sessions. +#rpc_max_simultaneous_sessions = 100 +# The maximum comms RPC sessions allowed per peer (default value = 10). +#rpc_max_sessions_per_peer = 10 +#rpc_max_sessions_per_peer = 10 +# If true, and the maximum per peer RPC sessions is reached, the RPC server will close an old session and replace it +# with a new session. If false, the RPC server will reject the new session and preserve the older session. +# (default value = true). +#pub cull_oldest_peer_rpc_connection_on_full = true + +[wallet.p2p.transport] +# -------------- Transport configuration -------------- +# Use TCP to connect to the Tari network. This transport can only communicate with TCP/IP addresses, so peers with +# e.g. tor onion addresses will not be contactable. (default = "tor") +#type = "tor" + +# The address and port to listen for peer connections over TCP. (use: type = "tcp") +#tcp.listener_address = "/ip4/0.0.0.0/tcp/18189" +# Configures a tor proxy used to connect to onion addresses. All other traffic uses direct TCP connections. +# This setting is optional however, if it is not specified, this node will not be able to connect to nodes that +# only advertise an onion address. (default = ) +#tcp.tor_socks_address = +# Optional tor SOCKS proxy authentication (default = "none") +#tcp.tor_socks_auth = "none" + +# Configures the node to run over a tor hidden service using the Tor proxy. This transport recognises ip/tcp, +# onion v2, onion v3 and dns addresses. (use: type = "tor") +# Address of the tor control server +#tor.control_address = "/ip4/127.0.0.1/tcp/9051" +# SOCKS proxy auth (default = "none") +#tor.socks_auth = "none" +# Use this socks address instead of getting it from the tor proxy. (default = ) +#tor.socks_address_override = +# Authentication to use for the tor control server (default = "auto") +#tor.control_auth = "auto" # or "password=xxxxxx" +# The onion port to use. +#tor.onion_port = 18141 +# When these peer addresses are encountered when dialing another peer, the tor proxy is bypassed and the connection is +# made directly over TCP. /ip4, /ip6, /dns, /dns4 and /dns6 are supported. (e.g. ["/dns4/my-foo-base-node/tcp/9998"]) +#tor.proxy_bypass_addresses = [] +# When using the tor transport and set to true, outbound TCP connections bypass the tor proxy. Defaults to 'true' for +# better network performance for TCP nodes; set it to 'false' for better privacy. +#tor.proxy_bypass_for_outbound_tcp = true +# If set, instructs tor to forward traffic the provided address. (e.g. "/ip4/127.0.0.1/tcp/0") (default = ) +#tor.forward_address = + +# Use a SOCKS5 proxy transport. This transport recognises any addresses supported by the proxy. +# (use: type = "socks5") +# The address of the SOCKS5 proxy. Traffic will be forwarded to tcp.listener_address. +# (Default = "/ip4/127.0.0.1/tcp/8080") +#socks.proxy_address = "/ip4/127.0.0.1/tcp/9050" +# SOCKS proxy auth (Default = "none", or assign "username_password=username:xxxxxxx") +#socks.auth = "none" + +# Use a Memory proxy transport. (use: type = "memory") +#memory.listener_address = "/memory/0" + +[wallet.p2p.dht] +# The `DbConnectionUrl` for the Dht database. Default: In-memory database +database_url = "data/wallet/dht.db" +# The maximum number of peer nodes that a message has to be closer to, to be considered a neighbour. Default: 8 +num_neighbouring_nodes = 5 +# Number of random peers to include. Default: 4 +num_random_nodes = 1 +# Connections above the configured number of neighbouring and random nodes will be removed (default: false) +minimize_connections = true +# Send to this many peers when using the broadcast strategy. Default: 8 +#broadcast_factor = 8 +# Send to this many peers when using the propagate strategy. Default: 4 +#propagation_factor = 4 + +# The amount of time added to the current time will be used to check if the message has expired or not. Default: 3 hours +#saf.msg_validity = 10_800 # 3 * 60 * 60 // 3 hours +# The maximum number of messages that can be stored using the Store-and-forward middleware. Default: 100,000 +#saf.msg_storage_capacity = 100_000 +# A request to retrieve stored messages will be ignored if the requesting node is not within one of this nodes _n_ +# closest nodes. Default 10 +#saf.num_closest_nodes = 10 +# The maximum number of messages to return from a store and forward retrieval request. Default: 100 +#saf.max_returned_messages = 50 +# The time-to-live duration used for storage of low priority messages by the Store-and-forward middleware. +# Default: 6 hours +#saf.low_priority_msg_storage_ttl = 21_600 # 6 * 60 * 60 // 6 hours +# The time-to-live duration used for storage of high priority messages by the Store-and-forward middleware. +# Default: 3 days +#saf.high_priority_msg_storage_ttl = 259_200 # 3 * 24 * 60 * 60 // 3 days +# The limit on the message size to store in SAF storage in bytes. Default 500 KiB +#saf.max_message_size = 524_288 # 512 * 1024 +# When true, store and forward messages are requested from peers on connect (Default: true) +#saf.auto_request = true +# The maximum allowed time between asking for a message and accepting a response +#saf.max_inflight_request_age = 120 +# The maximum number of peer nodes that a message must be closer than to get stored by SAF. Default: 8 +#saf.num_neighbouring_nodes = 8 + +# The max capacity of the message hash cache. Default: 2,500 +#dedup_cache_capacity = 2_500 +# The periodic trim interval for items in the message hash cache. Default: 300s (5 mins) +#dedup_cache_trim_interval = 300 # 5 * 60 +# The number of occurrences of a message is allowed to pass through the DHT pipeline before being deduped/discarded +# Default: 1 +#dedup_allowed_message_occurrences = 1 +# The duration to wait for a peer discovery to complete before giving up. Default: 2 minutes +#discovery_request_timeout = 120 # 2 * 60 +# Set to true to automatically broadcast a join message when ready, otherwise false. Default: false +#auto_join = true +# The minimum time between sending a Join message to the network. Joins are only sent when the node establishes +# enough connections to the network as determined by comms ConnectivityManager. If a join was sent and then state +# change happens again after this period, another join will be sent. Default: 10 minutes +#join_cooldown_interval = 120 # 10 * 60 + +# The interval to update the neighbouring and random pools, if necessary. Default: 2 minutes +connectivity.update_interval = 300 # 2 * 60 +# The interval to change the random pool peers. Default = 2 hours +#connectivity.random_pool_refresh_interval = 7_200 # 2 * 60 * 60 +# Length of cooldown when high connection failure rates are encountered. Default: 45s +#connectivity.high_failure_rate_cooldown = 45 +# The minimum desired ratio of TCPv4 to Tor connections. TCPv4 addresses have some significant cost to create, +# making sybil attacks costly. This setting does not guarantee this ratio is maintained. +# Currently, it only emits a warning if the ratio is below this setting. Default: 0.1 (10%) +connectivity.minimum_desired_tcpv4_node_ratio = 0.0 + +# True to enable network discovery, false to disable it. Default: true +#network_discovery.enabled = true +# A threshold for the minimum number of peers this node should ideally be aware of. If below this threshold a +# more "aggressive" strategy is employed. Default: 50 +network_discovery.min_desired_peers = 16 +# The period to wait once the number of rounds given by `idle_after_num_rounds` has completed. Default: 30 mins +#network_discovery.idle_period = 1_800 # 30 * 60 +# The minimum number of network discovery rounds to perform before idling (going to sleep). If there are less +# than `min_desired_peers` then the actual number of rounds performed will exceed this value. Default: 10 +#network_discovery.idle_after_num_rounds = 10 +# Time to idle after a failed round. Default: 5 secs +#network_discovery.on_failure_idle_period = 5 +# The maximum number of sync peer to select for each round. The selection strategy varies depending on the current state. +# Default: 5 +#network_discovery.max_sync_peers = 5 +# The maximum number of peers we allow per round of sync. (Default: 500) +#network_discovery.max_peers_to_sync_per_round = 500 +# Initial refresh sync peers delay period, when a configured connection needs preference. (Default: Disabled) +network_discovery.initial_peer_sync_delay = 25 + +# Length of time to ban a peer if the peer misbehaves at the DHT-level. Default: 6 hrs +ban_duration = 120 # 2 mins +# Length of time to ban a peer for a "short" duration. Default: 60 mins +ban_duration_short = 60 # 1 min +# The maximum number of messages over `flood_ban_timespan` to allow before banning the peer (for `ban_duration_short`) +# Default: 100_000 messages +#flood_ban_max_msg_count = 100_000 +# The timespan over which to calculate the max message rate. +# `flood_ban_max_count / flood_ban_timespan (as seconds) = avg. messages per second over the timespan` +# Default: 100 seconds +#flood_ban_timespan = 100 +# Once a peer has been marked as offline, wait at least this length of time before reconsidering them. +# In a situation where a node is not well-connected and many nodes are locally marked as offline, we can retry +# peers that were previously tried. Default: 2 hours +#offline_peer_cooldown = 7_200 # 2 * 60 * 60 +# Addresses that should never be dialed (default value = []). This can be a specific address or an IPv4/TCP range. +# Example: When used in conjunction with `allow_test_addresses = true` (but it could be any other range) +# `excluded_dial_addresses = ["/ip4/127.*.0:49.*/tcp/*", "/ip4/127.*.101:255.*/tcp/*"]` +# or +# `excluded_dial_addresses = ["/ip4/127.0:0.1/tcp/122", "/ip4/127.0:0.1/tcp/1000:2000"]` +excluded_dial_addresses = [] +# Enables the DHT to forward messages to other nodes in the network - communication nodes only (Default: false) +#enable_forwarding = false + +# setting this to some version will reject peers that dont meet the min version or the agent string in the correct string. +# peer string should match X/X/X/X/{VERSION} where the last segment is the version in semer versioning scheme +#peer_validator_config.min_peer_version = "" + + +######################################################################################################################## +# # +# Miner Configuration Options (MinerConfig) # +# # +######################################################################################################################## + +[miner] + +# GRPC address of base node (default = "http://127.0.0.1:18142") +base_node_grpc_address = "http://127.0.0.1:18142" +# GRPC authentication for the base node (default = "none") +#base_node_grpc_authentication = { username = "miner", password = "xxxx" } +# GRPC TLS communication is turned on by defining the domain name for the service (default = "none") +#base_node_grpc_tls_domain_name = "localhost" + +# Number of mining threads (default: number of logical CPU cores) +num_mining_threads = 1 + +# Start mining only when base node is bootstrapped and current block height is on the tip of network (default = true) +#mine_on_tip_only = true + +# 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 (default = 30 s) +#validate_tip_timeout_sec = 30 + +# Stratum Mode configuration - mining pool address (e.g. "miningcore.tari.com:3052") +#mining_pool_address = "miningcore.tari.com:3052" + +# Stratum Mode configuration - mining wallet address/public key +# (e.g. "20B19870ABEE8ABC6ACC77AE4E6CA169057645B27C35334B74446B4D3EE52150") +#stratum_mining_wallet_address = "f2HRDbEBUJKBJVWtGneP7pDng7u3VTpgjAqDB1YywgCgx8ff5yUWzke2Do6gpvBbFn4MDTY7nwTpyB8Paor85zAjUYi" + +# Stratum Mode configuration - mining worker name (e.g. "worker1") (default = "") +#stratum_mining_worker_name = "worker1" + +# 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%. +#coinbase_extra = "minotari_miner" + +# Base node reconnect timeout after any GRPC or miner error (default: 10 s) +#wait_timeout_on_error = 10 + +# The Tari wallet address (valid address in hex) where the mining funds will be sent to - must be assigned +# e.g. "78e724f466d202abdee0f23c261289074e4a2fc9eb61e83e0179eead76ce2d3f17" +wallet_payment_address = "f2HRDbEBUJKBJVWtGneP7pDng7u3VTpgjAqDB1YywgCgx8ff5yUWzke2Do6gpvBbFn4MDTY7nwTpyB8Paor85zAjUYi" +# Range proof type - revealed_value or bullet_proof_plus: (default = "revealed_value") +#range_proof_type = "revealed_value" + +# The mining algorithm to use - options are Sha3x or RandomXT (the Tari version of RandomX). (default = "Sha3X") +#proof_of_work_algo = "Sha3X" + + +######################################################################################################################## +# # +# Merge Mining Configuration Options (MergeMiningProxyConfig) # +# # +######################################################################################################################## + +[merge_mining_proxy] + + +# Use dynamic monerod URL obtained form the official Monero website (https://monero.fail/) (default: true) +#use_dynamic_fail_data = true + +# The monero fail URL to get the monerod URLs from - must be pointing to the official Monero website. +# Valid alternatives are: +# - mainnet: 'https://monero.fail/?chain=monero&network=mainnet&all=true' (default) +# - stagenet: `https://monero.fail/?chain=monero&network=stagenet&all=true` +# - testnet: `https://monero.fail/?chain=monero&network=testnet&all=true` +#monero_fail_url = "https://monero.fail/?chain=monero&network=mainnet&all=true" + +# URL to monerod (you can add your own server here or use public nodes from https://monero.fail/), only if +# 'use_dynamic_fail_data = false' or if the server at 'monero_fail_url' is not available +# (default: The 'monerod_url = [ # mainnet ...' list below) + +#monerod_url = [# stagenet +# "http://stagenet.xmr-tw.org:38081", +# "http://node.monerodevs.org:38089", +# "http://node3.monerodevs.org:38089", +# "http://xmr-lux.boldsuck.org:38081", +# "http://singapore.node.xmr.pm:38081", +#] + +#monerod_url = [ # mainnet +# "http://node.c3pool.org:18081", +# "http://xmr-full.p2pool.uk:18089", +# "http://monero.stackwallet.com:18081", +# "http://xmr.support:18081", +# "https://xmr-01.tari.com", +# "http://node1.xmr-tw.org:18081", +# "http://monero-g2.hexhex.online:18081", +# "http://137.220.120.19:18089", +# "http://185.218.124.120:18489", +# "http://185.218.124.120:18789", +# "https://xmr-de-2.boldsuck.org:18081", +# "http://46.32.46.171:18081", +# "http://185.218.124.120:18089", +# "http://185.218.124.120:18589", +# "http://xmr-de-1.boldsuck.org:18081", +# "http://185.218.124.120:18889", +# "http://pinodexmr.hopto.org:18081", +# "http://node.tincloud.eu:18081", +# "http://183.6.24.33:18081", +# "http://147.45.196.232:18089", +# "http://h-helix.com:18089", +# "http://185.218.124.120:18689", +# "http://185.218.124.120:18289", +# "https://node.tincloud.eu", +# "https://xmr-de.boldsuck.org:18081", +# "https://monero.booze.org", +# "https://xmr.mailia.be:18088", +# "https://xmr.lolfox.au", +# "https://xmr1.doggett.tech:18089", +# "https://node.icefiles.nz:18081", +# "http://45.8.132.220:18089", +# "http://82.147.85.13:18089", +#] + +# Username for curl. (default = "") +#monerod_username = "" + +# Password for curl. (default = "") +#monerod_password = "" + +# If authentication is being used for curl. (default = false) +#monerod_use_auth = false + +# The Minotari base node's GRPC address. (default = "http://127.0.0.1:18142") +#base_node_grpc_address = "http://127.0.0.1:18142" + +# GRPC authentication for the base node (default = "none") +#base_node_grpc_authentication = { username = "miner", password = "xxxx" } + +# Address of the minotari_merge_mining_proxy application. (default = "/ip4/127.0.0.1/tcp/18081") +#listener_address = "/ip4/127.0.0.1/tcp/18081" + +# In sole merged mining, the block solution is usually submitted to the Monero blockchain +# (monerod) as well as to the Minotari blockchain, then this setting should be "true". With pool +# merged mining, there is no sense in submitting the solution to the Monero blockchain as the +# pool does that, then this setting should be "false". (default = true) +#submit_to_origin = true + +# The merge mining proxy can either wait for the base node to achieve initial sync at startup before it enables mining, +# or not. If merge mining starts before the base node has achieved initial sync, those Minotari mined blocks will not be +# accepted. (default = true) +#wait_for_initial_sync_at_startup = true + +# When mining for minotari, you might want to check the achieved difficulty of the mined minotari block before submitting +# This setting this can be disabled to allow you to always submit minotari blocks even if the difficulty does not meet the +# required. (default = true) +#check_tari_difficulty_before_submit = true + +# The maximum amount of VMs that RandomX will be use (default = 5) +#max_randomx_vms = 5 + +# 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%. (default = "tari_merge_mining_proxy") +#coinbase_extra = "tari_merge_mining_proxy" + +# The Tari wallet address (valid address in hex) where the mining funds will be sent to - must be assigned +# e.g. "78e724f466d202abdee0f23c261289074e4a2fc9eb61e83e0179eead76ce2d3f17" +wallet_payment_address = "f2HRDbEBUJKBJVWtGneP7pDng7u3VTpgjAqDB1YywgCgx8ff5yUWzke2Do6gpvBbFn4MDTY7nwTpyB8Paor85zAjUYi" +# Range proof type - "revealed_value" or "bullet_proof_plus": (default = "revealed_value") +#range_proof_type = "revealed_value" + +# Use p2pool to submit and get block templates (default = false) +#p2pool_enabled = false, + +# The timeout duration for connecting to monerod (default = 2s) +#monerod_connection_timeout = 2 + + +######################################################################################################################## +# # +# Validator Node Configuration Options (ValidatorNodeConfig) # +# # +######################################################################################################################## + +[validator_node] + +# A path to the file that stores your node identity and secret key (default = "validator_node_id.json") +#identity_file = "validator_node_id.json" + +# A path to the file that stores the tor hidden service private key, if using the tor transport +# (default = "validator_node_tor_id.json") +#tor_identity_file = "validator_node_tor_id.json" + +# The node's publicly-accessible hostname. This is the host name that is advertised on the network so that +# peers can find you. +# _NOTE_: If using the `tor` transport type, public_address will be ignored and an onion address will be +# automatically configured (default = ) +#public_address = + +# The Minotari base node's GRPC address. (default = "http://127.0.0.1:" the value is based on network) +#base_node_grpc_address = "http://127.0.0.1:18142" + +# The Minotari console wallet's GRPC address. (default = "http://127.0.0.1:" the value is based on network) +#wallet_grpc_address = "127.0.0.1/tcp/18143" + +# How often do we want to scan the base layer for changes. (default = 10) +#base_layer_scanning_interval = 10 + +# The relative path to store persistent data (default = "data/validator_node") +#data_dir = "data/validator_node" + +# JSON-RPC listener address (default = "127.0.0.1:18200") +#json_rpc_address = "127.0.0.1:18200" + +# HTTP UI listener address (default = "127.0.0.1:5000") +#http_ui_address = "127.0.0.1:5000" + +# Set to true to enable auto registration for each epoch (default = true) +#auto_register = true + +[validator_node.p2p] +#transport = "tor" + + +######################################################################################################################## +# # +# Collectibles Configuration Options (CollectiblesConfig) # +# # +######################################################################################################################## + +[collectibles] + +# GRPC address of validator node (default = "http://127.0.0.1:18144") +#validator_node_grpc_address = "http://127.0.0.1:18144" + +# GRPC address of base node (default = "http://127.0.0.1:18142") +#base_node_grpc_address = "http://127.0.0.1:18142" + +# GRPC address of wallet (default = "http://127.0.0.1:18143") +#wallet_grpc_address = "http://127.0.0.1:18143" + + +######################################################################################################################## +# # +# Indexer Configuration Options (IndexerConfig) # +# # +######################################################################################################################## + +[indexer] + +# A path to the file that stores your node identity and secret key (default = "indexer_id.json") +#identity_file = "indexer_id.json" + +# A path to the file that stores the tor hidden service private key, if using the tor transport +# (default = "indexer_tor_id.json") +#tor_identity_file = "indexer_tor_id.json" + +# The node's publicly-accessible hostname. This is the host name that is advertised on the network so that +# peers can find you. +# _NOTE_: If using the `tor` transport type, public_address will be ignored and an onion address will be +# automatically configured (default = ) +#public_address = + +# The Minotari base node's GRPC address. (default = "http://127.0.0.1:" the value is based on network) +#base_node_grpc_address = "http://127.0.0.1:18142" + +# How often do we want to scan the base layer for changes. (default = 10) +#base_layer_scanning_interval = 10 + +# The relative path to store persistent data (default = "data/indexer") +#data_dir = "data/indexer" + +# JSON-RPC listener address (default = "127.0.0.1:18300") +#json_rpc_address = "127.0.0.1:18300" + +# HTTP UI listener address (default = "127.0.0.1:15000") +#http_ui_address = "127.0.0.1:15000" + +# Substate addresses to keep watching +#address_watchlist=[] + +# How often do we want to scan the dan layer for change. (default = 10) +#dan_layer_scanning_internal=10 + +[indexer.p2p] +#transport = "tor" + + +######################################################################################################################## +# # +# DAN Wallet Daemon Configuration Options () # +# # +######################################################################################################################## + +[dan_wallet_daemon] +# JSON-RPC listener address (default = "127.0.0.1:9000") +# listen_addr = "127.0.0.1:9000" + +# Signaling server address (default = "127.0.0.1:9100") +# signaling_server_addr = "127.0.0.1:9100" + +# Validator node endpoint url (default = "http://127.0.0.1:18200/json_rpc") +# validator_node_endpoint = "http://127.0.0.1:18200/json_rpc" + diff --git a/internal/gbt/tari/miner/log4rs.yml b/internal/gbt/tari/miner/log4rs.yml new file mode 100644 index 0000000..3263294 --- /dev/null +++ b/internal/gbt/tari/miner/log4rs.yml @@ -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 diff --git a/internal/gbt/tari/minotari_miner/Cargo.toml b/internal/gbt/tari/minotari_miner/Cargo.toml new file mode 100644 index 0000000..4c53db4 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/Cargo.toml @@ -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", +] diff --git a/internal/gbt/tari/minotari_miner/README.md b/internal/gbt/tari/minotari_miner/README.md new file mode 100644 index 0000000..be11f2b --- /dev/null +++ b/internal/gbt/tari/minotari_miner/README.md @@ -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. diff --git a/internal/gbt/tari/minotari_miner/build.rs b/internal/gbt/tari/minotari_miner/build.rs new file mode 100644 index 0000000..d89d530 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/build.rs @@ -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() {} diff --git a/internal/gbt/tari/minotari_miner/icon.ico b/internal/gbt/tari/minotari_miner/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..4c7ee91f398b4d3db4bb0104ff8f9b04d8235513 GIT binary patch literal 285478 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 z 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�i**O4(bDOJR@=7vFww8m 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 R_?TOM$G3kgpF4Br{{l=3Qak_v literal 0 HcmV?d00001 diff --git a/internal/gbt/tari/minotari_miner/linux/runtime/start_minotari_miner.sh b/internal/gbt/tari/minotari_miner/linux/runtime/start_minotari_miner.sh new file mode 100644 index 0000000..f8b045a --- /dev/null +++ b/internal/gbt/tari/minotari_miner/linux/runtime/start_minotari_miner.sh @@ -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} diff --git a/internal/gbt/tari/minotari_miner/linux/start_minotari_miner b/internal/gbt/tari/minotari_miner/linux/start_minotari_miner new file mode 100644 index 0000000..8a971d2 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/linux/start_minotari_miner @@ -0,0 +1 @@ +./runtime/start_minotari_miner.sh \ No newline at end of file diff --git a/internal/gbt/tari/minotari_miner/log4rs_sample.yml b/internal/gbt/tari/minotari_miner/log4rs_sample.yml new file mode 100644 index 0000000..bf7d90d --- /dev/null +++ b/internal/gbt/tari/minotari_miner/log4rs_sample.yml @@ -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 diff --git a/internal/gbt/tari/minotari_miner/osx/runtime/start_minotari_miner.sh b/internal/gbt/tari/minotari_miner/osx/runtime/start_minotari_miner.sh new file mode 100644 index 0000000..57cb144 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/osx/runtime/start_minotari_miner.sh @@ -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 diff --git a/internal/gbt/tari/minotari_miner/osx/start_minotari_miner b/internal/gbt/tari/minotari_miner/osx/start_minotari_miner new file mode 100644 index 0000000..8a971d2 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/osx/start_minotari_miner @@ -0,0 +1 @@ +./runtime/start_minotari_miner.sh \ No newline at end of file diff --git a/internal/gbt/tari/minotari_miner/src/cli.rs b/internal/gbt/tari/minotari_miner/src/cli.rs new file mode 100644 index 0000000..039e935 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/cli.rs @@ -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, + #[clap(long, alias = "max-blocks")] + pub miner_max_blocks: Option, + #[clap(long, alias = "min-difficulty")] + pub miner_min_diff: Option, + #[clap(long, alias = "max-difficulty")] + pub miner_max_diff: Option, + #[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())); +} diff --git a/internal/gbt/tari/minotari_miner/src/config.rs b/internal/gbt/tari/minotari_miner/src/config.rs new file mode 100644 index 0000000..642aac6 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/config.rs @@ -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, + /// 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, + /// 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>(&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); + } +} diff --git a/internal/gbt/tari/minotari_miner/src/difficulty.rs b/internal/gbt/tari/minotari_miner/src/difficulty.rs new file mode 100644 index 0000000..b8df393 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/difficulty.rs @@ -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, +} + +impl BlockHeaderSha3 { + #[allow(clippy::cast_possible_truncation)] + #[allow(clippy::cast_sign_loss)] + pub fn new(header: grpc_header, vm_key: FixedHash, rx_factory: Option) -> Result { + 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 { + self.hashes = self.hashes.saturating_add(1); + Ok(sha3x_difficulty(&self.header)?.as_u64()) + } + + #[inline] + pub fn difficulty_rx(&mut self) -> Result { + 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::::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()); + } + } +} diff --git a/internal/gbt/tari/minotari_miner/src/errors.rs b/internal/gbt/tari/minotari_miner/src/errors.rs new file mode 100644 index 0000000..79267b3 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/errors.rs @@ -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()) +} diff --git a/internal/gbt/tari/minotari_miner/src/lib.rs b/internal/gbt/tari/minotari_miner/src/lib.rs new file mode 100644 index 0000000..90f1db7 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/lib.rs @@ -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 +} diff --git a/internal/gbt/tari/minotari_miner/src/main.rs b/internal/gbt/tari/minotari_miner/src/main.rs new file mode 100644 index 0000000..587c807 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/main.rs @@ -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 +} diff --git a/internal/gbt/tari/minotari_miner/src/miner.rs b/internal/gbt/tari/minotari_miner/src/miner.rs new file mode 100644 index 0000000..9a6afa5 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/miner.rs @@ -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, + 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>, + channels: Vec>, + num_threads: usize, + header: BlockHeader, + target_difficulty: u64, + share_mode: bool, + vm_key: FixedHash, + rx_factory: Option, + + publisher_socket: Arc>, + subscriber_socket: Arc>, + 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, + publisher_socket: Arc>, + subscriber_socket: Arc>, + ) -> 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> { + 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>, msg: &GbtMsg) -> Result<(), Box> { + 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>) -> Option { + 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::(&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, + waker: Waker, + miner: usize, + share_mode: bool, + vm_key: FixedHash, + rx_factory: Option, + publisher_socket: Arc>, + subscriber_socket: Arc>, +) { + 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(()) +} \ No newline at end of file diff --git a/internal/gbt/tari/minotari_miner/src/run_miner.rs b/internal/gbt/tari/minotari_miner/src/run_miner.rs new file mode 100644 index 0000000..8f5eb19 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/run_miner.rs @@ -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, +} + +async fn connect(config: &MinerConfig) -> Result { + // 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 { + 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 { + 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>>, + config: &MinerConfig, + cli: &Cli, + key_manager: &MemoryDbKeyManager, + wallet_payment_address: &TariAddress, + consensus_manager: &ConsensusManager, +) -> Result { + 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 { + 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 { + 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 { + 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, + config: &MinerConfig, + cli: &Cli, + key_manager: &MemoryDbKeyManager, + wallet_payment_address: &TariAddress, + consensus_manager: &ConsensusManager, + publisher_socket: Arc>, + subscriber_socket: Arc>, +) -> Result { + 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, +) -> 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(()) +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/controller.rs b/internal/gbt/tari/minotari_miner/src/stratum/controller.rs new file mode 100644 index 0000000..3fd2bcf --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/controller.rs @@ -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, + server_password: Option, + server_tls_enabled: Option, + stream: Option, + rx: mpsc::Receiver, + pub tx: mpsc::Sender, + miner_tx: mpsc::Sender, + 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, + server_password: Option, + server_tls_enabled: Option, + miner_tx: mpsc::Sender, + ) -> Result { + let (tx, rx) = mpsc::channel::(); + 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, 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::()?, + job.target.parse::()?, + 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::(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::(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::(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::(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::(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::(&m) { + // Is this a response or request? + if v["method"] == "job" { + // this is a request + match serde_json::from_str::(&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::(&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 + } +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/error.rs b/internal/gbt/tari/minotari_miner/src/stratum/error.rs new file mode 100644 index 0000000..29f1ac3 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/error.rs @@ -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>), + #[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 From> for Error { + fn from(error: std::sync::PoisonError) -> Self { + Error::General(format!("Failed to get lock: {:?}", error)) + } +} + +impl From> for Error { + fn from(error: std::sync::mpsc::SendError) -> Self { + Error::General(format!("Failed to send to a channel: {:?}", error)) + } +} + +impl From> for Error { + fn from(error: native_tls::HandshakeError) -> Self { + Error::General(format!("TLS handshake error: {:?}", error)) + } +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/mod.rs b/internal/gbt/tari/minotari_miner/src/stratum/mod.rs new file mode 100644 index 0000000..3b82bfd --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/mod.rs @@ -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; diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/controller.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/controller.rs new file mode 100644 index 0000000..27bbbae --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/controller.rs @@ -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, + pub tx: mpsc::Sender, + client_tx: Option>, + current_height: u64, + current_job_id: u64, + current_difficulty_target: u64, + current_blob: CurrentBlob, + current_header: Option, + keep_alive_time: SystemTime, + num_mining_threads: usize, + +} + +impl Controller { + pub fn new(num_mining_threads: usize) -> Result { + let (tx, rx) = mpsc::channel::(); + 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) { + self.client_tx = Some(client_tx); + } + + #[allow(clippy::too_many_lines)] + pub async fn run(&mut self) -> Result<(), Error> { + let mut miner: Option = 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 { + 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) + } + } +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/mod.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/mod.rs new file mode 100644 index 0000000..bebf4e8 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_controller/mod.rs @@ -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; diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/client_message.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/client_message.rs new file mode 100644 index 0000000..fe25165 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/client_message.rs @@ -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, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job.rs new file mode 100644 index 0000000..fc33165 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job.rs @@ -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, + pub target: u64, + pub height: u64, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job_params.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job_params.rs new file mode 100644 index 0000000..8cd3a2c --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/job_params.rs @@ -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, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_params.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_params.rs new file mode 100644 index 0000000..3bde37b --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_params.rs @@ -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, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_response.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_response.rs new file mode 100644 index 0000000..e6fe598 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/login_response.rs @@ -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, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/miner_message.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/miner_message.rs new file mode 100644 index 0000000..a8a557b --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/miner_message.rs @@ -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), + ResumeJob, + StopJob, + Shutdown, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/mod.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/mod.rs new file mode 100644 index 0000000..242f76c --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/mod.rs @@ -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; diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_error.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_error.rs new file mode 100644 index 0000000..3044533 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_error.rs @@ -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, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_request.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_request.rs new file mode 100644 index 0000000..8278166 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_request.rs @@ -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, + pub jsonrpc: String, + pub method: String, + pub params: Option, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_response.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_response.rs new file mode 100644 index 0000000..bad6973 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/rpc_response.rs @@ -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, + pub error: Option, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_params.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_params.rs new file mode 100644 index 0000000..913a7d0 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_params.rs @@ -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, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_response.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_response.rs new file mode 100644 index 0000000..407c334 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/submit_response.rs @@ -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, + pub error: Option, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/worker_identifier.rs b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/worker_identifier.rs new file mode 100644 index 0000000..f5cb805 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stratum_types/worker_identifier.rs @@ -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, +} diff --git a/internal/gbt/tari/minotari_miner/src/stratum/stream.rs b/internal/gbt/tari/minotari_miner/src/stratum/stream.rs new file mode 100644 index 0000000..dba1bc9 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/src/stratum/stream.rs @@ -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), + TlsStream(Box>>), +} + +impl Stream { + pub fn try_connect(server_url: &str, tls: Option) -> Result { + 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 { + 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 { + 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) -> io::Result { + self.buf_reader().read_until(byte, buf) + } + + fn read_line(&mut self, string: &mut String) -> io::Result { + self.buf_reader().read_line(string) + } +} diff --git a/internal/gbt/tari/minotari_miner/windows/runtime/source_miner_env.bat b/internal/gbt/tari/minotari_miner/windows/runtime/source_miner_env.bat new file mode 100644 index 0000000..513bcf1 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/windows/runtime/source_miner_env.bat @@ -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%" diff --git a/internal/gbt/tari/minotari_miner/windows/runtime/start_minotari_miner.bat b/internal/gbt/tari/minotari_miner/windows/runtime/start_minotari_miner.bat new file mode 100644 index 0000000..b620145 --- /dev/null +++ b/internal/gbt/tari/minotari_miner/windows/runtime/start_minotari_miner.bat @@ -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 diff --git a/internal/gbt/tari/minotari_miner/windows/start_minotari_miner.lnk b/internal/gbt/tari/minotari_miner/windows/start_minotari_miner.lnk new file mode 100644 index 0000000000000000000000000000000000000000..3d2d3590e02c2c770fc26e35da346d778e9e9c52 GIT binary patch literal 2426 zcmeHIT}YEr7=C8G{a8XRD)=el#kuO6#0d9u^p}&0FsdG=-3Z7)0a!tx##tQW>#uj`_w+ z`l&ybM%H!h$2NFT4>tm6LWpQ0c8stdSLWmz;cN+oJ$_pzkoOa>j0vyWC%lnhG)m2x zLYZ))g?wRn;D-%djwDn_&Ct`7eCNklFwz_uXXQN+WZ1vNy& zOsyH^+_wN_47>~u6k;Pbv2P|@#(`^eNnRU{BTrNTgRK8T;j1Z zK>`x7mq$m}P5m&Hnnnt-sHo8DstL^Hn%OkILo7SzU4EYO*dX8x=}V(K@(y7g+uBnn zTgB7HioS_2q{QVyE#k=6FlS literal 0 HcmV?d00001 diff --git a/internal/gbt/tari/proto/base_node.pb.go b/internal/gbt/tari/proto/base_node.pb.go deleted file mode 100644 index 74fb539..0000000 --- a/internal/gbt/tari/proto/base_node.pb.go +++ /dev/null @@ -1,4609 +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: base_node.proto - -package base_node - -import ( - block "pool/internal/gbt/tari/proto/block" - net_work "pool/internal/gbt/tari/proto/net_work" - sidechain_types "pool/internal/gbt/tari/proto/sidechain_types" - transaction "pool/internal/gbt/tari/proto/transaction" - 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 BaseNodeState int32 - -const ( - BaseNodeState_START_UP BaseNodeState = 0 - BaseNodeState_HEADER_SYNC BaseNodeState = 1 - BaseNodeState_HORIZON_SYNC BaseNodeState = 2 - BaseNodeState_CONNECTING BaseNodeState = 3 - BaseNodeState_BLOCK_SYNC BaseNodeState = 4 - BaseNodeState_LISTENING BaseNodeState = 5 - BaseNodeState_SYNC_FAILED BaseNodeState = 6 -) - -// Enum value maps for BaseNodeState. -var ( - BaseNodeState_name = map[int32]string{ - 0: "START_UP", - 1: "HEADER_SYNC", - 2: "HORIZON_SYNC", - 3: "CONNECTING", - 4: "BLOCK_SYNC", - 5: "LISTENING", - 6: "SYNC_FAILED", - } - BaseNodeState_value = map[string]int32{ - "START_UP": 0, - "HEADER_SYNC": 1, - "HORIZON_SYNC": 2, - "CONNECTING": 3, - "BLOCK_SYNC": 4, - "LISTENING": 5, - "SYNC_FAILED": 6, - } -) - -func (x BaseNodeState) Enum() *BaseNodeState { - p := new(BaseNodeState) - *p = x - return p -} - -func (x BaseNodeState) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (BaseNodeState) Descriptor() protoreflect.EnumDescriptor { - return file_base_node_proto_enumTypes[0].Descriptor() -} - -func (BaseNodeState) Type() protoreflect.EnumType { - return &file_base_node_proto_enumTypes[0] -} - -func (x BaseNodeState) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use BaseNodeState.Descriptor instead. -func (BaseNodeState) EnumDescriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{0} -} - -type CalcType int32 - -const ( - CalcType_MEAN CalcType = 0 - CalcType_MEDIAN CalcType = 1 - CalcType_QUANTILE CalcType = 2 - CalcType_QUARTILE CalcType = 3 -) - -// Enum value maps for CalcType. -var ( - CalcType_name = map[int32]string{ - 0: "MEAN", - 1: "MEDIAN", - 2: "QUANTILE", - 3: "QUARTILE", - } - CalcType_value = map[string]int32{ - "MEAN": 0, - "MEDIAN": 1, - "QUANTILE": 2, - "QUARTILE": 3, - } -) - -func (x CalcType) Enum() *CalcType { - p := new(CalcType) - *p = x - return p -} - -func (x CalcType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (CalcType) Descriptor() protoreflect.EnumDescriptor { - return file_base_node_proto_enumTypes[1].Descriptor() -} - -func (CalcType) Type() protoreflect.EnumType { - return &file_base_node_proto_enumTypes[1] -} - -func (x CalcType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use CalcType.Descriptor instead. -func (CalcType) EnumDescriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{1} -} - -type Sorting int32 - -const ( - Sorting_SORTING_DESC Sorting = 0 - Sorting_SORTING_ASC Sorting = 1 -) - -// Enum value maps for Sorting. -var ( - Sorting_name = map[int32]string{ - 0: "SORTING_DESC", - 1: "SORTING_ASC", - } - Sorting_value = map[string]int32{ - "SORTING_DESC": 0, - "SORTING_ASC": 1, - } -) - -func (x Sorting) Enum() *Sorting { - p := new(Sorting) - *p = x - return p -} - -func (x Sorting) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (Sorting) Descriptor() protoreflect.EnumDescriptor { - return file_base_node_proto_enumTypes[2].Descriptor() -} - -func (Sorting) Type() protoreflect.EnumType { - return &file_base_node_proto_enumTypes[2] -} - -func (x Sorting) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use Sorting.Descriptor instead. -func (Sorting) EnumDescriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{2} -} - -type SyncState int32 - -const ( - SyncState_STARTUP SyncState = 0 - SyncState_HEADER_STARTING SyncState = 1 - SyncState_HEADER SyncState = 2 - SyncState_BLOCK_STARTING SyncState = 3 - SyncState_BLOCK SyncState = 4 - SyncState_DONE SyncState = 5 -) - -// Enum value maps for SyncState. -var ( - SyncState_name = map[int32]string{ - 0: "STARTUP", - 1: "HEADER_STARTING", - 2: "HEADER", - 3: "BLOCK_STARTING", - 4: "BLOCK", - 5: "DONE", - } - SyncState_value = map[string]int32{ - "STARTUP": 0, - "HEADER_STARTING": 1, - "HEADER": 2, - "BLOCK_STARTING": 3, - "BLOCK": 4, - "DONE": 5, - } -) - -func (x SyncState) Enum() *SyncState { - p := new(SyncState) - *p = x - return p -} - -func (x SyncState) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SyncState) Descriptor() protoreflect.EnumDescriptor { - return file_base_node_proto_enumTypes[3].Descriptor() -} - -func (SyncState) Type() protoreflect.EnumType { - return &file_base_node_proto_enumTypes[3] -} - -func (x SyncState) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SyncState.Descriptor instead. -func (SyncState) EnumDescriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{3} -} - -type SubmitTransactionResult int32 - -const ( - SubmitTransactionResult_NONE SubmitTransactionResult = 0 - SubmitTransactionResult_ACCEPTED SubmitTransactionResult = 1 - SubmitTransactionResult_NOT_PROCESSABLE_AT_THIS_TIME SubmitTransactionResult = 2 - SubmitTransactionResult_ALREADY_MINED SubmitTransactionResult = 3 - SubmitTransactionResult_REJECTED SubmitTransactionResult = 4 -) - -// Enum value maps for SubmitTransactionResult. -var ( - SubmitTransactionResult_name = map[int32]string{ - 0: "NONE", - 1: "ACCEPTED", - 2: "NOT_PROCESSABLE_AT_THIS_TIME", - 3: "ALREADY_MINED", - 4: "REJECTED", - } - SubmitTransactionResult_value = map[string]int32{ - "NONE": 0, - "ACCEPTED": 1, - "NOT_PROCESSABLE_AT_THIS_TIME": 2, - "ALREADY_MINED": 3, - "REJECTED": 4, - } -) - -func (x SubmitTransactionResult) Enum() *SubmitTransactionResult { - p := new(SubmitTransactionResult) - *p = x - return p -} - -func (x SubmitTransactionResult) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (SubmitTransactionResult) Descriptor() protoreflect.EnumDescriptor { - return file_base_node_proto_enumTypes[4].Descriptor() -} - -func (SubmitTransactionResult) Type() protoreflect.EnumType { - return &file_base_node_proto_enumTypes[4] -} - -func (x SubmitTransactionResult) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use SubmitTransactionResult.Descriptor instead. -func (SubmitTransactionResult) EnumDescriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{4} -} - -type TransactionLocation int32 - -const ( - TransactionLocation_UNKNOWN TransactionLocation = 0 - TransactionLocation_MEMPOOL TransactionLocation = 1 - TransactionLocation_MINED TransactionLocation = 2 - TransactionLocation_NOT_STORED TransactionLocation = 3 -) - -// Enum value maps for TransactionLocation. -var ( - TransactionLocation_name = map[int32]string{ - 0: "UNKNOWN", - 1: "MEMPOOL", - 2: "MINED", - 3: "NOT_STORED", - } - TransactionLocation_value = map[string]int32{ - "UNKNOWN": 0, - "MEMPOOL": 1, - "MINED": 2, - "NOT_STORED": 3, - } -) - -func (x TransactionLocation) Enum() *TransactionLocation { - p := new(TransactionLocation) - *p = x - return p -} - -func (x TransactionLocation) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (TransactionLocation) Descriptor() protoreflect.EnumDescriptor { - return file_base_node_proto_enumTypes[5].Descriptor() -} - -func (TransactionLocation) Type() protoreflect.EnumType { - return &file_base_node_proto_enumTypes[5] -} - -func (x TransactionLocation) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use TransactionLocation.Descriptor instead. -func (TransactionLocation) EnumDescriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{5} -} - -type GetAssetMetadataRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AssetPublicKey []byte `protobuf:"bytes,1,opt,name=asset_public_key,json=assetPublicKey,proto3" json:"asset_public_key,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAssetMetadataRequest) Reset() { - *x = GetAssetMetadataRequest{} - mi := &file_base_node_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAssetMetadataRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAssetMetadataRequest) ProtoMessage() {} - -func (x *GetAssetMetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 GetAssetMetadataRequest.ProtoReflect.Descriptor instead. -func (*GetAssetMetadataRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{0} -} - -func (x *GetAssetMetadataRequest) GetAssetPublicKey() []byte { - if x != nil { - return x.AssetPublicKey - } - return nil -} - -type GetAssetMetadataResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - Image string `protobuf:"bytes,4,opt,name=image,proto3" json:"image,omitempty"` - OwnerCommitment []byte `protobuf:"bytes,5,opt,name=owner_commitment,json=ownerCommitment,proto3" json:"owner_commitment,omitempty"` - Features *transaction.OutputFeatures `protobuf:"bytes,6,opt,name=features,proto3" json:"features,omitempty"` - MinedHeight uint64 `protobuf:"varint,7,opt,name=mined_height,json=minedHeight,proto3" json:"mined_height,omitempty"` - MinedInBlock []byte `protobuf:"bytes,8,opt,name=mined_in_block,json=minedInBlock,proto3" json:"mined_in_block,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetAssetMetadataResponse) Reset() { - *x = GetAssetMetadataResponse{} - mi := &file_base_node_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetAssetMetadataResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetAssetMetadataResponse) ProtoMessage() {} - -func (x *GetAssetMetadataResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 GetAssetMetadataResponse.ProtoReflect.Descriptor instead. -func (*GetAssetMetadataResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{1} -} - -func (x *GetAssetMetadataResponse) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *GetAssetMetadataResponse) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *GetAssetMetadataResponse) GetImage() string { - if x != nil { - return x.Image - } - return "" -} - -func (x *GetAssetMetadataResponse) GetOwnerCommitment() []byte { - if x != nil { - return x.OwnerCommitment - } - return nil -} - -func (x *GetAssetMetadataResponse) GetFeatures() *transaction.OutputFeatures { - if x != nil { - return x.Features - } - return nil -} - -func (x *GetAssetMetadataResponse) GetMinedHeight() uint64 { - if x != nil { - return x.MinedHeight - } - return 0 -} - -func (x *GetAssetMetadataResponse) GetMinedInBlock() []byte { - if x != nil { - return x.MinedInBlock - } - return nil -} - -type ListAssetRegistrationsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Offset uint64 `protobuf:"varint,2,opt,name=offset,proto3" json:"offset,omitempty"` - Count uint64 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListAssetRegistrationsRequest) Reset() { - *x = ListAssetRegistrationsRequest{} - mi := &file_base_node_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListAssetRegistrationsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListAssetRegistrationsRequest) ProtoMessage() {} - -func (x *ListAssetRegistrationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 ListAssetRegistrationsRequest.ProtoReflect.Descriptor instead. -func (*ListAssetRegistrationsRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{2} -} - -func (x *ListAssetRegistrationsRequest) GetOffset() uint64 { - if x != nil { - return x.Offset - } - return 0 -} - -func (x *ListAssetRegistrationsRequest) GetCount() uint64 { - if x != nil { - return x.Count - } - return 0 -} - -type ListAssetRegistrationsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - AssetPublicKey []byte `protobuf:"bytes,1,opt,name=asset_public_key,json=assetPublicKey,proto3" json:"asset_public_key,omitempty"` - UniqueId []byte `protobuf:"bytes,2,opt,name=unique_id,json=uniqueId,proto3" json:"unique_id,omitempty"` - OwnerCommitment []byte `protobuf:"bytes,3,opt,name=owner_commitment,json=ownerCommitment,proto3" json:"owner_commitment,omitempty"` - MinedHeight uint64 `protobuf:"varint,4,opt,name=mined_height,json=minedHeight,proto3" json:"mined_height,omitempty"` - MinedInBlock []byte `protobuf:"bytes,5,opt,name=mined_in_block,json=minedInBlock,proto3" json:"mined_in_block,omitempty"` - Features *transaction.OutputFeatures `protobuf:"bytes,6,opt,name=features,proto3" json:"features,omitempty"` - Script []byte `protobuf:"bytes,7,opt,name=script,proto3" json:"script,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListAssetRegistrationsResponse) Reset() { - *x = ListAssetRegistrationsResponse{} - mi := &file_base_node_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListAssetRegistrationsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListAssetRegistrationsResponse) ProtoMessage() {} - -func (x *ListAssetRegistrationsResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 ListAssetRegistrationsResponse.ProtoReflect.Descriptor instead. -func (*ListAssetRegistrationsResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{3} -} - -func (x *ListAssetRegistrationsResponse) GetAssetPublicKey() []byte { - if x != nil { - return x.AssetPublicKey - } - return nil -} - -func (x *ListAssetRegistrationsResponse) GetUniqueId() []byte { - if x != nil { - return x.UniqueId - } - return nil -} - -func (x *ListAssetRegistrationsResponse) GetOwnerCommitment() []byte { - if x != nil { - return x.OwnerCommitment - } - return nil -} - -func (x *ListAssetRegistrationsResponse) GetMinedHeight() uint64 { - if x != nil { - return x.MinedHeight - } - return 0 -} - -func (x *ListAssetRegistrationsResponse) GetMinedInBlock() []byte { - if x != nil { - return x.MinedInBlock - } - return nil -} - -func (x *ListAssetRegistrationsResponse) GetFeatures() *transaction.OutputFeatures { - if x != nil { - return x.Features - } - return nil -} - -func (x *ListAssetRegistrationsResponse) GetScript() []byte { - if x != nil { - return x.Script - } - return nil -} - -type GetTokensRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - AssetPublicKey []byte `protobuf:"bytes,1,opt,name=asset_public_key,json=assetPublicKey,proto3" json:"asset_public_key,omitempty"` - // Optionally get a set of specific unique_ids - UniqueIds [][]byte `protobuf:"bytes,2,rep,name=unique_ids,json=uniqueIds,proto3" json:"unique_ids,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetTokensRequest) Reset() { - *x = GetTokensRequest{} - mi := &file_base_node_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetTokensRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetTokensRequest) ProtoMessage() {} - -func (x *GetTokensRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 GetTokensRequest.ProtoReflect.Descriptor instead. -func (*GetTokensRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{4} -} - -func (x *GetTokensRequest) GetAssetPublicKey() []byte { - if x != nil { - return x.AssetPublicKey - } - return nil -} - -func (x *GetTokensRequest) GetUniqueIds() [][]byte { - if x != nil { - return x.UniqueIds - } - return nil -} - -type GetTokensResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - UniqueId []byte `protobuf:"bytes,1,opt,name=unique_id,json=uniqueId,proto3" json:"unique_id,omitempty"` - AssetPublicKey []byte `protobuf:"bytes,2,opt,name=asset_public_key,json=assetPublicKey,proto3" json:"asset_public_key,omitempty"` - OwnerCommitment []byte `protobuf:"bytes,3,opt,name=owner_commitment,json=ownerCommitment,proto3" json:"owner_commitment,omitempty"` - MinedInBlock []byte `protobuf:"bytes,4,opt,name=mined_in_block,json=minedInBlock,proto3" json:"mined_in_block,omitempty"` - MinedHeight uint64 `protobuf:"varint,5,opt,name=mined_height,json=minedHeight,proto3" json:"mined_height,omitempty"` - Features *transaction.OutputFeatures `protobuf:"bytes,6,opt,name=features,proto3" json:"features,omitempty"` - Script []byte `protobuf:"bytes,7,opt,name=script,proto3" json:"script,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetTokensResponse) Reset() { - *x = GetTokensResponse{} - mi := &file_base_node_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetTokensResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetTokensResponse) ProtoMessage() {} - -func (x *GetTokensResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 GetTokensResponse.ProtoReflect.Descriptor instead. -func (*GetTokensResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{5} -} - -func (x *GetTokensResponse) GetUniqueId() []byte { - if x != nil { - return x.UniqueId - } - return nil -} - -func (x *GetTokensResponse) GetAssetPublicKey() []byte { - if x != nil { - return x.AssetPublicKey - } - return nil -} - -func (x *GetTokensResponse) GetOwnerCommitment() []byte { - if x != nil { - return x.OwnerCommitment - } - return nil -} - -func (x *GetTokensResponse) GetMinedInBlock() []byte { - if x != nil { - return x.MinedInBlock - } - return nil -} - -func (x *GetTokensResponse) GetMinedHeight() uint64 { - if x != nil { - return x.MinedHeight - } - return 0 -} - -func (x *GetTokensResponse) GetFeatures() *transaction.OutputFeatures { - if x != nil { - return x.Features - } - return nil -} - -func (x *GetTokensResponse) GetScript() []byte { - if x != nil { - return x.Script - } - return nil -} - -type SubmitBlockResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - BlockHash []byte `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubmitBlockResponse) Reset() { - *x = SubmitBlockResponse{} - mi := &file_base_node_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubmitBlockResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubmitBlockResponse) ProtoMessage() {} - -func (x *SubmitBlockResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 SubmitBlockResponse.ProtoReflect.Descriptor instead. -func (*SubmitBlockResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{6} -} - -func (x *SubmitBlockResponse) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -type BlockBlobRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - HeaderBlob []byte `protobuf:"bytes,1,opt,name=header_blob,json=headerBlob,proto3" json:"header_blob,omitempty"` - BodyBlob []byte `protobuf:"bytes,2,opt,name=body_blob,json=bodyBlob,proto3" json:"body_blob,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BlockBlobRequest) Reset() { - *x = BlockBlobRequest{} - mi := &file_base_node_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BlockBlobRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockBlobRequest) ProtoMessage() {} - -func (x *BlockBlobRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 BlockBlobRequest.ProtoReflect.Descriptor instead. -func (*BlockBlobRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{7} -} - -func (x *BlockBlobRequest) GetHeaderBlob() []byte { - if x != nil { - return x.HeaderBlob - } - return nil -} - -func (x *BlockBlobRequest) GetBodyBlob() []byte { - if x != nil { - return x.BodyBlob - } - return nil -} - -// / return type of GetTipInfo -type TipInfoResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Metadata *MetaData `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` - InitialSyncAchieved bool `protobuf:"varint,2,opt,name=initial_sync_achieved,json=initialSyncAchieved,proto3" json:"initial_sync_achieved,omitempty"` - BaseNodeState BaseNodeState `protobuf:"varint,3,opt,name=base_node_state,json=baseNodeState,proto3,enum=tari.rpc.BaseNodeState" json:"base_node_state,omitempty"` - FailedCheckpoints bool `protobuf:"varint,4,opt,name=failed_checkpoints,json=failedCheckpoints,proto3" json:"failed_checkpoints,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TipInfoResponse) Reset() { - *x = TipInfoResponse{} - mi := &file_base_node_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TipInfoResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TipInfoResponse) ProtoMessage() {} - -func (x *TipInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_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 TipInfoResponse.ProtoReflect.Descriptor instead. -func (*TipInfoResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{8} -} - -func (x *TipInfoResponse) GetMetadata() *MetaData { - if x != nil { - return x.Metadata - } - return nil -} - -func (x *TipInfoResponse) GetInitialSyncAchieved() bool { - if x != nil { - return x.InitialSyncAchieved - } - return false -} - -func (x *TipInfoResponse) GetBaseNodeState() BaseNodeState { - if x != nil { - return x.BaseNodeState - } - return BaseNodeState_START_UP -} - -func (x *TipInfoResponse) GetFailedCheckpoints() bool { - if x != nil { - return x.FailedCheckpoints - } - return false -} - -// / return type of GetNewBlockTemplate -type NewBlockTemplateResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - NewBlockTemplate *block.NewBlockTemplate `protobuf:"bytes,1,opt,name=new_block_template,json=newBlockTemplate,proto3" json:"new_block_template,omitempty"` - InitialSyncAchieved bool `protobuf:"varint,3,opt,name=initial_sync_achieved,json=initialSyncAchieved,proto3" json:"initial_sync_achieved,omitempty"` - MinerData *MinerData `protobuf:"bytes,4,opt,name=miner_data,json=minerData,proto3" json:"miner_data,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *NewBlockTemplateResponse) Reset() { - *x = NewBlockTemplateResponse{} - mi := &file_base_node_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *NewBlockTemplateResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NewBlockTemplateResponse) ProtoMessage() {} - -func (x *NewBlockTemplateResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[9] - 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 NewBlockTemplateResponse.ProtoReflect.Descriptor instead. -func (*NewBlockTemplateResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{9} -} - -func (x *NewBlockTemplateResponse) GetNewBlockTemplate() *block.NewBlockTemplate { - if x != nil { - return x.NewBlockTemplate - } - return nil -} - -func (x *NewBlockTemplateResponse) GetInitialSyncAchieved() bool { - if x != nil { - return x.InitialSyncAchieved - } - return false -} - -func (x *NewBlockTemplateResponse) GetMinerData() *MinerData { - if x != nil { - return x.MinerData - } - return nil -} - -// / return type of NewBlockTemplateRequest -type NewBlockTemplateRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Algo *block.PowAlgo `protobuf:"bytes,1,opt,name=algo,proto3" json:"algo,omitempty"` - // This field should be moved to optional once optional keyword is standard - MaxWeight uint64 `protobuf:"varint,2,opt,name=max_weight,json=maxWeight,proto3" json:"max_weight,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *NewBlockTemplateRequest) Reset() { - *x = NewBlockTemplateRequest{} - mi := &file_base_node_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *NewBlockTemplateRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NewBlockTemplateRequest) ProtoMessage() {} - -func (x *NewBlockTemplateRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[10] - 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 NewBlockTemplateRequest.ProtoReflect.Descriptor instead. -func (*NewBlockTemplateRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{10} -} - -func (x *NewBlockTemplateRequest) GetAlgo() *block.PowAlgo { - if x != nil { - return x.Algo - } - return nil -} - -func (x *NewBlockTemplateRequest) GetMaxWeight() uint64 { - if x != nil { - return x.MaxWeight - } - return 0 -} - -// / return type of NewBlockTemplateRequest -type GetNewBlockTemplateWithCoinbasesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Algo *block.PowAlgo `protobuf:"bytes,1,opt,name=algo,proto3" json:"algo,omitempty"` - // This field should be moved to optional once optional keyword is standard - MaxWeight uint64 `protobuf:"varint,2,opt,name=max_weight,json=maxWeight,proto3" json:"max_weight,omitempty"` - Coinbases []*NewBlockCoinbase `protobuf:"bytes,3,rep,name=coinbases,proto3" json:"coinbases,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNewBlockTemplateWithCoinbasesRequest) Reset() { - *x = GetNewBlockTemplateWithCoinbasesRequest{} - mi := &file_base_node_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNewBlockTemplateWithCoinbasesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNewBlockTemplateWithCoinbasesRequest) ProtoMessage() {} - -func (x *GetNewBlockTemplateWithCoinbasesRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[11] - 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 GetNewBlockTemplateWithCoinbasesRequest.ProtoReflect.Descriptor instead. -func (*GetNewBlockTemplateWithCoinbasesRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{11} -} - -func (x *GetNewBlockTemplateWithCoinbasesRequest) GetAlgo() *block.PowAlgo { - if x != nil { - return x.Algo - } - return nil -} - -func (x *GetNewBlockTemplateWithCoinbasesRequest) GetMaxWeight() uint64 { - if x != nil { - return x.MaxWeight - } - return 0 -} - -func (x *GetNewBlockTemplateWithCoinbasesRequest) GetCoinbases() []*NewBlockCoinbase { - if x != nil { - return x.Coinbases - } - return nil -} - -// / request type of GetNewBlockWithCoinbasesRequest -type GetNewBlockWithCoinbasesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - NewTemplate *block.NewBlockTemplate `protobuf:"bytes,1,opt,name=new_template,json=newTemplate,proto3" json:"new_template,omitempty"` - Coinbases []*NewBlockCoinbase `protobuf:"bytes,2,rep,name=coinbases,proto3" json:"coinbases,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNewBlockWithCoinbasesRequest) Reset() { - *x = GetNewBlockWithCoinbasesRequest{} - mi := &file_base_node_proto_msgTypes[12] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNewBlockWithCoinbasesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNewBlockWithCoinbasesRequest) ProtoMessage() {} - -func (x *GetNewBlockWithCoinbasesRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[12] - 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 GetNewBlockWithCoinbasesRequest.ProtoReflect.Descriptor instead. -func (*GetNewBlockWithCoinbasesRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{12} -} - -func (x *GetNewBlockWithCoinbasesRequest) GetNewTemplate() *block.NewBlockTemplate { - if x != nil { - return x.NewTemplate - } - return nil -} - -func (x *GetNewBlockWithCoinbasesRequest) GetCoinbases() []*NewBlockCoinbase { - if x != nil { - return x.Coinbases - } - return nil -} - -type NewBlockCoinbase struct { - state protoimpl.MessageState `protogen:"open.v1"` - Address string `protobuf:"bytes,1,opt,name=address,proto3" json:"address,omitempty"` - Value uint64 `protobuf:"varint,2,opt,name=value,proto3" json:"value,omitempty"` - StealthPayment bool `protobuf:"varint,3,opt,name=stealth_payment,json=stealthPayment,proto3" json:"stealth_payment,omitempty"` - RevealedValueProof bool `protobuf:"varint,4,opt,name=revealed_value_proof,json=revealedValueProof,proto3" json:"revealed_value_proof,omitempty"` - CoinbaseExtra []byte `protobuf:"bytes,5,opt,name=coinbase_extra,json=coinbaseExtra,proto3" json:"coinbase_extra,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *NewBlockCoinbase) Reset() { - *x = NewBlockCoinbase{} - mi := &file_base_node_proto_msgTypes[13] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *NewBlockCoinbase) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NewBlockCoinbase) ProtoMessage() {} - -func (x *NewBlockCoinbase) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[13] - 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 NewBlockCoinbase.ProtoReflect.Descriptor instead. -func (*NewBlockCoinbase) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{13} -} - -func (x *NewBlockCoinbase) GetAddress() string { - if x != nil { - return x.Address - } - return "" -} - -func (x *NewBlockCoinbase) GetValue() uint64 { - if x != nil { - return x.Value - } - return 0 -} - -func (x *NewBlockCoinbase) GetStealthPayment() bool { - if x != nil { - return x.StealthPayment - } - return false -} - -func (x *NewBlockCoinbase) GetRevealedValueProof() bool { - if x != nil { - return x.RevealedValueProof - } - return false -} - -func (x *NewBlockCoinbase) GetCoinbaseExtra() []byte { - if x != nil { - return x.CoinbaseExtra - } - return nil -} - -// Network difficulty response -type NetworkDifficultyResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Difficulty uint64 `protobuf:"varint,1,opt,name=difficulty,proto3" json:"difficulty,omitempty"` - EstimatedHashRate uint64 `protobuf:"varint,2,opt,name=estimated_hash_rate,json=estimatedHashRate,proto3" json:"estimated_hash_rate,omitempty"` - Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` - Timestamp uint64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - PowAlgo uint64 `protobuf:"varint,5,opt,name=pow_algo,json=powAlgo,proto3" json:"pow_algo,omitempty"` - Sha3XEstimatedHashRate uint64 `protobuf:"varint,6,opt,name=sha3x_estimated_hash_rate,json=sha3xEstimatedHashRate,proto3" json:"sha3x_estimated_hash_rate,omitempty"` - MoneroRandomxEstimatedHashRate uint64 `protobuf:"varint,7,opt,name=monero_randomx_estimated_hash_rate,json=moneroRandomxEstimatedHashRate,proto3" json:"monero_randomx_estimated_hash_rate,omitempty"` - TariRandomxEstimatedHashRate uint64 `protobuf:"varint,10,opt,name=tari_randomx_estimated_hash_rate,json=tariRandomxEstimatedHashRate,proto3" json:"tari_randomx_estimated_hash_rate,omitempty"` - NumCoinbases uint64 `protobuf:"varint,8,opt,name=num_coinbases,json=numCoinbases,proto3" json:"num_coinbases,omitempty"` - CoinbaseExtras [][]byte `protobuf:"bytes,9,rep,name=coinbase_extras,json=coinbaseExtras,proto3" json:"coinbase_extras,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *NetworkDifficultyResponse) Reset() { - *x = NetworkDifficultyResponse{} - mi := &file_base_node_proto_msgTypes[14] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *NetworkDifficultyResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*NetworkDifficultyResponse) ProtoMessage() {} - -func (x *NetworkDifficultyResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[14] - 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 NetworkDifficultyResponse.ProtoReflect.Descriptor instead. -func (*NetworkDifficultyResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{14} -} - -func (x *NetworkDifficultyResponse) GetDifficulty() uint64 { - if x != nil { - return x.Difficulty - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetEstimatedHashRate() uint64 { - if x != nil { - return x.EstimatedHashRate - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetPowAlgo() uint64 { - if x != nil { - return x.PowAlgo - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetSha3XEstimatedHashRate() uint64 { - if x != nil { - return x.Sha3XEstimatedHashRate - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetMoneroRandomxEstimatedHashRate() uint64 { - if x != nil { - return x.MoneroRandomxEstimatedHashRate - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetTariRandomxEstimatedHashRate() uint64 { - if x != nil { - return x.TariRandomxEstimatedHashRate - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetNumCoinbases() uint64 { - if x != nil { - return x.NumCoinbases - } - return 0 -} - -func (x *NetworkDifficultyResponse) GetCoinbaseExtras() [][]byte { - if x != nil { - return x.CoinbaseExtras - } - return nil -} - -// A generic single value response for a specific height -type ValueAtHeightResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // uint64 circulating_supply = 1; // No longer used - // uint64 spendable_supply = 2; // No longer used - Height uint64 `protobuf:"varint,3,opt,name=height,proto3" json:"height,omitempty"` - MinedRewards uint64 `protobuf:"varint,4,opt,name=mined_rewards,json=minedRewards,proto3" json:"mined_rewards,omitempty"` - SpendableRewards uint64 `protobuf:"varint,5,opt,name=spendable_rewards,json=spendableRewards,proto3" json:"spendable_rewards,omitempty"` - SpendablePreMine uint64 `protobuf:"varint,6,opt,name=spendable_pre_mine,json=spendablePreMine,proto3" json:"spendable_pre_mine,omitempty"` - TotalSpendable uint64 `protobuf:"varint,7,opt,name=total_spendable,json=totalSpendable,proto3" json:"total_spendable,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ValueAtHeightResponse) Reset() { - *x = ValueAtHeightResponse{} - mi := &file_base_node_proto_msgTypes[15] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ValueAtHeightResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ValueAtHeightResponse) ProtoMessage() {} - -func (x *ValueAtHeightResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[15] - 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 ValueAtHeightResponse.ProtoReflect.Descriptor instead. -func (*ValueAtHeightResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{15} -} - -func (x *ValueAtHeightResponse) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *ValueAtHeightResponse) GetMinedRewards() uint64 { - if x != nil { - return x.MinedRewards - } - return 0 -} - -func (x *ValueAtHeightResponse) GetSpendableRewards() uint64 { - if x != nil { - return x.SpendableRewards - } - return 0 -} - -func (x *ValueAtHeightResponse) GetSpendablePreMine() uint64 { - if x != nil { - return x.SpendablePreMine - } - return 0 -} - -func (x *ValueAtHeightResponse) GetTotalSpendable() uint64 { - if x != nil { - return x.TotalSpendable - } - return 0 -} - -// A generic uint value -type IntegerValue struct { - state protoimpl.MessageState `protogen:"open.v1"` - Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *IntegerValue) Reset() { - *x = IntegerValue{} - mi := &file_base_node_proto_msgTypes[16] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *IntegerValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*IntegerValue) ProtoMessage() {} - -func (x *IntegerValue) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[16] - 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 IntegerValue.ProtoReflect.Descriptor instead. -func (*IntegerValue) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{16} -} - -func (x *IntegerValue) GetValue() uint64 { - if x != nil { - return x.Value - } - return 0 -} - -// A generic String value -type StringValue struct { - state protoimpl.MessageState `protogen:"open.v1"` - Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *StringValue) Reset() { - *x = StringValue{} - mi := &file_base_node_proto_msgTypes[17] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *StringValue) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*StringValue) ProtoMessage() {} - -func (x *StringValue) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[17] - 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 StringValue.ProtoReflect.Descriptor instead. -func (*StringValue) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{17} -} - -func (x *StringValue) GetValue() string { - if x != nil { - return x.Value - } - return "" -} - -// / GetBlockSize / GetBlockFees Request -// / Either the starting and ending heights OR the from_tip param must be specified -type BlockGroupRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The height from the chain tip (optional) - FromTip uint64 `protobuf:"varint,1,opt,name=from_tip,json=fromTip,proto3" json:"from_tip,omitempty"` - // The starting height (optional) - StartHeight uint64 `protobuf:"varint,2,opt,name=start_height,json=startHeight,proto3" json:"start_height,omitempty"` - // The ending height (optional) - EndHeight uint64 `protobuf:"varint,3,opt,name=end_height,json=endHeight,proto3" json:"end_height,omitempty"` - // / The type of calculation required (optional) - // / Defaults to median - // / median, mean, quartile, quantile - CalcType CalcType `protobuf:"varint,4,opt,name=calc_type,json=calcType,proto3,enum=tari.rpc.CalcType" json:"calc_type,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BlockGroupRequest) Reset() { - *x = BlockGroupRequest{} - mi := &file_base_node_proto_msgTypes[18] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BlockGroupRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockGroupRequest) ProtoMessage() {} - -func (x *BlockGroupRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[18] - 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 BlockGroupRequest.ProtoReflect.Descriptor instead. -func (*BlockGroupRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{18} -} - -func (x *BlockGroupRequest) GetFromTip() uint64 { - if x != nil { - return x.FromTip - } - return 0 -} - -func (x *BlockGroupRequest) GetStartHeight() uint64 { - if x != nil { - return x.StartHeight - } - return 0 -} - -func (x *BlockGroupRequest) GetEndHeight() uint64 { - if x != nil { - return x.EndHeight - } - return 0 -} - -func (x *BlockGroupRequest) GetCalcType() CalcType { - if x != nil { - return x.CalcType - } - return CalcType_MEAN -} - -// / GetBlockSize / GetBlockFees Response -type BlockGroupResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Value []float64 `protobuf:"fixed64,1,rep,packed,name=value,proto3" json:"value,omitempty"` - CalcType CalcType `protobuf:"varint,2,opt,name=calc_type,json=calcType,proto3,enum=tari.rpc.CalcType" json:"calc_type,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BlockGroupResponse) Reset() { - *x = BlockGroupResponse{} - mi := &file_base_node_proto_msgTypes[19] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BlockGroupResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockGroupResponse) ProtoMessage() {} - -func (x *BlockGroupResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[19] - 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 BlockGroupResponse.ProtoReflect.Descriptor instead. -func (*BlockGroupResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{19} -} - -func (x *BlockGroupResponse) GetValue() []float64 { - if x != nil { - return x.Value - } - return nil -} - -func (x *BlockGroupResponse) GetCalcType() CalcType { - if x != nil { - return x.CalcType - } - return CalcType_MEAN -} - -// 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 -type HeightRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The height from the chain tip (optional) - FromTip uint64 `protobuf:"varint,1,opt,name=from_tip,json=fromTip,proto3" json:"from_tip,omitempty"` - // The starting height (optional) - StartHeight uint64 `protobuf:"varint,2,opt,name=start_height,json=startHeight,proto3" json:"start_height,omitempty"` - // The ending height (optional) - EndHeight uint64 `protobuf:"varint,3,opt,name=end_height,json=endHeight,proto3" json:"end_height,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *HeightRequest) Reset() { - *x = HeightRequest{} - mi := &file_base_node_proto_msgTypes[20] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *HeightRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*HeightRequest) ProtoMessage() {} - -func (x *HeightRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[20] - 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 HeightRequest.ProtoReflect.Descriptor instead. -func (*HeightRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{20} -} - -func (x *HeightRequest) GetFromTip() uint64 { - if x != nil { - return x.FromTip - } - return 0 -} - -func (x *HeightRequest) GetStartHeight() uint64 { - if x != nil { - return x.StartHeight - } - return 0 -} - -func (x *HeightRequest) GetEndHeight() uint64 { - if x != nil { - return x.EndHeight - } - return 0 -} - -// The return type of the rpc GetBlockTiming -type BlockTimingResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Max uint64 `protobuf:"varint,1,opt,name=max,proto3" json:"max,omitempty"` - Min uint64 `protobuf:"varint,2,opt,name=min,proto3" json:"min,omitempty"` - Avg float64 `protobuf:"fixed64,3,opt,name=avg,proto3" json:"avg,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BlockTimingResponse) Reset() { - *x = BlockTimingResponse{} - mi := &file_base_node_proto_msgTypes[21] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BlockTimingResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockTimingResponse) ProtoMessage() {} - -func (x *BlockTimingResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[21] - 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 BlockTimingResponse.ProtoReflect.Descriptor instead. -func (*BlockTimingResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{21} -} - -func (x *BlockTimingResponse) GetMax() uint64 { - if x != nil { - return x.Max - } - return 0 -} - -func (x *BlockTimingResponse) GetMin() uint64 { - if x != nil { - return x.Min - } - return 0 -} - -func (x *BlockTimingResponse) GetAvg() float64 { - if x != nil { - return x.Avg - } - return 0 -} - -// Request that returns a header based by hash -type GetHeaderByHashRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The hash of the block header - Hash []byte `protobuf:"bytes,1,opt,name=hash,proto3" json:"hash,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetHeaderByHashRequest) Reset() { - *x = GetHeaderByHashRequest{} - mi := &file_base_node_proto_msgTypes[22] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetHeaderByHashRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetHeaderByHashRequest) ProtoMessage() {} - -func (x *GetHeaderByHashRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[22] - 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 GetHeaderByHashRequest.ProtoReflect.Descriptor instead. -func (*GetHeaderByHashRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{22} -} - -func (x *GetHeaderByHashRequest) GetHash() []byte { - if x != nil { - return x.Hash - } - return nil -} - -type BlockHeaderResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The block header - Header *block.BlockHeader `protobuf:"bytes,1,opt,name=header,proto3" json:"header,omitempty"` - // The number of blocks from the tip of this block (a.k.a depth) - Confirmations uint64 `protobuf:"varint,2,opt,name=confirmations,proto3" json:"confirmations,omitempty"` - // The block reward i.e mining reward + fees - Reward uint64 `protobuf:"varint,3,opt,name=reward,proto3" json:"reward,omitempty"` - // Achieved difficulty - Difficulty uint64 `protobuf:"varint,4,opt,name=difficulty,proto3" json:"difficulty,omitempty"` - // The number of transactions contained in the block - NumTransactions uint32 `protobuf:"varint,5,opt,name=num_transactions,json=numTransactions,proto3" json:"num_transactions,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BlockHeaderResponse) Reset() { - *x = BlockHeaderResponse{} - mi := &file_base_node_proto_msgTypes[23] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BlockHeaderResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockHeaderResponse) ProtoMessage() {} - -func (x *BlockHeaderResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[23] - 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 BlockHeaderResponse.ProtoReflect.Descriptor instead. -func (*BlockHeaderResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{23} -} - -func (x *BlockHeaderResponse) GetHeader() *block.BlockHeader { - if x != nil { - return x.Header - } - return nil -} - -func (x *BlockHeaderResponse) GetConfirmations() uint64 { - if x != nil { - return x.Confirmations - } - return 0 -} - -func (x *BlockHeaderResponse) GetReward() uint64 { - if x != nil { - return x.Reward - } - return 0 -} - -func (x *BlockHeaderResponse) GetDifficulty() uint64 { - if x != nil { - return x.Difficulty - } - return 0 -} - -func (x *BlockHeaderResponse) GetNumTransactions() uint32 { - if x != nil { - return x.NumTransactions - } - return 0 -} - -// 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. -type ListHeadersRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // 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. - FromHeight uint64 `protobuf:"varint,1,opt,name=from_height,json=fromHeight,proto3" json:"from_height,omitempty"` - // The number of headers to return. If not specified, it will default to 10 - NumHeaders uint64 `protobuf:"varint,2,opt,name=num_headers,json=numHeaders,proto3" json:"num_headers,omitempty"` - // 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 `protobuf:"varint,3,opt,name=sorting,proto3,enum=tari.rpc.Sorting" json:"sorting,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ListHeadersRequest) Reset() { - *x = ListHeadersRequest{} - mi := &file_base_node_proto_msgTypes[24] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ListHeadersRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ListHeadersRequest) ProtoMessage() {} - -func (x *ListHeadersRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[24] - 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 ListHeadersRequest.ProtoReflect.Descriptor instead. -func (*ListHeadersRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{24} -} - -func (x *ListHeadersRequest) GetFromHeight() uint64 { - if x != nil { - return x.FromHeight - } - return 0 -} - -func (x *ListHeadersRequest) GetNumHeaders() uint64 { - if x != nil { - return x.NumHeaders - } - return 0 -} - -func (x *ListHeadersRequest) GetSorting() Sorting { - if x != nil { - return x.Sorting - } - return Sorting_SORTING_DESC -} - -// 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. -type GetBlocksRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Heights []uint64 `protobuf:"varint,1,rep,packed,name=heights,proto3" json:"heights,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetBlocksRequest) Reset() { - *x = GetBlocksRequest{} - mi := &file_base_node_proto_msgTypes[25] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetBlocksRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetBlocksRequest) ProtoMessage() {} - -func (x *GetBlocksRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[25] - 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 GetBlocksRequest.ProtoReflect.Descriptor instead. -func (*GetBlocksRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{25} -} - -func (x *GetBlocksRequest) GetHeights() []uint64 { - if x != nil { - return x.Heights - } - return nil -} - -// The return type of the rpc GetBlocks. Blocks are not guaranteed to be returned in the order requested. -type GetBlocksResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Blocks []*block.HistoricalBlock `protobuf:"bytes,1,rep,name=blocks,proto3" json:"blocks,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetBlocksResponse) Reset() { - *x = GetBlocksResponse{} - mi := &file_base_node_proto_msgTypes[26] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetBlocksResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetBlocksResponse) ProtoMessage() {} - -func (x *GetBlocksResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[26] - 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 GetBlocksResponse.ProtoReflect.Descriptor instead. -func (*GetBlocksResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{26} -} - -func (x *GetBlocksResponse) GetBlocks() []*block.HistoricalBlock { - if x != nil { - return x.Blocks - } - return nil -} - -type MetaData struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The current chain height, or the block number of the longest valid chain, or `None` if there is no chain - BestBlockHeight uint64 `protobuf:"varint,1,opt,name=best_block_height,json=bestBlockHeight,proto3" json:"best_block_height,omitempty"` - // The block hash of the current tip of the longest valid chain, or `None` for an empty chain - BestBlockHash []byte `protobuf:"bytes,2,opt,name=best_block_hash,json=bestBlockHash,proto3" json:"best_block_hash,omitempty"` - // The current geometric mean of the pow of the chain tip, or `None` if there is no chain - AccumulatedDifficulty []byte `protobuf:"bytes,5,opt,name=accumulated_difficulty,json=accumulatedDifficulty,proto3" json:"accumulated_difficulty,omitempty"` - // 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. - PrunedHeight uint64 `protobuf:"varint,6,opt,name=pruned_height,json=prunedHeight,proto3" json:"pruned_height,omitempty"` - Timestamp uint64 `protobuf:"varint,7,opt,name=timestamp,proto3" json:"timestamp,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MetaData) Reset() { - *x = MetaData{} - mi := &file_base_node_proto_msgTypes[27] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MetaData) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MetaData) ProtoMessage() {} - -func (x *MetaData) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[27] - 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 MetaData.ProtoReflect.Descriptor instead. -func (*MetaData) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{27} -} - -func (x *MetaData) GetBestBlockHeight() uint64 { - if x != nil { - return x.BestBlockHeight - } - return 0 -} - -func (x *MetaData) GetBestBlockHash() []byte { - if x != nil { - return x.BestBlockHash - } - return nil -} - -func (x *MetaData) GetAccumulatedDifficulty() []byte { - if x != nil { - return x.AccumulatedDifficulty - } - return nil -} - -func (x *MetaData) GetPrunedHeight() uint64 { - if x != nil { - return x.PrunedHeight - } - return 0 -} - -func (x *MetaData) GetTimestamp() uint64 { - if x != nil { - return x.Timestamp - } - return 0 -} - -type SyncInfoResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TipHeight uint64 `protobuf:"varint,1,opt,name=tip_height,json=tipHeight,proto3" json:"tip_height,omitempty"` - LocalHeight uint64 `protobuf:"varint,2,opt,name=local_height,json=localHeight,proto3" json:"local_height,omitempty"` - PeerNodeId [][]byte `protobuf:"bytes,3,rep,name=peer_node_id,json=peerNodeId,proto3" json:"peer_node_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncInfoResponse) Reset() { - *x = SyncInfoResponse{} - mi := &file_base_node_proto_msgTypes[28] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncInfoResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncInfoResponse) ProtoMessage() {} - -func (x *SyncInfoResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[28] - 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 SyncInfoResponse.ProtoReflect.Descriptor instead. -func (*SyncInfoResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{28} -} - -func (x *SyncInfoResponse) GetTipHeight() uint64 { - if x != nil { - return x.TipHeight - } - return 0 -} - -func (x *SyncInfoResponse) GetLocalHeight() uint64 { - if x != nil { - return x.LocalHeight - } - return 0 -} - -func (x *SyncInfoResponse) GetPeerNodeId() [][]byte { - if x != nil { - return x.PeerNodeId - } - return nil -} - -type SyncProgressResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - TipHeight uint64 `protobuf:"varint,1,opt,name=tip_height,json=tipHeight,proto3" json:"tip_height,omitempty"` - LocalHeight uint64 `protobuf:"varint,2,opt,name=local_height,json=localHeight,proto3" json:"local_height,omitempty"` - State SyncState `protobuf:"varint,3,opt,name=state,proto3,enum=tari.rpc.SyncState" json:"state,omitempty"` - ShortDesc string `protobuf:"bytes,4,opt,name=short_desc,json=shortDesc,proto3" json:"short_desc,omitempty"` - InitialConnectedPeers uint64 `protobuf:"varint,5,opt,name=initial_connected_peers,json=initialConnectedPeers,proto3" json:"initial_connected_peers,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SyncProgressResponse) Reset() { - *x = SyncProgressResponse{} - mi := &file_base_node_proto_msgTypes[29] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SyncProgressResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SyncProgressResponse) ProtoMessage() {} - -func (x *SyncProgressResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[29] - 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 SyncProgressResponse.ProtoReflect.Descriptor instead. -func (*SyncProgressResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{29} -} - -func (x *SyncProgressResponse) GetTipHeight() uint64 { - if x != nil { - return x.TipHeight - } - return 0 -} - -func (x *SyncProgressResponse) GetLocalHeight() uint64 { - if x != nil { - return x.LocalHeight - } - return 0 -} - -func (x *SyncProgressResponse) GetState() SyncState { - if x != nil { - return x.State - } - return SyncState_STARTUP -} - -func (x *SyncProgressResponse) GetShortDesc() string { - if x != nil { - return x.ShortDesc - } - return "" -} - -func (x *SyncProgressResponse) GetInitialConnectedPeers() uint64 { - if x != nil { - return x.InitialConnectedPeers - } - return 0 -} - -// This is the message that is returned for a miner after it asks for a new block. -type GetNewBlockResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - // This is the header hash of the completed block - BlockHash []byte `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - // This is the completed block - Block *block.Block `protobuf:"bytes,2,opt,name=block,proto3" json:"block,omitempty"` - MergeMiningHash []byte `protobuf:"bytes,3,opt,name=merge_mining_hash,json=mergeMiningHash,proto3" json:"merge_mining_hash,omitempty"` - TariUniqueId []byte `protobuf:"bytes,4,opt,name=tari_unique_id,json=tariUniqueId,proto3" json:"tari_unique_id,omitempty"` - MinerData *MinerData `protobuf:"bytes,5,opt,name=miner_data,json=minerData,proto3" json:"miner_data,omitempty"` - VmKey []byte `protobuf:"bytes,6,opt,name=vm_key,json=vmKey,proto3" json:"vm_key,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNewBlockResult) Reset() { - *x = GetNewBlockResult{} - mi := &file_base_node_proto_msgTypes[30] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNewBlockResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNewBlockResult) ProtoMessage() {} - -func (x *GetNewBlockResult) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[30] - 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 GetNewBlockResult.ProtoReflect.Descriptor instead. -func (*GetNewBlockResult) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{30} -} - -func (x *GetNewBlockResult) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -func (x *GetNewBlockResult) GetBlock() *block.Block { - if x != nil { - return x.Block - } - return nil -} - -func (x *GetNewBlockResult) GetMergeMiningHash() []byte { - if x != nil { - return x.MergeMiningHash - } - return nil -} - -func (x *GetNewBlockResult) GetTariUniqueId() []byte { - if x != nil { - return x.TariUniqueId - } - return nil -} - -func (x *GetNewBlockResult) GetMinerData() *MinerData { - if x != nil { - return x.MinerData - } - return nil -} - -func (x *GetNewBlockResult) GetVmKey() []byte { - if x != nil { - return x.VmKey - } - return nil -} - -// This is the message that is returned for a miner after it asks for a new block. -type GetNewBlockBlobResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - // This is the header hash of the completed block - BlockHash []byte `protobuf:"bytes,1,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - // This is the completed block's header - Header []byte `protobuf:"bytes,2,opt,name=header,proto3" json:"header,omitempty"` - // This is the completed block's body - BlockBody []byte `protobuf:"bytes,3,opt,name=block_body,json=blockBody,proto3" json:"block_body,omitempty"` - MergeMiningHash []byte `protobuf:"bytes,4,opt,name=merge_mining_hash,json=mergeMiningHash,proto3" json:"merge_mining_hash,omitempty"` - UtxoMr []byte `protobuf:"bytes,5,opt,name=utxo_mr,json=utxoMr,proto3" json:"utxo_mr,omitempty"` - TariUniqueId []byte `protobuf:"bytes,6,opt,name=tari_unique_id,json=tariUniqueId,proto3" json:"tari_unique_id,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNewBlockBlobResult) Reset() { - *x = GetNewBlockBlobResult{} - mi := &file_base_node_proto_msgTypes[31] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNewBlockBlobResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNewBlockBlobResult) ProtoMessage() {} - -func (x *GetNewBlockBlobResult) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[31] - 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 GetNewBlockBlobResult.ProtoReflect.Descriptor instead. -func (*GetNewBlockBlobResult) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{31} -} - -func (x *GetNewBlockBlobResult) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -func (x *GetNewBlockBlobResult) GetHeader() []byte { - if x != nil { - return x.Header - } - return nil -} - -func (x *GetNewBlockBlobResult) GetBlockBody() []byte { - if x != nil { - return x.BlockBody - } - return nil -} - -func (x *GetNewBlockBlobResult) GetMergeMiningHash() []byte { - if x != nil { - return x.MergeMiningHash - } - return nil -} - -func (x *GetNewBlockBlobResult) GetUtxoMr() []byte { - if x != nil { - return x.UtxoMr - } - return nil -} - -func (x *GetNewBlockBlobResult) GetTariUniqueId() []byte { - if x != nil { - return x.TariUniqueId - } - return nil -} - -// This is mining data for the miner asking for a new block -type MinerData struct { - state protoimpl.MessageState `protogen:"open.v1"` - Algo *block.PowAlgo `protobuf:"bytes,1,opt,name=algo,proto3" json:"algo,omitempty"` - TargetDifficulty uint64 `protobuf:"varint,2,opt,name=target_difficulty,json=targetDifficulty,proto3" json:"target_difficulty,omitempty"` - Reward uint64 `protobuf:"varint,3,opt,name=reward,proto3" json:"reward,omitempty"` - // bytes merge_mining_hash =4; - TotalFees uint64 `protobuf:"varint,5,opt,name=total_fees,json=totalFees,proto3" json:"total_fees,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MinerData) Reset() { - *x = MinerData{} - mi := &file_base_node_proto_msgTypes[32] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MinerData) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MinerData) ProtoMessage() {} - -func (x *MinerData) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[32] - 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 MinerData.ProtoReflect.Descriptor instead. -func (*MinerData) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{32} -} - -func (x *MinerData) GetAlgo() *block.PowAlgo { - if x != nil { - return x.Algo - } - return nil -} - -func (x *MinerData) GetTargetDifficulty() uint64 { - if x != nil { - return x.TargetDifficulty - } - return 0 -} - -func (x *MinerData) GetReward() uint64 { - if x != nil { - return x.Reward - } - return 0 -} - -func (x *MinerData) GetTotalFees() uint64 { - if x != nil { - return x.TotalFees - } - return 0 -} - -// This is the request type for the Search Kernels rpc -type SearchKernelsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Signatures []*types.Signature `protobuf:"bytes,1,rep,name=signatures,proto3" json:"signatures,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchKernelsRequest) Reset() { - *x = SearchKernelsRequest{} - mi := &file_base_node_proto_msgTypes[33] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchKernelsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchKernelsRequest) ProtoMessage() {} - -func (x *SearchKernelsRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[33] - 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 SearchKernelsRequest.ProtoReflect.Descriptor instead. -func (*SearchKernelsRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{33} -} - -func (x *SearchKernelsRequest) GetSignatures() []*types.Signature { - if x != nil { - return x.Signatures - } - return nil -} - -// This is the request type for the Search Utxo rpc -type SearchUtxosRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Commitments [][]byte `protobuf:"bytes,1,rep,name=commitments,proto3" json:"commitments,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchUtxosRequest) Reset() { - *x = SearchUtxosRequest{} - mi := &file_base_node_proto_msgTypes[34] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchUtxosRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchUtxosRequest) ProtoMessage() {} - -func (x *SearchUtxosRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[34] - 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 SearchUtxosRequest.ProtoReflect.Descriptor instead. -func (*SearchUtxosRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{34} -} - -func (x *SearchUtxosRequest) GetCommitments() [][]byte { - if x != nil { - return x.Commitments - } - return nil -} - -type FetchMatchingUtxosRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Hashes [][]byte `protobuf:"bytes,1,rep,name=hashes,proto3" json:"hashes,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *FetchMatchingUtxosRequest) Reset() { - *x = FetchMatchingUtxosRequest{} - mi := &file_base_node_proto_msgTypes[35] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *FetchMatchingUtxosRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FetchMatchingUtxosRequest) ProtoMessage() {} - -func (x *FetchMatchingUtxosRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[35] - 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 FetchMatchingUtxosRequest.ProtoReflect.Descriptor instead. -func (*FetchMatchingUtxosRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{35} -} - -func (x *FetchMatchingUtxosRequest) GetHashes() [][]byte { - if x != nil { - return x.Hashes - } - return nil -} - -type FetchMatchingUtxosResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Output *transaction.TransactionOutput `protobuf:"bytes,1,opt,name=output,proto3" json:"output,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *FetchMatchingUtxosResponse) Reset() { - *x = FetchMatchingUtxosResponse{} - mi := &file_base_node_proto_msgTypes[36] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *FetchMatchingUtxosResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*FetchMatchingUtxosResponse) ProtoMessage() {} - -func (x *FetchMatchingUtxosResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[36] - 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 FetchMatchingUtxosResponse.ProtoReflect.Descriptor instead. -func (*FetchMatchingUtxosResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{36} -} - -func (x *FetchMatchingUtxosResponse) GetOutput() *transaction.TransactionOutput { - if x != nil { - return x.Output - } - return nil -} - -// This is the request type of the get all peers rpc call -type GetPeersResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Peer *net_work.Peer `protobuf:"bytes,1,opt,name=peer,proto3" json:"peer,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetPeersResponse) Reset() { - *x = GetPeersResponse{} - mi := &file_base_node_proto_msgTypes[37] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetPeersResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetPeersResponse) ProtoMessage() {} - -func (x *GetPeersResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[37] - 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 GetPeersResponse.ProtoReflect.Descriptor instead. -func (*GetPeersResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{37} -} - -func (x *GetPeersResponse) GetPeer() *net_work.Peer { - if x != nil { - return x.Peer - } - return nil -} - -type GetPeersRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetPeersRequest) Reset() { - *x = GetPeersRequest{} - mi := &file_base_node_proto_msgTypes[38] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetPeersRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetPeersRequest) ProtoMessage() {} - -func (x *GetPeersRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[38] - 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 GetPeersRequest.ProtoReflect.Descriptor instead. -func (*GetPeersRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{38} -} - -type SubmitTransactionRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Transaction *transaction.Transaction `protobuf:"bytes,1,opt,name=transaction,proto3" json:"transaction,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubmitTransactionRequest) Reset() { - *x = SubmitTransactionRequest{} - mi := &file_base_node_proto_msgTypes[39] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubmitTransactionRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubmitTransactionRequest) ProtoMessage() {} - -func (x *SubmitTransactionRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[39] - 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 SubmitTransactionRequest.ProtoReflect.Descriptor instead. -func (*SubmitTransactionRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{39} -} - -func (x *SubmitTransactionRequest) GetTransaction() *transaction.Transaction { - if x != nil { - return x.Transaction - } - return nil -} - -type SubmitTransactionResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result SubmitTransactionResult `protobuf:"varint,1,opt,name=result,proto3,enum=tari.rpc.SubmitTransactionResult" json:"result,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SubmitTransactionResponse) Reset() { - *x = SubmitTransactionResponse{} - mi := &file_base_node_proto_msgTypes[40] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SubmitTransactionResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SubmitTransactionResponse) ProtoMessage() {} - -func (x *SubmitTransactionResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[40] - 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 SubmitTransactionResponse.ProtoReflect.Descriptor instead. -func (*SubmitTransactionResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{40} -} - -func (x *SubmitTransactionResponse) GetResult() SubmitTransactionResult { - if x != nil { - return x.Result - } - return SubmitTransactionResult_NONE -} - -type GetMempoolTransactionsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetMempoolTransactionsRequest) Reset() { - *x = GetMempoolTransactionsRequest{} - mi := &file_base_node_proto_msgTypes[41] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetMempoolTransactionsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetMempoolTransactionsRequest) ProtoMessage() {} - -func (x *GetMempoolTransactionsRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[41] - 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 GetMempoolTransactionsRequest.ProtoReflect.Descriptor instead. -func (*GetMempoolTransactionsRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{41} -} - -type GetMempoolTransactionsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Transaction *transaction.Transaction `protobuf:"bytes,1,opt,name=transaction,proto3" json:"transaction,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetMempoolTransactionsResponse) Reset() { - *x = GetMempoolTransactionsResponse{} - mi := &file_base_node_proto_msgTypes[42] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetMempoolTransactionsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetMempoolTransactionsResponse) ProtoMessage() {} - -func (x *GetMempoolTransactionsResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[42] - 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 GetMempoolTransactionsResponse.ProtoReflect.Descriptor instead. -func (*GetMempoolTransactionsResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{42} -} - -func (x *GetMempoolTransactionsResponse) GetTransaction() *transaction.Transaction { - if x != nil { - return x.Transaction - } - return nil -} - -type TransactionStateRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - ExcessSig *types.Signature `protobuf:"bytes,1,opt,name=excess_sig,json=excessSig,proto3" json:"excess_sig,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TransactionStateRequest) Reset() { - *x = TransactionStateRequest{} - mi := &file_base_node_proto_msgTypes[43] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TransactionStateRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransactionStateRequest) ProtoMessage() {} - -func (x *TransactionStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[43] - 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 TransactionStateRequest.ProtoReflect.Descriptor instead. -func (*TransactionStateRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{43} -} - -func (x *TransactionStateRequest) GetExcessSig() *types.Signature { - if x != nil { - return x.ExcessSig - } - return nil -} - -type TransactionStateResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - Result TransactionLocation `protobuf:"varint,1,opt,name=result,proto3,enum=tari.rpc.TransactionLocation" json:"result,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TransactionStateResponse) Reset() { - *x = TransactionStateResponse{} - mi := &file_base_node_proto_msgTypes[44] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TransactionStateResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransactionStateResponse) ProtoMessage() {} - -func (x *TransactionStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[44] - 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 TransactionStateResponse.ProtoReflect.Descriptor instead. -func (*TransactionStateResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{44} -} - -func (x *TransactionStateResponse) GetResult() TransactionLocation { - if x != nil { - return x.Result - } - return TransactionLocation_UNKNOWN -} - -type MempoolStatsResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - UnconfirmedTxs uint64 `protobuf:"varint,2,opt,name=unconfirmed_txs,json=unconfirmedTxs,proto3" json:"unconfirmed_txs,omitempty"` - ReorgTxs uint64 `protobuf:"varint,3,opt,name=reorg_txs,json=reorgTxs,proto3" json:"reorg_txs,omitempty"` - UnconfirmedWeight uint64 `protobuf:"varint,4,opt,name=unconfirmed_weight,json=unconfirmedWeight,proto3" json:"unconfirmed_weight,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *MempoolStatsResponse) Reset() { - *x = MempoolStatsResponse{} - mi := &file_base_node_proto_msgTypes[45] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *MempoolStatsResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*MempoolStatsResponse) ProtoMessage() {} - -func (x *MempoolStatsResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[45] - 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 MempoolStatsResponse.ProtoReflect.Descriptor instead. -func (*MempoolStatsResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{45} -} - -func (x *MempoolStatsResponse) GetUnconfirmedTxs() uint64 { - if x != nil { - return x.UnconfirmedTxs - } - return 0 -} - -func (x *MempoolStatsResponse) GetReorgTxs() uint64 { - if x != nil { - return x.ReorgTxs - } - return 0 -} - -func (x *MempoolStatsResponse) GetUnconfirmedWeight() uint64 { - if x != nil { - return x.UnconfirmedWeight - } - return 0 -} - -type GetActiveValidatorNodesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetActiveValidatorNodesRequest) Reset() { - *x = GetActiveValidatorNodesRequest{} - mi := &file_base_node_proto_msgTypes[46] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetActiveValidatorNodesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetActiveValidatorNodesRequest) ProtoMessage() {} - -func (x *GetActiveValidatorNodesRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[46] - 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 GetActiveValidatorNodesRequest.ProtoReflect.Descriptor instead. -func (*GetActiveValidatorNodesRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{46} -} - -func (x *GetActiveValidatorNodesRequest) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -type GetActiveValidatorNodesResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - ShardKey []byte `protobuf:"bytes,1,opt,name=shard_key,json=shardKey,proto3" json:"shard_key,omitempty"` - PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetActiveValidatorNodesResponse) Reset() { - *x = GetActiveValidatorNodesResponse{} - mi := &file_base_node_proto_msgTypes[47] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetActiveValidatorNodesResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetActiveValidatorNodesResponse) ProtoMessage() {} - -func (x *GetActiveValidatorNodesResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[47] - 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 GetActiveValidatorNodesResponse.ProtoReflect.Descriptor instead. -func (*GetActiveValidatorNodesResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{47} -} - -func (x *GetActiveValidatorNodesResponse) GetShardKey() []byte { - if x != nil { - return x.ShardKey - } - return nil -} - -func (x *GetActiveValidatorNodesResponse) GetPublicKey() []byte { - if x != nil { - return x.PublicKey - } - return nil -} - -type GetShardKeyRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - PublicKey []byte `protobuf:"bytes,2,opt,name=public_key,json=publicKey,proto3" json:"public_key,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetShardKeyRequest) Reset() { - *x = GetShardKeyRequest{} - mi := &file_base_node_proto_msgTypes[48] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetShardKeyRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardKeyRequest) ProtoMessage() {} - -func (x *GetShardKeyRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[48] - 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 GetShardKeyRequest.ProtoReflect.Descriptor instead. -func (*GetShardKeyRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{48} -} - -func (x *GetShardKeyRequest) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *GetShardKeyRequest) GetPublicKey() []byte { - if x != nil { - return x.PublicKey - } - return nil -} - -type GetShardKeyResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - ShardKey []byte `protobuf:"bytes,1,opt,name=shard_key,json=shardKey,proto3" json:"shard_key,omitempty"` - Found bool `protobuf:"varint,2,opt,name=found,proto3" json:"found,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetShardKeyResponse) Reset() { - *x = GetShardKeyResponse{} - mi := &file_base_node_proto_msgTypes[49] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetShardKeyResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetShardKeyResponse) ProtoMessage() {} - -func (x *GetShardKeyResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[49] - 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 GetShardKeyResponse.ProtoReflect.Descriptor instead. -func (*GetShardKeyResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{49} -} - -func (x *GetShardKeyResponse) GetShardKey() []byte { - if x != nil { - return x.ShardKey - } - return nil -} - -func (x *GetShardKeyResponse) GetFound() bool { - if x != nil { - return x.Found - } - return false -} - -type GetTemplateRegistrationsRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - StartHash []byte `protobuf:"bytes,1,opt,name=start_hash,json=startHash,proto3" json:"start_hash,omitempty"` - Count uint64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetTemplateRegistrationsRequest) Reset() { - *x = GetTemplateRegistrationsRequest{} - mi := &file_base_node_proto_msgTypes[50] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetTemplateRegistrationsRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetTemplateRegistrationsRequest) ProtoMessage() {} - -func (x *GetTemplateRegistrationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[50] - 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 GetTemplateRegistrationsRequest.ProtoReflect.Descriptor instead. -func (*GetTemplateRegistrationsRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{50} -} - -func (x *GetTemplateRegistrationsRequest) GetStartHash() []byte { - if x != nil { - return x.StartHash - } - return nil -} - -func (x *GetTemplateRegistrationsRequest) GetCount() uint64 { - if x != nil { - return x.Count - } - return 0 -} - -type GetTemplateRegistrationResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - UtxoHash []byte `protobuf:"bytes,1,opt,name=utxo_hash,json=utxoHash,proto3" json:"utxo_hash,omitempty"` - Registration *sidechain_types.TemplateRegistration `protobuf:"bytes,2,opt,name=registration,proto3" json:"registration,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetTemplateRegistrationResponse) Reset() { - *x = GetTemplateRegistrationResponse{} - mi := &file_base_node_proto_msgTypes[51] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetTemplateRegistrationResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetTemplateRegistrationResponse) ProtoMessage() {} - -func (x *GetTemplateRegistrationResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[51] - 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 GetTemplateRegistrationResponse.ProtoReflect.Descriptor instead. -func (*GetTemplateRegistrationResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{51} -} - -func (x *GetTemplateRegistrationResponse) GetUtxoHash() []byte { - if x != nil { - return x.UtxoHash - } - return nil -} - -func (x *GetTemplateRegistrationResponse) GetRegistration() *sidechain_types.TemplateRegistration { - if x != nil { - return x.Registration - } - return nil -} - -type BlockInfo struct { - state protoimpl.MessageState `protogen:"open.v1"` - Height uint64 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"` - Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` - NextBlockHash []byte `protobuf:"bytes,3,opt,name=next_block_hash,json=nextBlockHash,proto3" json:"next_block_hash,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BlockInfo) Reset() { - *x = BlockInfo{} - mi := &file_base_node_proto_msgTypes[52] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BlockInfo) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockInfo) ProtoMessage() {} - -func (x *BlockInfo) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[52] - 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 BlockInfo.ProtoReflect.Descriptor instead. -func (*BlockInfo) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{52} -} - -func (x *BlockInfo) GetHeight() uint64 { - if x != nil { - return x.Height - } - return 0 -} - -func (x *BlockInfo) GetHash() []byte { - if x != nil { - return x.Hash - } - return nil -} - -func (x *BlockInfo) GetNextBlockHash() []byte { - if x != nil { - return x.NextBlockHash - } - return nil -} - -type GetSideChainUtxosRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - StartHash []byte `protobuf:"bytes,1,opt,name=start_hash,json=startHash,proto3" json:"start_hash,omitempty"` - Count uint64 `protobuf:"varint,2,opt,name=count,proto3" json:"count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetSideChainUtxosRequest) Reset() { - *x = GetSideChainUtxosRequest{} - mi := &file_base_node_proto_msgTypes[53] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetSideChainUtxosRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSideChainUtxosRequest) ProtoMessage() {} - -func (x *GetSideChainUtxosRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[53] - 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 GetSideChainUtxosRequest.ProtoReflect.Descriptor instead. -func (*GetSideChainUtxosRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{53} -} - -func (x *GetSideChainUtxosRequest) GetStartHash() []byte { - if x != nil { - return x.StartHash - } - return nil -} - -func (x *GetSideChainUtxosRequest) GetCount() uint64 { - if x != nil { - return x.Count - } - return 0 -} - -type GetSideChainUtxosResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - BlockInfo *BlockInfo `protobuf:"bytes,1,opt,name=block_info,json=blockInfo,proto3" json:"block_info,omitempty"` - Outputs []*transaction.TransactionOutput `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetSideChainUtxosResponse) Reset() { - *x = GetSideChainUtxosResponse{} - mi := &file_base_node_proto_msgTypes[54] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetSideChainUtxosResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetSideChainUtxosResponse) ProtoMessage() {} - -func (x *GetSideChainUtxosResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[54] - 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 GetSideChainUtxosResponse.ProtoReflect.Descriptor instead. -func (*GetSideChainUtxosResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{54} -} - -func (x *GetSideChainUtxosResponse) GetBlockInfo() *BlockInfo { - if x != nil { - return x.BlockInfo - } - return nil -} - -func (x *GetSideChainUtxosResponse) GetOutputs() []*transaction.TransactionOutput { - if x != nil { - return x.Outputs - } - return nil -} - -type GetNetworkStateRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNetworkStateRequest) Reset() { - *x = GetNetworkStateRequest{} - mi := &file_base_node_proto_msgTypes[55] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNetworkStateRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNetworkStateRequest) ProtoMessage() {} - -func (x *GetNetworkStateRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[55] - 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 GetNetworkStateRequest.ProtoReflect.Descriptor instead. -func (*GetNetworkStateRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{55} -} - -type GetNetworkStateResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // metadata - Metadata *MetaData `protobuf:"bytes,1,opt,name=metadata,proto3" json:"metadata,omitempty"` - // has the base node synced - InitialSyncAchieved bool `protobuf:"varint,2,opt,name=initial_sync_achieved,json=initialSyncAchieved,proto3" json:"initial_sync_achieved,omitempty"` - // current state of the base node - BaseNodeState BaseNodeState `protobuf:"varint,3,opt,name=base_node_state,json=baseNodeState,proto3,enum=tari.rpc.BaseNodeState" json:"base_node_state,omitempty"` - // do we have failed checkpoints - FailedCheckpoints bool `protobuf:"varint,4,opt,name=failed_checkpoints,json=failedCheckpoints,proto3" json:"failed_checkpoints,omitempty"` - // The block reward of the next tip - Reward uint64 `protobuf:"varint,5,opt,name=reward,proto3" json:"reward,omitempty"` - // estimate sha3x hash rate - Sha3XEstimatedHashRate uint64 `protobuf:"varint,6,opt,name=sha3x_estimated_hash_rate,json=sha3xEstimatedHashRate,proto3" json:"sha3x_estimated_hash_rate,omitempty"` - // estimate randomx hash rate - MoneroRandomxEstimatedHashRate uint64 `protobuf:"varint,7,opt,name=monero_randomx_estimated_hash_rate,json=moneroRandomxEstimatedHashRate,proto3" json:"monero_randomx_estimated_hash_rate,omitempty"` - TariRandomxEstimatedHashRate uint64 `protobuf:"varint,10,opt,name=tari_randomx_estimated_hash_rate,json=tariRandomxEstimatedHashRate,proto3" json:"tari_randomx_estimated_hash_rate,omitempty"` - // number of connections - NumConnections uint64 `protobuf:"varint,8,opt,name=num_connections,json=numConnections,proto3" json:"num_connections,omitempty"` - // liveness results - LivenessResults []*LivenessResult `protobuf:"bytes,9,rep,name=liveness_results,json=livenessResults,proto3" json:"liveness_results,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *GetNetworkStateResponse) Reset() { - *x = GetNetworkStateResponse{} - mi := &file_base_node_proto_msgTypes[56] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *GetNetworkStateResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*GetNetworkStateResponse) ProtoMessage() {} - -func (x *GetNetworkStateResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[56] - 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 GetNetworkStateResponse.ProtoReflect.Descriptor instead. -func (*GetNetworkStateResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{56} -} - -func (x *GetNetworkStateResponse) GetMetadata() *MetaData { - if x != nil { - return x.Metadata - } - return nil -} - -func (x *GetNetworkStateResponse) GetInitialSyncAchieved() bool { - if x != nil { - return x.InitialSyncAchieved - } - return false -} - -func (x *GetNetworkStateResponse) GetBaseNodeState() BaseNodeState { - if x != nil { - return x.BaseNodeState - } - return BaseNodeState_START_UP -} - -func (x *GetNetworkStateResponse) GetFailedCheckpoints() bool { - if x != nil { - return x.FailedCheckpoints - } - return false -} - -func (x *GetNetworkStateResponse) GetReward() uint64 { - if x != nil { - return x.Reward - } - return 0 -} - -func (x *GetNetworkStateResponse) GetSha3XEstimatedHashRate() uint64 { - if x != nil { - return x.Sha3XEstimatedHashRate - } - return 0 -} - -func (x *GetNetworkStateResponse) GetMoneroRandomxEstimatedHashRate() uint64 { - if x != nil { - return x.MoneroRandomxEstimatedHashRate - } - return 0 -} - -func (x *GetNetworkStateResponse) GetTariRandomxEstimatedHashRate() uint64 { - if x != nil { - return x.TariRandomxEstimatedHashRate - } - return 0 -} - -func (x *GetNetworkStateResponse) GetNumConnections() uint64 { - if x != nil { - return x.NumConnections - } - return 0 -} - -func (x *GetNetworkStateResponse) GetLivenessResults() []*LivenessResult { - if x != nil { - return x.LivenessResults - } - return nil -} - -type LivenessResult struct { - state protoimpl.MessageState `protogen:"open.v1"` - // node id - PeerNodeId []byte `protobuf:"bytes,1,opt,name=peer_node_id,json=peerNodeId,proto3" json:"peer_node_id,omitempty"` - // time to discover - DiscoverLatency uint64 `protobuf:"varint,2,opt,name=discover_latency,json=discoverLatency,proto3" json:"discover_latency,omitempty"` - // Dial latency - PingLatency uint64 `protobuf:"varint,3,opt,name=ping_latency,json=pingLatency,proto3" json:"ping_latency,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *LivenessResult) Reset() { - *x = LivenessResult{} - mi := &file_base_node_proto_msgTypes[57] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *LivenessResult) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*LivenessResult) ProtoMessage() {} - -func (x *LivenessResult) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[57] - 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 LivenessResult.ProtoReflect.Descriptor instead. -func (*LivenessResult) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{57} -} - -func (x *LivenessResult) GetPeerNodeId() []byte { - if x != nil { - return x.PeerNodeId - } - return nil -} - -func (x *LivenessResult) GetDiscoverLatency() uint64 { - if x != nil { - return x.DiscoverLatency - } - return 0 -} - -func (x *LivenessResult) GetPingLatency() uint64 { - if x != nil { - return x.PingLatency - } - return 0 -} - -// Request to search for outputs by payment reference -type SearchPaymentReferencesRequest struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Payment reference as hex string (64 characters) - PaymentReferenceHex []string `protobuf:"bytes,1,rep,name=payment_reference_hex,json=paymentReferenceHex,proto3" json:"payment_reference_hex,omitempty"` - PaymentReferenceBytes [][]byte `protobuf:"bytes,2,rep,name=payment_reference_bytes,json=paymentReferenceBytes,proto3" json:"payment_reference_bytes,omitempty"` - // Optional: include spent outputs in results - IncludeSpent bool `protobuf:"varint,3,opt,name=include_spent,json=includeSpent,proto3" json:"include_spent,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *SearchPaymentReferencesRequest) Reset() { - *x = SearchPaymentReferencesRequest{} - mi := &file_base_node_proto_msgTypes[58] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *SearchPaymentReferencesRequest) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SearchPaymentReferencesRequest) ProtoMessage() {} - -func (x *SearchPaymentReferencesRequest) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[58] - 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 SearchPaymentReferencesRequest.ProtoReflect.Descriptor instead. -func (*SearchPaymentReferencesRequest) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{58} -} - -func (x *SearchPaymentReferencesRequest) GetPaymentReferenceHex() []string { - if x != nil { - return x.PaymentReferenceHex - } - return nil -} - -func (x *SearchPaymentReferencesRequest) GetPaymentReferenceBytes() [][]byte { - if x != nil { - return x.PaymentReferenceBytes - } - return nil -} - -func (x *SearchPaymentReferencesRequest) GetIncludeSpent() bool { - if x != nil { - return x.IncludeSpent - } - return false -} - -// Response containing payment reference match -type PaymentReferenceResponse struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The payment reference that was found - PaymentReferenceHex string `protobuf:"bytes,1,opt,name=payment_reference_hex,json=paymentReferenceHex,proto3" json:"payment_reference_hex,omitempty"` - // Block height where the output was mined - BlockHeight uint64 `protobuf:"varint,2,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` - // Block hash where the output was mined - BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty"` - // Timestamp when the output was mined - MinedTimestamp uint64 `protobuf:"varint,4,opt,name=mined_timestamp,json=minedTimestamp,proto3" json:"mined_timestamp,omitempty"` - // Output commitment (32 bytes) - Commitment []byte `protobuf:"bytes,5,opt,name=commitment,proto3" json:"commitment,omitempty"` - // Whether this output has been spent - IsSpent bool `protobuf:"varint,6,opt,name=is_spent,json=isSpent,proto3" json:"is_spent,omitempty"` - // Height where output was spent (if spent) - SpentHeight uint64 `protobuf:"varint,7,opt,name=spent_height,json=spentHeight,proto3" json:"spent_height,omitempty"` - // Block hash where output was spent (if spent) - SpentBlockHash []byte `protobuf:"bytes,8,opt,name=spent_block_hash,json=spentBlockHash,proto3" json:"spent_block_hash,omitempty"` - // Transaction output amount will be 0 for non set a - MinValuePromise uint64 `protobuf:"varint,9,opt,name=min_value_promise,json=minValuePromise,proto3" json:"min_value_promise,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PaymentReferenceResponse) Reset() { - *x = PaymentReferenceResponse{} - mi := &file_base_node_proto_msgTypes[59] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PaymentReferenceResponse) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PaymentReferenceResponse) ProtoMessage() {} - -func (x *PaymentReferenceResponse) ProtoReflect() protoreflect.Message { - mi := &file_base_node_proto_msgTypes[59] - 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 PaymentReferenceResponse.ProtoReflect.Descriptor instead. -func (*PaymentReferenceResponse) Descriptor() ([]byte, []int) { - return file_base_node_proto_rawDescGZIP(), []int{59} -} - -func (x *PaymentReferenceResponse) GetPaymentReferenceHex() string { - if x != nil { - return x.PaymentReferenceHex - } - return "" -} - -func (x *PaymentReferenceResponse) GetBlockHeight() uint64 { - if x != nil { - return x.BlockHeight - } - return 0 -} - -func (x *PaymentReferenceResponse) GetBlockHash() []byte { - if x != nil { - return x.BlockHash - } - return nil -} - -func (x *PaymentReferenceResponse) GetMinedTimestamp() uint64 { - if x != nil { - return x.MinedTimestamp - } - return 0 -} - -func (x *PaymentReferenceResponse) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -func (x *PaymentReferenceResponse) GetIsSpent() bool { - if x != nil { - return x.IsSpent - } - return false -} - -func (x *PaymentReferenceResponse) GetSpentHeight() uint64 { - if x != nil { - return x.SpentHeight - } - return 0 -} - -func (x *PaymentReferenceResponse) GetSpentBlockHash() []byte { - if x != nil { - return x.SpentBlockHash - } - return nil -} - -func (x *PaymentReferenceResponse) GetMinValuePromise() uint64 { - if x != nil { - return x.MinValuePromise - } - return 0 -} - -var File_base_node_proto protoreflect.FileDescriptor - -const file_base_node_proto_rawDesc = "" + - "\n" + - "\x0fbase_node.proto\x12\btari.rpc\x1a\vtypes.proto\x1a\x11transaction.proto\x1a\vblock.proto\x1a\rnetwork.proto\x1a\x15sidechain_types.proto\"C\n" + - "\x17GetAssetMetadataRequest\x12(\n" + - "\x10asset_public_key\x18\x01 \x01(\fR\x0eassetPublicKey\"\x90\x02\n" + - "\x18GetAssetMetadataResponse\x12\x12\n" + - "\x04name\x18\x02 \x01(\tR\x04name\x12 \n" + - "\vdescription\x18\x03 \x01(\tR\vdescription\x12\x14\n" + - "\x05image\x18\x04 \x01(\tR\x05image\x12)\n" + - "\x10owner_commitment\x18\x05 \x01(\fR\x0fownerCommitment\x124\n" + - "\bfeatures\x18\x06 \x01(\v2\x18.tari.rpc.OutputFeaturesR\bfeatures\x12!\n" + - "\fmined_height\x18\a \x01(\x04R\vminedHeight\x12$\n" + - "\x0emined_in_block\x18\b \x01(\fR\fminedInBlock\"M\n" + - "\x1dListAssetRegistrationsRequest\x12\x16\n" + - "\x06offset\x18\x02 \x01(\x04R\x06offset\x12\x14\n" + - "\x05count\x18\x03 \x01(\x04R\x05count\"\xa9\x02\n" + - "\x1eListAssetRegistrationsResponse\x12(\n" + - "\x10asset_public_key\x18\x01 \x01(\fR\x0eassetPublicKey\x12\x1b\n" + - "\tunique_id\x18\x02 \x01(\fR\buniqueId\x12)\n" + - "\x10owner_commitment\x18\x03 \x01(\fR\x0fownerCommitment\x12!\n" + - "\fmined_height\x18\x04 \x01(\x04R\vminedHeight\x12$\n" + - "\x0emined_in_block\x18\x05 \x01(\fR\fminedInBlock\x124\n" + - "\bfeatures\x18\x06 \x01(\v2\x18.tari.rpc.OutputFeaturesR\bfeatures\x12\x16\n" + - "\x06script\x18\a \x01(\fR\x06script\"[\n" + - "\x10GetTokensRequest\x12(\n" + - "\x10asset_public_key\x18\x01 \x01(\fR\x0eassetPublicKey\x12\x1d\n" + - "\n" + - "unique_ids\x18\x02 \x03(\fR\tuniqueIds\"\x9c\x02\n" + - "\x11GetTokensResponse\x12\x1b\n" + - "\tunique_id\x18\x01 \x01(\fR\buniqueId\x12(\n" + - "\x10asset_public_key\x18\x02 \x01(\fR\x0eassetPublicKey\x12)\n" + - "\x10owner_commitment\x18\x03 \x01(\fR\x0fownerCommitment\x12$\n" + - "\x0emined_in_block\x18\x04 \x01(\fR\fminedInBlock\x12!\n" + - "\fmined_height\x18\x05 \x01(\x04R\vminedHeight\x124\n" + - "\bfeatures\x18\x06 \x01(\v2\x18.tari.rpc.OutputFeaturesR\bfeatures\x12\x16\n" + - "\x06script\x18\a \x01(\fR\x06script\"4\n" + - "\x13SubmitBlockResponse\x12\x1d\n" + - "\n" + - "block_hash\x18\x01 \x01(\fR\tblockHash\"P\n" + - "\x10BlockBlobRequest\x12\x1f\n" + - "\vheader_blob\x18\x01 \x01(\fR\n" + - "headerBlob\x12\x1b\n" + - "\tbody_blob\x18\x02 \x01(\fR\bbodyBlob\"\xe5\x01\n" + - "\x0fTipInfoResponse\x12.\n" + - "\bmetadata\x18\x01 \x01(\v2\x12.tari.rpc.MetaDataR\bmetadata\x122\n" + - "\x15initial_sync_achieved\x18\x02 \x01(\bR\x13initialSyncAchieved\x12?\n" + - "\x0fbase_node_state\x18\x03 \x01(\x0e2\x17.tari.rpc.BaseNodeStateR\rbaseNodeState\x12-\n" + - "\x12failed_checkpoints\x18\x04 \x01(\bR\x11failedCheckpoints\"\xcc\x01\n" + - "\x18NewBlockTemplateResponse\x12H\n" + - "\x12new_block_template\x18\x01 \x01(\v2\x1a.tari.rpc.NewBlockTemplateR\x10newBlockTemplate\x122\n" + - "\x15initial_sync_achieved\x18\x03 \x01(\bR\x13initialSyncAchieved\x122\n" + - "\n" + - "miner_data\x18\x04 \x01(\v2\x13.tari.rpc.MinerDataR\tminerData\"_\n" + - "\x17NewBlockTemplateRequest\x12%\n" + - "\x04algo\x18\x01 \x01(\v2\x11.tari.rpc.PowAlgoR\x04algo\x12\x1d\n" + - "\n" + - "max_weight\x18\x02 \x01(\x04R\tmaxWeight\"\xa9\x01\n" + - "'GetNewBlockTemplateWithCoinbasesRequest\x12%\n" + - "\x04algo\x18\x01 \x01(\v2\x11.tari.rpc.PowAlgoR\x04algo\x12\x1d\n" + - "\n" + - "max_weight\x18\x02 \x01(\x04R\tmaxWeight\x128\n" + - "\tcoinbases\x18\x03 \x03(\v2\x1a.tari.rpc.NewBlockCoinbaseR\tcoinbases\"\x9a\x01\n" + - "\x1fGetNewBlockWithCoinbasesRequest\x12=\n" + - "\fnew_template\x18\x01 \x01(\v2\x1a.tari.rpc.NewBlockTemplateR\vnewTemplate\x128\n" + - "\tcoinbases\x18\x02 \x03(\v2\x1a.tari.rpc.NewBlockCoinbaseR\tcoinbases\"\xc4\x01\n" + - "\x10NewBlockCoinbase\x12\x18\n" + - "\aaddress\x18\x01 \x01(\tR\aaddress\x12\x14\n" + - "\x05value\x18\x02 \x01(\x04R\x05value\x12'\n" + - "\x0fstealth_payment\x18\x03 \x01(\bR\x0estealthPayment\x120\n" + - "\x14revealed_value_proof\x18\x04 \x01(\bR\x12revealedValueProof\x12%\n" + - "\x0ecoinbase_extra\x18\x05 \x01(\fR\rcoinbaseExtra\"\xd9\x03\n" + - "\x19NetworkDifficultyResponse\x12\x1e\n" + - "\n" + - "difficulty\x18\x01 \x01(\x04R\n" + - "difficulty\x12.\n" + - "\x13estimated_hash_rate\x18\x02 \x01(\x04R\x11estimatedHashRate\x12\x16\n" + - "\x06height\x18\x03 \x01(\x04R\x06height\x12\x1c\n" + - "\ttimestamp\x18\x04 \x01(\x04R\ttimestamp\x12\x19\n" + - "\bpow_algo\x18\x05 \x01(\x04R\apowAlgo\x129\n" + - "\x19sha3x_estimated_hash_rate\x18\x06 \x01(\x04R\x16sha3xEstimatedHashRate\x12J\n" + - "\"monero_randomx_estimated_hash_rate\x18\a \x01(\x04R\x1emoneroRandomxEstimatedHashRate\x12F\n" + - " tari_randomx_estimated_hash_rate\x18\n" + - " \x01(\x04R\x1ctariRandomxEstimatedHashRate\x12#\n" + - "\rnum_coinbases\x18\b \x01(\x04R\fnumCoinbases\x12'\n" + - "\x0fcoinbase_extras\x18\t \x03(\fR\x0ecoinbaseExtras\"\xd8\x01\n" + - "\x15ValueAtHeightResponse\x12\x16\n" + - "\x06height\x18\x03 \x01(\x04R\x06height\x12#\n" + - "\rmined_rewards\x18\x04 \x01(\x04R\fminedRewards\x12+\n" + - "\x11spendable_rewards\x18\x05 \x01(\x04R\x10spendableRewards\x12,\n" + - "\x12spendable_pre_mine\x18\x06 \x01(\x04R\x10spendablePreMine\x12'\n" + - "\x0ftotal_spendable\x18\a \x01(\x04R\x0etotalSpendable\"$\n" + - "\fIntegerValue\x12\x14\n" + - "\x05value\x18\x01 \x01(\x04R\x05value\"#\n" + - "\vStringValue\x12\x14\n" + - "\x05value\x18\x01 \x01(\tR\x05value\"\xa1\x01\n" + - "\x11BlockGroupRequest\x12\x19\n" + - "\bfrom_tip\x18\x01 \x01(\x04R\afromTip\x12!\n" + - "\fstart_height\x18\x02 \x01(\x04R\vstartHeight\x12\x1d\n" + - "\n" + - "end_height\x18\x03 \x01(\x04R\tendHeight\x12/\n" + - "\tcalc_type\x18\x04 \x01(\x0e2\x12.tari.rpc.CalcTypeR\bcalcType\"[\n" + - "\x12BlockGroupResponse\x12\x14\n" + - "\x05value\x18\x01 \x03(\x01R\x05value\x12/\n" + - "\tcalc_type\x18\x02 \x01(\x0e2\x12.tari.rpc.CalcTypeR\bcalcType\"l\n" + - "\rHeightRequest\x12\x19\n" + - "\bfrom_tip\x18\x01 \x01(\x04R\afromTip\x12!\n" + - "\fstart_height\x18\x02 \x01(\x04R\vstartHeight\x12\x1d\n" + - "\n" + - "end_height\x18\x03 \x01(\x04R\tendHeight\"K\n" + - "\x13BlockTimingResponse\x12\x10\n" + - "\x03max\x18\x01 \x01(\x04R\x03max\x12\x10\n" + - "\x03min\x18\x02 \x01(\x04R\x03min\x12\x10\n" + - "\x03avg\x18\x03 \x01(\x01R\x03avg\",\n" + - "\x16GetHeaderByHashRequest\x12\x12\n" + - "\x04hash\x18\x01 \x01(\fR\x04hash\"\xcd\x01\n" + - "\x13BlockHeaderResponse\x12-\n" + - "\x06header\x18\x01 \x01(\v2\x15.tari.rpc.BlockHeaderR\x06header\x12$\n" + - "\rconfirmations\x18\x02 \x01(\x04R\rconfirmations\x12\x16\n" + - "\x06reward\x18\x03 \x01(\x04R\x06reward\x12\x1e\n" + - "\n" + - "difficulty\x18\x04 \x01(\x04R\n" + - "difficulty\x12)\n" + - "\x10num_transactions\x18\x05 \x01(\rR\x0fnumTransactions\"\x83\x01\n" + - "\x12ListHeadersRequest\x12\x1f\n" + - "\vfrom_height\x18\x01 \x01(\x04R\n" + - "fromHeight\x12\x1f\n" + - "\vnum_headers\x18\x02 \x01(\x04R\n" + - "numHeaders\x12+\n" + - "\asorting\x18\x03 \x01(\x0e2\x11.tari.rpc.SortingR\asorting\",\n" + - "\x10GetBlocksRequest\x12\x18\n" + - "\aheights\x18\x01 \x03(\x04R\aheights\"F\n" + - "\x11GetBlocksResponse\x121\n" + - "\x06blocks\x18\x01 \x03(\v2\x19.tari.rpc.HistoricalBlockR\x06blocks\"\xd8\x01\n" + - "\bMetaData\x12*\n" + - "\x11best_block_height\x18\x01 \x01(\x04R\x0fbestBlockHeight\x12&\n" + - "\x0fbest_block_hash\x18\x02 \x01(\fR\rbestBlockHash\x125\n" + - "\x16accumulated_difficulty\x18\x05 \x01(\fR\x15accumulatedDifficulty\x12#\n" + - "\rpruned_height\x18\x06 \x01(\x04R\fprunedHeight\x12\x1c\n" + - "\ttimestamp\x18\a \x01(\x04R\ttimestamp\"v\n" + - "\x10SyncInfoResponse\x12\x1d\n" + - "\n" + - "tip_height\x18\x01 \x01(\x04R\ttipHeight\x12!\n" + - "\flocal_height\x18\x02 \x01(\x04R\vlocalHeight\x12 \n" + - "\fpeer_node_id\x18\x03 \x03(\fR\n" + - "peerNodeId\"\xda\x01\n" + - "\x14SyncProgressResponse\x12\x1d\n" + - "\n" + - "tip_height\x18\x01 \x01(\x04R\ttipHeight\x12!\n" + - "\flocal_height\x18\x02 \x01(\x04R\vlocalHeight\x12)\n" + - "\x05state\x18\x03 \x01(\x0e2\x13.tari.rpc.SyncStateR\x05state\x12\x1d\n" + - "\n" + - "short_desc\x18\x04 \x01(\tR\tshortDesc\x126\n" + - "\x17initial_connected_peers\x18\x05 \x01(\x04R\x15initialConnectedPeers\"\xf6\x01\n" + - "\x11GetNewBlockResult\x12\x1d\n" + - "\n" + - "block_hash\x18\x01 \x01(\fR\tblockHash\x12%\n" + - "\x05block\x18\x02 \x01(\v2\x0f.tari.rpc.BlockR\x05block\x12*\n" + - "\x11merge_mining_hash\x18\x03 \x01(\fR\x0fmergeMiningHash\x12$\n" + - "\x0etari_unique_id\x18\x04 \x01(\fR\ftariUniqueId\x122\n" + - "\n" + - "miner_data\x18\x05 \x01(\v2\x13.tari.rpc.MinerDataR\tminerData\x12\x15\n" + - "\x06vm_key\x18\x06 \x01(\fR\x05vmKey\"\xd8\x01\n" + - "\x15GetNewBlockBlobResult\x12\x1d\n" + - "\n" + - "block_hash\x18\x01 \x01(\fR\tblockHash\x12\x16\n" + - "\x06header\x18\x02 \x01(\fR\x06header\x12\x1d\n" + - "\n" + - "block_body\x18\x03 \x01(\fR\tblockBody\x12*\n" + - "\x11merge_mining_hash\x18\x04 \x01(\fR\x0fmergeMiningHash\x12\x17\n" + - "\autxo_mr\x18\x05 \x01(\fR\x06utxoMr\x12$\n" + - "\x0etari_unique_id\x18\x06 \x01(\fR\ftariUniqueId\"\x96\x01\n" + - "\tMinerData\x12%\n" + - "\x04algo\x18\x01 \x01(\v2\x11.tari.rpc.PowAlgoR\x04algo\x12+\n" + - "\x11target_difficulty\x18\x02 \x01(\x04R\x10targetDifficulty\x12\x16\n" + - "\x06reward\x18\x03 \x01(\x04R\x06reward\x12\x1d\n" + - "\n" + - "total_fees\x18\x05 \x01(\x04R\ttotalFees\"K\n" + - "\x14SearchKernelsRequest\x123\n" + - "\n" + - "signatures\x18\x01 \x03(\v2\x13.tari.rpc.SignatureR\n" + - "signatures\"6\n" + - "\x12SearchUtxosRequest\x12 \n" + - "\vcommitments\x18\x01 \x03(\fR\vcommitments\"3\n" + - "\x19FetchMatchingUtxosRequest\x12\x16\n" + - "\x06hashes\x18\x01 \x03(\fR\x06hashes\"Q\n" + - "\x1aFetchMatchingUtxosResponse\x123\n" + - "\x06output\x18\x01 \x01(\v2\x1b.tari.rpc.TransactionOutputR\x06output\"6\n" + - "\x10GetPeersResponse\x12\"\n" + - "\x04peer\x18\x01 \x01(\v2\x0e.tari.rpc.PeerR\x04peer\"\x11\n" + - "\x0fGetPeersRequest\"S\n" + - "\x18SubmitTransactionRequest\x127\n" + - "\vtransaction\x18\x01 \x01(\v2\x15.tari.rpc.TransactionR\vtransaction\"V\n" + - "\x19SubmitTransactionResponse\x129\n" + - "\x06result\x18\x01 \x01(\x0e2!.tari.rpc.SubmitTransactionResultR\x06result\"\x1f\n" + - "\x1dGetMempoolTransactionsRequest\"Y\n" + - "\x1eGetMempoolTransactionsResponse\x127\n" + - "\vtransaction\x18\x01 \x01(\v2\x15.tari.rpc.TransactionR\vtransaction\"M\n" + - "\x17TransactionStateRequest\x122\n" + - "\n" + - "excess_sig\x18\x01 \x01(\v2\x13.tari.rpc.SignatureR\texcessSig\"Q\n" + - "\x18TransactionStateResponse\x125\n" + - "\x06result\x18\x01 \x01(\x0e2\x1d.tari.rpc.TransactionLocationR\x06result\"\x8b\x01\n" + - "\x14MempoolStatsResponse\x12'\n" + - "\x0funconfirmed_txs\x18\x02 \x01(\x04R\x0eunconfirmedTxs\x12\x1b\n" + - "\treorg_txs\x18\x03 \x01(\x04R\breorgTxs\x12-\n" + - "\x12unconfirmed_weight\x18\x04 \x01(\x04R\x11unconfirmedWeight\"8\n" + - "\x1eGetActiveValidatorNodesRequest\x12\x16\n" + - "\x06height\x18\x01 \x01(\x04R\x06height\"]\n" + - "\x1fGetActiveValidatorNodesResponse\x12\x1b\n" + - "\tshard_key\x18\x01 \x01(\fR\bshardKey\x12\x1d\n" + - "\n" + - "public_key\x18\x02 \x01(\fR\tpublicKey\"K\n" + - "\x12GetShardKeyRequest\x12\x16\n" + - "\x06height\x18\x01 \x01(\x04R\x06height\x12\x1d\n" + - "\n" + - "public_key\x18\x02 \x01(\fR\tpublicKey\"H\n" + - "\x13GetShardKeyResponse\x12\x1b\n" + - "\tshard_key\x18\x01 \x01(\fR\bshardKey\x12\x14\n" + - "\x05found\x18\x02 \x01(\bR\x05found\"V\n" + - "\x1fGetTemplateRegistrationsRequest\x12\x1d\n" + - "\n" + - "start_hash\x18\x01 \x01(\fR\tstartHash\x12\x14\n" + - "\x05count\x18\x02 \x01(\x04R\x05count\"\x82\x01\n" + - "\x1fGetTemplateRegistrationResponse\x12\x1b\n" + - "\tutxo_hash\x18\x01 \x01(\fR\butxoHash\x12B\n" + - "\fregistration\x18\x02 \x01(\v2\x1e.tari.rpc.TemplateRegistrationR\fregistration\"_\n" + - "\tBlockInfo\x12\x16\n" + - "\x06height\x18\x01 \x01(\x04R\x06height\x12\x12\n" + - "\x04hash\x18\x02 \x01(\fR\x04hash\x12&\n" + - "\x0fnext_block_hash\x18\x03 \x01(\fR\rnextBlockHash\"O\n" + - "\x18GetSideChainUtxosRequest\x12\x1d\n" + - "\n" + - "start_hash\x18\x01 \x01(\fR\tstartHash\x12\x14\n" + - "\x05count\x18\x02 \x01(\x04R\x05count\"\x86\x01\n" + - "\x19GetSideChainUtxosResponse\x122\n" + - "\n" + - "block_info\x18\x01 \x01(\v2\x13.tari.rpc.BlockInfoR\tblockInfo\x125\n" + - "\aoutputs\x18\x02 \x03(\v2\x1b.tari.rpc.TransactionOutputR\aoutputs\"\x18\n" + - "\x16GetNetworkStateRequest\"\xc2\x04\n" + - "\x17GetNetworkStateResponse\x12.\n" + - "\bmetadata\x18\x01 \x01(\v2\x12.tari.rpc.MetaDataR\bmetadata\x122\n" + - "\x15initial_sync_achieved\x18\x02 \x01(\bR\x13initialSyncAchieved\x12?\n" + - "\x0fbase_node_state\x18\x03 \x01(\x0e2\x17.tari.rpc.BaseNodeStateR\rbaseNodeState\x12-\n" + - "\x12failed_checkpoints\x18\x04 \x01(\bR\x11failedCheckpoints\x12\x16\n" + - "\x06reward\x18\x05 \x01(\x04R\x06reward\x129\n" + - "\x19sha3x_estimated_hash_rate\x18\x06 \x01(\x04R\x16sha3xEstimatedHashRate\x12J\n" + - "\"monero_randomx_estimated_hash_rate\x18\a \x01(\x04R\x1emoneroRandomxEstimatedHashRate\x12F\n" + - " tari_randomx_estimated_hash_rate\x18\n" + - " \x01(\x04R\x1ctariRandomxEstimatedHashRate\x12'\n" + - "\x0fnum_connections\x18\b \x01(\x04R\x0enumConnections\x12C\n" + - "\x10liveness_results\x18\t \x03(\v2\x18.tari.rpc.LivenessResultR\x0flivenessResults\"\x80\x01\n" + - "\x0eLivenessResult\x12 \n" + - "\fpeer_node_id\x18\x01 \x01(\fR\n" + - "peerNodeId\x12)\n" + - "\x10discover_latency\x18\x02 \x01(\x04R\x0fdiscoverLatency\x12!\n" + - "\fping_latency\x18\x03 \x01(\x04R\vpingLatency\"\xb1\x01\n" + - "\x1eSearchPaymentReferencesRequest\x122\n" + - "\x15payment_reference_hex\x18\x01 \x03(\tR\x13paymentReferenceHex\x126\n" + - "\x17payment_reference_bytes\x18\x02 \x03(\fR\x15paymentReferenceBytes\x12#\n" + - "\rinclude_spent\x18\x03 \x01(\bR\fincludeSpent\"\xed\x02\n" + - "\x18PaymentReferenceResponse\x122\n" + - "\x15payment_reference_hex\x18\x01 \x01(\tR\x13paymentReferenceHex\x12!\n" + - "\fblock_height\x18\x02 \x01(\x04R\vblockHeight\x12\x1d\n" + - "\n" + - "block_hash\x18\x03 \x01(\fR\tblockHash\x12'\n" + - "\x0fmined_timestamp\x18\x04 \x01(\x04R\x0eminedTimestamp\x12\x1e\n" + - "\n" + - "commitment\x18\x05 \x01(\fR\n" + - "commitment\x12\x19\n" + - "\bis_spent\x18\x06 \x01(\bR\aisSpent\x12!\n" + - "\fspent_height\x18\a \x01(\x04R\vspentHeight\x12(\n" + - "\x10spent_block_hash\x18\b \x01(\fR\x0espentBlockHash\x12*\n" + - "\x11min_value_promise\x18\t \x01(\x04R\x0fminValuePromise*\x80\x01\n" + - "\rBaseNodeState\x12\f\n" + - "\bSTART_UP\x10\x00\x12\x0f\n" + - "\vHEADER_SYNC\x10\x01\x12\x10\n" + - "\fHORIZON_SYNC\x10\x02\x12\x0e\n" + - "\n" + - "CONNECTING\x10\x03\x12\x0e\n" + - "\n" + - "BLOCK_SYNC\x10\x04\x12\r\n" + - "\tLISTENING\x10\x05\x12\x0f\n" + - "\vSYNC_FAILED\x10\x06*<\n" + - "\bCalcType\x12\b\n" + - "\x04MEAN\x10\x00\x12\n" + - "\n" + - "\x06MEDIAN\x10\x01\x12\f\n" + - "\bQUANTILE\x10\x02\x12\f\n" + - "\bQUARTILE\x10\x03*,\n" + - "\aSorting\x12\x10\n" + - "\fSORTING_DESC\x10\x00\x12\x0f\n" + - "\vSORTING_ASC\x10\x01*b\n" + - "\tSyncState\x12\v\n" + - "\aSTARTUP\x10\x00\x12\x13\n" + - "\x0fHEADER_STARTING\x10\x01\x12\n" + - "\n" + - "\x06HEADER\x10\x02\x12\x12\n" + - "\x0eBLOCK_STARTING\x10\x03\x12\t\n" + - "\x05BLOCK\x10\x04\x12\b\n" + - "\x04DONE\x10\x05*t\n" + - "\x17SubmitTransactionResult\x12\b\n" + - "\x04NONE\x10\x00\x12\f\n" + - "\bACCEPTED\x10\x01\x12 \n" + - "\x1cNOT_PROCESSABLE_AT_THIS_TIME\x10\x02\x12\x11\n" + - "\rALREADY_MINED\x10\x03\x12\f\n" + - "\bREJECTED\x10\x04*J\n" + - "\x13TransactionLocation\x12\v\n" + - "\aUNKNOWN\x10\x00\x12\v\n" + - "\aMEMPOOL\x10\x01\x12\t\n" + - "\x05MINED\x10\x02\x12\x0e\n" + - "\n" + - "NOT_STORED\x10\x032\x9a\x18\n" + - "\bBaseNode\x12L\n" + - "\vListHeaders\x12\x1c.tari.rpc.ListHeadersRequest\x1a\x1d.tari.rpc.BlockHeaderResponse0\x01\x12R\n" + - "\x0fGetHeaderByHash\x12 .tari.rpc.GetHeaderByHashRequest\x1a\x1d.tari.rpc.BlockHeaderResponse\x12D\n" + - "\tGetBlocks\x12\x1a.tari.rpc.GetBlocksRequest\x1a\x19.tari.rpc.HistoricalBlock0\x01\x12H\n" + - "\x0eGetBlockTiming\x12\x17.tari.rpc.HeightRequest\x1a\x1d.tari.rpc.BlockTimingResponse\x12C\n" + - "\fGetConstants\x12\x15.tari.rpc.BlockHeight\x1a\x1c.tari.rpc.ConsensusConstants\x12I\n" + - "\fGetBlockSize\x12\x1b.tari.rpc.BlockGroupRequest\x1a\x1c.tari.rpc.BlockGroupResponse\x12I\n" + - "\fGetBlockFees\x12\x1b.tari.rpc.BlockGroupRequest\x1a\x1c.tari.rpc.BlockGroupResponse\x124\n" + - "\n" + - "GetVersion\x12\x0f.tari.rpc.Empty\x1a\x15.tari.rpc.StringValue\x12<\n" + - "\x0fCheckForUpdates\x12\x0f.tari.rpc.Empty\x1a\x18.tari.rpc.SoftwareUpdate\x12W\n" + - "\x16GetTokensInCirculation\x12\x1a.tari.rpc.GetBlocksRequest\x1a\x1f.tari.rpc.ValueAtHeightResponse0\x01\x12V\n" + - "\x14GetNetworkDifficulty\x12\x17.tari.rpc.HeightRequest\x1a#.tari.rpc.NetworkDifficultyResponse0\x01\x12\\\n" + - "\x13GetNewBlockTemplate\x12!.tari.rpc.NewBlockTemplateRequest\x1a\".tari.rpc.NewBlockTemplateResponse\x12F\n" + - "\vGetNewBlock\x12\x1a.tari.rpc.NewBlockTemplate\x1a\x1b.tari.rpc.GetNewBlockResult\x12b\n" + - "\x18GetNewBlockWithCoinbases\x12).tari.rpc.GetNewBlockWithCoinbasesRequest\x1a\x1b.tari.rpc.GetNewBlockResult\x12r\n" + - " GetNewBlockTemplateWithCoinbases\x121.tari.rpc.GetNewBlockTemplateWithCoinbasesRequest\x1a\x1b.tari.rpc.GetNewBlockResult\x12N\n" + - "\x0fGetNewBlockBlob\x12\x1a.tari.rpc.NewBlockTemplate\x1a\x1f.tari.rpc.GetNewBlockBlobResult\x12=\n" + - "\vSubmitBlock\x12\x0f.tari.rpc.Block\x1a\x1d.tari.rpc.SubmitBlockResponse\x12L\n" + - "\x0fSubmitBlockBlob\x12\x1a.tari.rpc.BlockBlobRequest\x1a\x1d.tari.rpc.SubmitBlockResponse\x12\\\n" + - "\x11SubmitTransaction\x12\".tari.rpc.SubmitTransactionRequest\x1a#.tari.rpc.SubmitTransactionResponse\x12:\n" + - "\vGetSyncInfo\x12\x0f.tari.rpc.Empty\x1a\x1a.tari.rpc.SyncInfoResponse\x12B\n" + - "\x0fGetSyncProgress\x12\x0f.tari.rpc.Empty\x1a\x1e.tari.rpc.SyncProgressResponse\x128\n" + - "\n" + - "GetTipInfo\x12\x0f.tari.rpc.Empty\x1a\x19.tari.rpc.TipInfoResponse\x12L\n" + - "\rSearchKernels\x12\x1e.tari.rpc.SearchKernelsRequest\x1a\x19.tari.rpc.HistoricalBlock0\x01\x12H\n" + - "\vSearchUtxos\x12\x1c.tari.rpc.SearchUtxosRequest\x1a\x19.tari.rpc.HistoricalBlock0\x01\x12a\n" + - "\x12FetchMatchingUtxos\x12#.tari.rpc.FetchMatchingUtxosRequest\x1a$.tari.rpc.FetchMatchingUtxosResponse0\x01\x12C\n" + - "\bGetPeers\x12\x19.tari.rpc.GetPeersRequest\x1a\x1a.tari.rpc.GetPeersResponse0\x01\x12m\n" + - "\x16GetMempoolTransactions\x12'.tari.rpc.GetMempoolTransactionsRequest\x1a(.tari.rpc.GetMempoolTransactionsResponse0\x01\x12Y\n" + - "\x10TransactionState\x12!.tari.rpc.TransactionStateRequest\x1a\".tari.rpc.TransactionStateResponse\x123\n" + - "\bIdentify\x12\x0f.tari.rpc.Empty\x1a\x16.tari.rpc.NodeIdentity\x12D\n" + - "\x10GetNetworkStatus\x12\x0f.tari.rpc.Empty\x1a\x1f.tari.rpc.NetworkStatusResponse\x12K\n" + - "\x12ListConnectedPeers\x12\x0f.tari.rpc.Empty\x1a$.tari.rpc.ListConnectedPeersResponse\x12B\n" + - "\x0fGetMempoolStats\x12\x0f.tari.rpc.Empty\x1a\x1e.tari.rpc.MempoolStatsResponse\x12p\n" + - "\x17GetActiveValidatorNodes\x12(.tari.rpc.GetActiveValidatorNodesRequest\x1a).tari.rpc.GetActiveValidatorNodesResponse0\x01\x12J\n" + - "\vGetShardKey\x12\x1c.tari.rpc.GetShardKeyRequest\x1a\x1d.tari.rpc.GetShardKeyResponse\x12r\n" + - "\x18GetTemplateRegistrations\x12).tari.rpc.GetTemplateRegistrationsRequest\x1a).tari.rpc.GetTemplateRegistrationResponse0\x01\x12^\n" + - "\x11GetSideChainUtxos\x12\".tari.rpc.GetSideChainUtxosRequest\x1a#.tari.rpc.GetSideChainUtxosResponse0\x01\x12V\n" + - "\x0fGetNetworkState\x12 .tari.rpc.GetNetworkStateRequest\x1a!.tari.rpc.GetNetworkStateResponse\x12i\n" + - "\x17SearchPaymentReferences\x12(.tari.rpc.SearchPaymentReferencesRequest\x1a\".tari.rpc.PaymentReferenceResponse0\x01B,Z*pool/internal/gbt/tari/base_node;base_nodeb\x06proto3" - -var ( - file_base_node_proto_rawDescOnce sync.Once - file_base_node_proto_rawDescData []byte -) - -func file_base_node_proto_rawDescGZIP() []byte { - file_base_node_proto_rawDescOnce.Do(func() { - file_base_node_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_base_node_proto_rawDesc), len(file_base_node_proto_rawDesc))) - }) - return file_base_node_proto_rawDescData -} - -var file_base_node_proto_enumTypes = make([]protoimpl.EnumInfo, 6) -var file_base_node_proto_msgTypes = make([]protoimpl.MessageInfo, 60) -var file_base_node_proto_goTypes = []any{ - (BaseNodeState)(0), // 0: tari.rpc.BaseNodeState - (CalcType)(0), // 1: tari.rpc.CalcType - (Sorting)(0), // 2: tari.rpc.Sorting - (SyncState)(0), // 3: tari.rpc.SyncState - (SubmitTransactionResult)(0), // 4: tari.rpc.SubmitTransactionResult - (TransactionLocation)(0), // 5: tari.rpc.TransactionLocation - (*GetAssetMetadataRequest)(nil), // 6: tari.rpc.GetAssetMetadataRequest - (*GetAssetMetadataResponse)(nil), // 7: tari.rpc.GetAssetMetadataResponse - (*ListAssetRegistrationsRequest)(nil), // 8: tari.rpc.ListAssetRegistrationsRequest - (*ListAssetRegistrationsResponse)(nil), // 9: tari.rpc.ListAssetRegistrationsResponse - (*GetTokensRequest)(nil), // 10: tari.rpc.GetTokensRequest - (*GetTokensResponse)(nil), // 11: tari.rpc.GetTokensResponse - (*SubmitBlockResponse)(nil), // 12: tari.rpc.SubmitBlockResponse - (*BlockBlobRequest)(nil), // 13: tari.rpc.BlockBlobRequest - (*TipInfoResponse)(nil), // 14: tari.rpc.TipInfoResponse - (*NewBlockTemplateResponse)(nil), // 15: tari.rpc.NewBlockTemplateResponse - (*NewBlockTemplateRequest)(nil), // 16: tari.rpc.NewBlockTemplateRequest - (*GetNewBlockTemplateWithCoinbasesRequest)(nil), // 17: tari.rpc.GetNewBlockTemplateWithCoinbasesRequest - (*GetNewBlockWithCoinbasesRequest)(nil), // 18: tari.rpc.GetNewBlockWithCoinbasesRequest - (*NewBlockCoinbase)(nil), // 19: tari.rpc.NewBlockCoinbase - (*NetworkDifficultyResponse)(nil), // 20: tari.rpc.NetworkDifficultyResponse - (*ValueAtHeightResponse)(nil), // 21: tari.rpc.ValueAtHeightResponse - (*IntegerValue)(nil), // 22: tari.rpc.IntegerValue - (*StringValue)(nil), // 23: tari.rpc.StringValue - (*BlockGroupRequest)(nil), // 24: tari.rpc.BlockGroupRequest - (*BlockGroupResponse)(nil), // 25: tari.rpc.BlockGroupResponse - (*HeightRequest)(nil), // 26: tari.rpc.HeightRequest - (*BlockTimingResponse)(nil), // 27: tari.rpc.BlockTimingResponse - (*GetHeaderByHashRequest)(nil), // 28: tari.rpc.GetHeaderByHashRequest - (*BlockHeaderResponse)(nil), // 29: tari.rpc.BlockHeaderResponse - (*ListHeadersRequest)(nil), // 30: tari.rpc.ListHeadersRequest - (*GetBlocksRequest)(nil), // 31: tari.rpc.GetBlocksRequest - (*GetBlocksResponse)(nil), // 32: tari.rpc.GetBlocksResponse - (*MetaData)(nil), // 33: tari.rpc.MetaData - (*SyncInfoResponse)(nil), // 34: tari.rpc.SyncInfoResponse - (*SyncProgressResponse)(nil), // 35: tari.rpc.SyncProgressResponse - (*GetNewBlockResult)(nil), // 36: tari.rpc.GetNewBlockResult - (*GetNewBlockBlobResult)(nil), // 37: tari.rpc.GetNewBlockBlobResult - (*MinerData)(nil), // 38: tari.rpc.MinerData - (*SearchKernelsRequest)(nil), // 39: tari.rpc.SearchKernelsRequest - (*SearchUtxosRequest)(nil), // 40: tari.rpc.SearchUtxosRequest - (*FetchMatchingUtxosRequest)(nil), // 41: tari.rpc.FetchMatchingUtxosRequest - (*FetchMatchingUtxosResponse)(nil), // 42: tari.rpc.FetchMatchingUtxosResponse - (*GetPeersResponse)(nil), // 43: tari.rpc.GetPeersResponse - (*GetPeersRequest)(nil), // 44: tari.rpc.GetPeersRequest - (*SubmitTransactionRequest)(nil), // 45: tari.rpc.SubmitTransactionRequest - (*SubmitTransactionResponse)(nil), // 46: tari.rpc.SubmitTransactionResponse - (*GetMempoolTransactionsRequest)(nil), // 47: tari.rpc.GetMempoolTransactionsRequest - (*GetMempoolTransactionsResponse)(nil), // 48: tari.rpc.GetMempoolTransactionsResponse - (*TransactionStateRequest)(nil), // 49: tari.rpc.TransactionStateRequest - (*TransactionStateResponse)(nil), // 50: tari.rpc.TransactionStateResponse - (*MempoolStatsResponse)(nil), // 51: tari.rpc.MempoolStatsResponse - (*GetActiveValidatorNodesRequest)(nil), // 52: tari.rpc.GetActiveValidatorNodesRequest - (*GetActiveValidatorNodesResponse)(nil), // 53: tari.rpc.GetActiveValidatorNodesResponse - (*GetShardKeyRequest)(nil), // 54: tari.rpc.GetShardKeyRequest - (*GetShardKeyResponse)(nil), // 55: tari.rpc.GetShardKeyResponse - (*GetTemplateRegistrationsRequest)(nil), // 56: tari.rpc.GetTemplateRegistrationsRequest - (*GetTemplateRegistrationResponse)(nil), // 57: tari.rpc.GetTemplateRegistrationResponse - (*BlockInfo)(nil), // 58: tari.rpc.BlockInfo - (*GetSideChainUtxosRequest)(nil), // 59: tari.rpc.GetSideChainUtxosRequest - (*GetSideChainUtxosResponse)(nil), // 60: tari.rpc.GetSideChainUtxosResponse - (*GetNetworkStateRequest)(nil), // 61: tari.rpc.GetNetworkStateRequest - (*GetNetworkStateResponse)(nil), // 62: tari.rpc.GetNetworkStateResponse - (*LivenessResult)(nil), // 63: tari.rpc.LivenessResult - (*SearchPaymentReferencesRequest)(nil), // 64: tari.rpc.SearchPaymentReferencesRequest - (*PaymentReferenceResponse)(nil), // 65: tari.rpc.PaymentReferenceResponse - (*transaction.OutputFeatures)(nil), // 66: tari.rpc.OutputFeatures - (*block.NewBlockTemplate)(nil), // 67: tari.rpc.NewBlockTemplate - (*block.PowAlgo)(nil), // 68: tari.rpc.PowAlgo - (*block.BlockHeader)(nil), // 69: tari.rpc.BlockHeader - (*block.HistoricalBlock)(nil), // 70: tari.rpc.HistoricalBlock - (*block.Block)(nil), // 71: tari.rpc.Block - (*types.Signature)(nil), // 72: tari.rpc.Signature - (*transaction.TransactionOutput)(nil), // 73: tari.rpc.TransactionOutput - (*net_work.Peer)(nil), // 74: tari.rpc.Peer - (*transaction.Transaction)(nil), // 75: tari.rpc.Transaction - (*sidechain_types.TemplateRegistration)(nil), // 76: tari.rpc.TemplateRegistration - (*types.BlockHeight)(nil), // 77: tari.rpc.BlockHeight - (*types.Empty)(nil), // 78: tari.rpc.Empty - (*types.ConsensusConstants)(nil), // 79: tari.rpc.ConsensusConstants - (*net_work.SoftwareUpdate)(nil), // 80: tari.rpc.SoftwareUpdate - (*net_work.NodeIdentity)(nil), // 81: tari.rpc.NodeIdentity - (*net_work.NetworkStatusResponse)(nil), // 82: tari.rpc.NetworkStatusResponse - (*net_work.ListConnectedPeersResponse)(nil), // 83: tari.rpc.ListConnectedPeersResponse -} -var file_base_node_proto_depIdxs = []int32{ - 66, // 0: tari.rpc.GetAssetMetadataResponse.features:type_name -> tari.rpc.OutputFeatures - 66, // 1: tari.rpc.ListAssetRegistrationsResponse.features:type_name -> tari.rpc.OutputFeatures - 66, // 2: tari.rpc.GetTokensResponse.features:type_name -> tari.rpc.OutputFeatures - 33, // 3: tari.rpc.TipInfoResponse.metadata:type_name -> tari.rpc.MetaData - 0, // 4: tari.rpc.TipInfoResponse.base_node_state:type_name -> tari.rpc.BaseNodeState - 67, // 5: tari.rpc.NewBlockTemplateResponse.new_block_template:type_name -> tari.rpc.NewBlockTemplate - 38, // 6: tari.rpc.NewBlockTemplateResponse.miner_data:type_name -> tari.rpc.MinerData - 68, // 7: tari.rpc.NewBlockTemplateRequest.algo:type_name -> tari.rpc.PowAlgo - 68, // 8: tari.rpc.GetNewBlockTemplateWithCoinbasesRequest.algo:type_name -> tari.rpc.PowAlgo - 19, // 9: tari.rpc.GetNewBlockTemplateWithCoinbasesRequest.coinbases:type_name -> tari.rpc.NewBlockCoinbase - 67, // 10: tari.rpc.GetNewBlockWithCoinbasesRequest.new_template:type_name -> tari.rpc.NewBlockTemplate - 19, // 11: tari.rpc.GetNewBlockWithCoinbasesRequest.coinbases:type_name -> tari.rpc.NewBlockCoinbase - 1, // 12: tari.rpc.BlockGroupRequest.calc_type:type_name -> tari.rpc.CalcType - 1, // 13: tari.rpc.BlockGroupResponse.calc_type:type_name -> tari.rpc.CalcType - 69, // 14: tari.rpc.BlockHeaderResponse.header:type_name -> tari.rpc.BlockHeader - 2, // 15: tari.rpc.ListHeadersRequest.sorting:type_name -> tari.rpc.Sorting - 70, // 16: tari.rpc.GetBlocksResponse.blocks:type_name -> tari.rpc.HistoricalBlock - 3, // 17: tari.rpc.SyncProgressResponse.state:type_name -> tari.rpc.SyncState - 71, // 18: tari.rpc.GetNewBlockResult.block:type_name -> tari.rpc.Block - 38, // 19: tari.rpc.GetNewBlockResult.miner_data:type_name -> tari.rpc.MinerData - 68, // 20: tari.rpc.MinerData.algo:type_name -> tari.rpc.PowAlgo - 72, // 21: tari.rpc.SearchKernelsRequest.signatures:type_name -> tari.rpc.Signature - 73, // 22: tari.rpc.FetchMatchingUtxosResponse.output:type_name -> tari.rpc.TransactionOutput - 74, // 23: tari.rpc.GetPeersResponse.peer:type_name -> tari.rpc.Peer - 75, // 24: tari.rpc.SubmitTransactionRequest.transaction:type_name -> tari.rpc.Transaction - 4, // 25: tari.rpc.SubmitTransactionResponse.result:type_name -> tari.rpc.SubmitTransactionResult - 75, // 26: tari.rpc.GetMempoolTransactionsResponse.transaction:type_name -> tari.rpc.Transaction - 72, // 27: tari.rpc.TransactionStateRequest.excess_sig:type_name -> tari.rpc.Signature - 5, // 28: tari.rpc.TransactionStateResponse.result:type_name -> tari.rpc.TransactionLocation - 76, // 29: tari.rpc.GetTemplateRegistrationResponse.registration:type_name -> tari.rpc.TemplateRegistration - 58, // 30: tari.rpc.GetSideChainUtxosResponse.block_info:type_name -> tari.rpc.BlockInfo - 73, // 31: tari.rpc.GetSideChainUtxosResponse.outputs:type_name -> tari.rpc.TransactionOutput - 33, // 32: tari.rpc.GetNetworkStateResponse.metadata:type_name -> tari.rpc.MetaData - 0, // 33: tari.rpc.GetNetworkStateResponse.base_node_state:type_name -> tari.rpc.BaseNodeState - 63, // 34: tari.rpc.GetNetworkStateResponse.liveness_results:type_name -> tari.rpc.LivenessResult - 30, // 35: tari.rpc.BaseNode.ListHeaders:input_type -> tari.rpc.ListHeadersRequest - 28, // 36: tari.rpc.BaseNode.GetHeaderByHash:input_type -> tari.rpc.GetHeaderByHashRequest - 31, // 37: tari.rpc.BaseNode.GetBlocks:input_type -> tari.rpc.GetBlocksRequest - 26, // 38: tari.rpc.BaseNode.GetBlockTiming:input_type -> tari.rpc.HeightRequest - 77, // 39: tari.rpc.BaseNode.GetConstants:input_type -> tari.rpc.BlockHeight - 24, // 40: tari.rpc.BaseNode.GetBlockSize:input_type -> tari.rpc.BlockGroupRequest - 24, // 41: tari.rpc.BaseNode.GetBlockFees:input_type -> tari.rpc.BlockGroupRequest - 78, // 42: tari.rpc.BaseNode.GetVersion:input_type -> tari.rpc.Empty - 78, // 43: tari.rpc.BaseNode.CheckForUpdates:input_type -> tari.rpc.Empty - 31, // 44: tari.rpc.BaseNode.GetTokensInCirculation:input_type -> tari.rpc.GetBlocksRequest - 26, // 45: tari.rpc.BaseNode.GetNetworkDifficulty:input_type -> tari.rpc.HeightRequest - 16, // 46: tari.rpc.BaseNode.GetNewBlockTemplate:input_type -> tari.rpc.NewBlockTemplateRequest - 67, // 47: tari.rpc.BaseNode.GetNewBlock:input_type -> tari.rpc.NewBlockTemplate - 18, // 48: tari.rpc.BaseNode.GetNewBlockWithCoinbases:input_type -> tari.rpc.GetNewBlockWithCoinbasesRequest - 17, // 49: tari.rpc.BaseNode.GetNewBlockTemplateWithCoinbases:input_type -> tari.rpc.GetNewBlockTemplateWithCoinbasesRequest - 67, // 50: tari.rpc.BaseNode.GetNewBlockBlob:input_type -> tari.rpc.NewBlockTemplate - 71, // 51: tari.rpc.BaseNode.SubmitBlock:input_type -> tari.rpc.Block - 13, // 52: tari.rpc.BaseNode.SubmitBlockBlob:input_type -> tari.rpc.BlockBlobRequest - 45, // 53: tari.rpc.BaseNode.SubmitTransaction:input_type -> tari.rpc.SubmitTransactionRequest - 78, // 54: tari.rpc.BaseNode.GetSyncInfo:input_type -> tari.rpc.Empty - 78, // 55: tari.rpc.BaseNode.GetSyncProgress:input_type -> tari.rpc.Empty - 78, // 56: tari.rpc.BaseNode.GetTipInfo:input_type -> tari.rpc.Empty - 39, // 57: tari.rpc.BaseNode.SearchKernels:input_type -> tari.rpc.SearchKernelsRequest - 40, // 58: tari.rpc.BaseNode.SearchUtxos:input_type -> tari.rpc.SearchUtxosRequest - 41, // 59: tari.rpc.BaseNode.FetchMatchingUtxos:input_type -> tari.rpc.FetchMatchingUtxosRequest - 44, // 60: tari.rpc.BaseNode.GetPeers:input_type -> tari.rpc.GetPeersRequest - 47, // 61: tari.rpc.BaseNode.GetMempoolTransactions:input_type -> tari.rpc.GetMempoolTransactionsRequest - 49, // 62: tari.rpc.BaseNode.TransactionState:input_type -> tari.rpc.TransactionStateRequest - 78, // 63: tari.rpc.BaseNode.Identify:input_type -> tari.rpc.Empty - 78, // 64: tari.rpc.BaseNode.GetNetworkStatus:input_type -> tari.rpc.Empty - 78, // 65: tari.rpc.BaseNode.ListConnectedPeers:input_type -> tari.rpc.Empty - 78, // 66: tari.rpc.BaseNode.GetMempoolStats:input_type -> tari.rpc.Empty - 52, // 67: tari.rpc.BaseNode.GetActiveValidatorNodes:input_type -> tari.rpc.GetActiveValidatorNodesRequest - 54, // 68: tari.rpc.BaseNode.GetShardKey:input_type -> tari.rpc.GetShardKeyRequest - 56, // 69: tari.rpc.BaseNode.GetTemplateRegistrations:input_type -> tari.rpc.GetTemplateRegistrationsRequest - 59, // 70: tari.rpc.BaseNode.GetSideChainUtxos:input_type -> tari.rpc.GetSideChainUtxosRequest - 61, // 71: tari.rpc.BaseNode.GetNetworkState:input_type -> tari.rpc.GetNetworkStateRequest - 64, // 72: tari.rpc.BaseNode.SearchPaymentReferences:input_type -> tari.rpc.SearchPaymentReferencesRequest - 29, // 73: tari.rpc.BaseNode.ListHeaders:output_type -> tari.rpc.BlockHeaderResponse - 29, // 74: tari.rpc.BaseNode.GetHeaderByHash:output_type -> tari.rpc.BlockHeaderResponse - 70, // 75: tari.rpc.BaseNode.GetBlocks:output_type -> tari.rpc.HistoricalBlock - 27, // 76: tari.rpc.BaseNode.GetBlockTiming:output_type -> tari.rpc.BlockTimingResponse - 79, // 77: tari.rpc.BaseNode.GetConstants:output_type -> tari.rpc.ConsensusConstants - 25, // 78: tari.rpc.BaseNode.GetBlockSize:output_type -> tari.rpc.BlockGroupResponse - 25, // 79: tari.rpc.BaseNode.GetBlockFees:output_type -> tari.rpc.BlockGroupResponse - 23, // 80: tari.rpc.BaseNode.GetVersion:output_type -> tari.rpc.StringValue - 80, // 81: tari.rpc.BaseNode.CheckForUpdates:output_type -> tari.rpc.SoftwareUpdate - 21, // 82: tari.rpc.BaseNode.GetTokensInCirculation:output_type -> tari.rpc.ValueAtHeightResponse - 20, // 83: tari.rpc.BaseNode.GetNetworkDifficulty:output_type -> tari.rpc.NetworkDifficultyResponse - 15, // 84: tari.rpc.BaseNode.GetNewBlockTemplate:output_type -> tari.rpc.NewBlockTemplateResponse - 36, // 85: tari.rpc.BaseNode.GetNewBlock:output_type -> tari.rpc.GetNewBlockResult - 36, // 86: tari.rpc.BaseNode.GetNewBlockWithCoinbases:output_type -> tari.rpc.GetNewBlockResult - 36, // 87: tari.rpc.BaseNode.GetNewBlockTemplateWithCoinbases:output_type -> tari.rpc.GetNewBlockResult - 37, // 88: tari.rpc.BaseNode.GetNewBlockBlob:output_type -> tari.rpc.GetNewBlockBlobResult - 12, // 89: tari.rpc.BaseNode.SubmitBlock:output_type -> tari.rpc.SubmitBlockResponse - 12, // 90: tari.rpc.BaseNode.SubmitBlockBlob:output_type -> tari.rpc.SubmitBlockResponse - 46, // 91: tari.rpc.BaseNode.SubmitTransaction:output_type -> tari.rpc.SubmitTransactionResponse - 34, // 92: tari.rpc.BaseNode.GetSyncInfo:output_type -> tari.rpc.SyncInfoResponse - 35, // 93: tari.rpc.BaseNode.GetSyncProgress:output_type -> tari.rpc.SyncProgressResponse - 14, // 94: tari.rpc.BaseNode.GetTipInfo:output_type -> tari.rpc.TipInfoResponse - 70, // 95: tari.rpc.BaseNode.SearchKernels:output_type -> tari.rpc.HistoricalBlock - 70, // 96: tari.rpc.BaseNode.SearchUtxos:output_type -> tari.rpc.HistoricalBlock - 42, // 97: tari.rpc.BaseNode.FetchMatchingUtxos:output_type -> tari.rpc.FetchMatchingUtxosResponse - 43, // 98: tari.rpc.BaseNode.GetPeers:output_type -> tari.rpc.GetPeersResponse - 48, // 99: tari.rpc.BaseNode.GetMempoolTransactions:output_type -> tari.rpc.GetMempoolTransactionsResponse - 50, // 100: tari.rpc.BaseNode.TransactionState:output_type -> tari.rpc.TransactionStateResponse - 81, // 101: tari.rpc.BaseNode.Identify:output_type -> tari.rpc.NodeIdentity - 82, // 102: tari.rpc.BaseNode.GetNetworkStatus:output_type -> tari.rpc.NetworkStatusResponse - 83, // 103: tari.rpc.BaseNode.ListConnectedPeers:output_type -> tari.rpc.ListConnectedPeersResponse - 51, // 104: tari.rpc.BaseNode.GetMempoolStats:output_type -> tari.rpc.MempoolStatsResponse - 53, // 105: tari.rpc.BaseNode.GetActiveValidatorNodes:output_type -> tari.rpc.GetActiveValidatorNodesResponse - 55, // 106: tari.rpc.BaseNode.GetShardKey:output_type -> tari.rpc.GetShardKeyResponse - 57, // 107: tari.rpc.BaseNode.GetTemplateRegistrations:output_type -> tari.rpc.GetTemplateRegistrationResponse - 60, // 108: tari.rpc.BaseNode.GetSideChainUtxos:output_type -> tari.rpc.GetSideChainUtxosResponse - 62, // 109: tari.rpc.BaseNode.GetNetworkState:output_type -> tari.rpc.GetNetworkStateResponse - 65, // 110: tari.rpc.BaseNode.SearchPaymentReferences:output_type -> tari.rpc.PaymentReferenceResponse - 73, // [73:111] is the sub-list for method output_type - 35, // [35:73] is the sub-list for method input_type - 35, // [35:35] is the sub-list for extension type_name - 35, // [35:35] is the sub-list for extension extendee - 0, // [0:35] is the sub-list for field type_name -} - -func init() { file_base_node_proto_init() } -func file_base_node_proto_init() { - if File_base_node_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_base_node_proto_rawDesc), len(file_base_node_proto_rawDesc)), - NumEnums: 6, - NumMessages: 60, - NumExtensions: 0, - NumServices: 1, - }, - GoTypes: file_base_node_proto_goTypes, - DependencyIndexes: file_base_node_proto_depIdxs, - EnumInfos: file_base_node_proto_enumTypes, - MessageInfos: file_base_node_proto_msgTypes, - }.Build() - File_base_node_proto = out.File - file_base_node_proto_goTypes = nil - file_base_node_proto_depIdxs = nil -} diff --git a/internal/gbt/tari/proto/base_node.proto b/internal/gbt/tari/proto/base_node.proto deleted file mode 100644 index 26ea595..0000000 --- a/internal/gbt/tari/proto/base_node.proto +++ /dev/null @@ -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; -} - diff --git a/internal/gbt/tari/proto/base_node_grpc.pb.go b/internal/gbt/tari/proto/base_node_grpc.pb.go deleted file mode 100644 index 126b243..0000000 --- a/internal/gbt/tari/proto/base_node_grpc.pb.go +++ /dev/null @@ -1,1666 +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-grpc. DO NOT EDIT. -// versions: -// - protoc-gen-go-grpc v1.5.1 -// - protoc v3.6.1 -// source: base_node.proto - -package base_node - -import ( - context "context" - "fmt" - block "pool/internal/gbt/tari/proto/block" - net_work "pool/internal/gbt/tari/proto/net_work" - types "pool/internal/gbt/tari/proto/types" - - grpc "google.golang.org/grpc" - codes "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" -) - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.64.0 or later. -const _ = grpc.SupportPackageIsVersion9 - -const ( - BaseNode_ListHeaders_FullMethodName = "/tari.rpc.BaseNode/ListHeaders" - BaseNode_GetHeaderByHash_FullMethodName = "/tari.rpc.BaseNode/GetHeaderByHash" - BaseNode_GetBlocks_FullMethodName = "/tari.rpc.BaseNode/GetBlocks" - BaseNode_GetBlockTiming_FullMethodName = "/tari.rpc.BaseNode/GetBlockTiming" - BaseNode_GetConstants_FullMethodName = "/tari.rpc.BaseNode/GetConstants" - BaseNode_GetBlockSize_FullMethodName = "/tari.rpc.BaseNode/GetBlockSize" - BaseNode_GetBlockFees_FullMethodName = "/tari.rpc.BaseNode/GetBlockFees" - BaseNode_GetVersion_FullMethodName = "/tari.rpc.BaseNode/GetVersion" - BaseNode_CheckForUpdates_FullMethodName = "/tari.rpc.BaseNode/CheckForUpdates" - BaseNode_GetTokensInCirculation_FullMethodName = "/tari.rpc.BaseNode/GetTokensInCirculation" - BaseNode_GetNetworkDifficulty_FullMethodName = "/tari.rpc.BaseNode/GetNetworkDifficulty" - BaseNode_GetNewBlockTemplate_FullMethodName = "/tari.rpc.BaseNode/GetNewBlockTemplate" - BaseNode_GetNewBlock_FullMethodName = "/tari.rpc.BaseNode/GetNewBlock" - BaseNode_GetNewBlockWithCoinbases_FullMethodName = "/tari.rpc.BaseNode/GetNewBlockWithCoinbases" - BaseNode_GetNewBlockTemplateWithCoinbases_FullMethodName = "/tari.rpc.BaseNode/GetNewBlockTemplateWithCoinbases" - BaseNode_GetNewBlockBlob_FullMethodName = "/tari.rpc.BaseNode/GetNewBlockBlob" - BaseNode_SubmitBlock_FullMethodName = "/tari.rpc.BaseNode/SubmitBlock" - BaseNode_SubmitBlockBlob_FullMethodName = "/tari.rpc.BaseNode/SubmitBlockBlob" - BaseNode_SubmitTransaction_FullMethodName = "/tari.rpc.BaseNode/SubmitTransaction" - BaseNode_GetSyncInfo_FullMethodName = "/tari.rpc.BaseNode/GetSyncInfo" - BaseNode_GetSyncProgress_FullMethodName = "/tari.rpc.BaseNode/GetSyncProgress" - BaseNode_GetTipInfo_FullMethodName = "/tari.rpc.BaseNode/GetTipInfo" - BaseNode_SearchKernels_FullMethodName = "/tari.rpc.BaseNode/SearchKernels" - BaseNode_SearchUtxos_FullMethodName = "/tari.rpc.BaseNode/SearchUtxos" - BaseNode_FetchMatchingUtxos_FullMethodName = "/tari.rpc.BaseNode/FetchMatchingUtxos" - BaseNode_GetPeers_FullMethodName = "/tari.rpc.BaseNode/GetPeers" - BaseNode_GetMempoolTransactions_FullMethodName = "/tari.rpc.BaseNode/GetMempoolTransactions" - BaseNode_TransactionState_FullMethodName = "/tari.rpc.BaseNode/TransactionState" - BaseNode_Identify_FullMethodName = "/tari.rpc.BaseNode/Identify" - BaseNode_GetNetworkStatus_FullMethodName = "/tari.rpc.BaseNode/GetNetworkStatus" - BaseNode_ListConnectedPeers_FullMethodName = "/tari.rpc.BaseNode/ListConnectedPeers" - BaseNode_GetMempoolStats_FullMethodName = "/tari.rpc.BaseNode/GetMempoolStats" - BaseNode_GetActiveValidatorNodes_FullMethodName = "/tari.rpc.BaseNode/GetActiveValidatorNodes" - BaseNode_GetShardKey_FullMethodName = "/tari.rpc.BaseNode/GetShardKey" - BaseNode_GetTemplateRegistrations_FullMethodName = "/tari.rpc.BaseNode/GetTemplateRegistrations" - BaseNode_GetSideChainUtxos_FullMethodName = "/tari.rpc.BaseNode/GetSideChainUtxos" - BaseNode_GetNetworkState_FullMethodName = "/tari.rpc.BaseNode/GetNetworkState" - BaseNode_SearchPaymentReferences_FullMethodName = "/tari.rpc.BaseNode/SearchPaymentReferences" -) - -// BaseNodeClient is the client API for BaseNode service. -// -// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. -// -// The gRPC interface for interacting with the base node. -type BaseNodeClient interface { - // Lists headers in the current best chain - ListHeaders(ctx context.Context, in *ListHeadersRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BlockHeaderResponse], error) - // Get header by hash - GetHeaderByHash(ctx context.Context, in *GetHeaderByHashRequest, opts ...grpc.CallOption) (*BlockHeaderResponse, error) - // Returns blocks in the current best chain. Currently only supports querying by height - GetBlocks(ctx context.Context, in *GetBlocksRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[block.HistoricalBlock], error) - // Returns the block timing for the chain heights - GetBlockTiming(ctx context.Context, in *HeightRequest, opts ...grpc.CallOption) (*BlockTimingResponse, error) - // Returns the network Constants - GetConstants(ctx context.Context, in *types.BlockHeight, opts ...grpc.CallOption) (*types.ConsensusConstants, error) - // Returns Block Sizes - GetBlockSize(ctx context.Context, in *BlockGroupRequest, opts ...grpc.CallOption) (*BlockGroupResponse, error) - // Returns Block Fees - GetBlockFees(ctx context.Context, in *BlockGroupRequest, opts ...grpc.CallOption) (*BlockGroupResponse, error) - // Get Version - GetVersion(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*StringValue, error) - // Check for new updates - CheckForUpdates(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.SoftwareUpdate, error) - // Get coins in circulation - GetTokensInCirculation(ctx context.Context, in *GetBlocksRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ValueAtHeightResponse], error) - // Get network difficulties - GetNetworkDifficulty(ctx context.Context, in *HeightRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[NetworkDifficultyResponse], error) - // Get the block template - GetNewBlockTemplate(ctx context.Context, in *NewBlockTemplateRequest, opts ...grpc.CallOption) (*NewBlockTemplateResponse, error) - // Construct a new block from a provided template - GetNewBlock(ctx context.Context, in *block.NewBlockTemplate, opts ...grpc.CallOption) (*GetNewBlockResult, error) - // Construct a new block from a provided template - GetNewBlockWithCoinbases(ctx context.Context, in *GetNewBlockWithCoinbasesRequest, opts ...grpc.CallOption) (*GetNewBlockResult, error) - // Construct a new block from a provided template - GetNewBlockTemplateWithCoinbases(ctx context.Context, in *GetNewBlockTemplateWithCoinbasesRequest, opts ...grpc.CallOption) (*GetNewBlockResult, error) - // Construct a new block and header blob from a provided template - GetNewBlockBlob(ctx context.Context, in *block.NewBlockTemplate, opts ...grpc.CallOption) (*GetNewBlockBlobResult, error) - // Submit a new block for propagation - SubmitBlock(ctx context.Context, in *block.Block, opts ...grpc.CallOption) (*SubmitBlockResponse, error) - // Submit a new mined block blob for propagation - SubmitBlockBlob(ctx context.Context, in *BlockBlobRequest, opts ...grpc.CallOption) (*SubmitBlockResponse, error) - // Submit a transaction for propagation - SubmitTransaction(ctx context.Context, in *SubmitTransactionRequest, opts ...grpc.CallOption) (*SubmitTransactionResponse, error) - // Get the base node sync information - GetSyncInfo(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*SyncInfoResponse, error) - // Get the base node sync information - GetSyncProgress(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*SyncProgressResponse, error) - // Get the base node tip information - GetTipInfo(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*TipInfoResponse, error) - // Search for blocks containing the specified kernels - SearchKernels(ctx context.Context, in *SearchKernelsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[block.HistoricalBlock], error) - // Search for blocks containing the specified commitments - SearchUtxos(ctx context.Context, in *SearchUtxosRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[block.HistoricalBlock], error) - // Fetch any utxos that exist in the main chain - FetchMatchingUtxos(ctx context.Context, in *FetchMatchingUtxosRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FetchMatchingUtxosResponse], error) - // get all peers from the base node - GetPeers(ctx context.Context, in *GetPeersRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetPeersResponse], error) - GetMempoolTransactions(ctx context.Context, in *GetMempoolTransactionsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetMempoolTransactionsResponse], error) - TransactionState(ctx context.Context, in *TransactionStateRequest, opts ...grpc.CallOption) (*TransactionStateResponse, error) - // This returns the node's network identity - Identify(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.NodeIdentity, error) - // Get Base Node network connectivity status - GetNetworkStatus(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.NetworkStatusResponse, error) - // List currently connected peers - ListConnectedPeers(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.ListConnectedPeersResponse, error) - // Get mempool stats - GetMempoolStats(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*MempoolStatsResponse, error) - // Get VNs - GetActiveValidatorNodes(ctx context.Context, in *GetActiveValidatorNodesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetActiveValidatorNodesResponse], error) - GetShardKey(ctx context.Context, in *GetShardKeyRequest, opts ...grpc.CallOption) (*GetShardKeyResponse, error) - // Get templates - GetTemplateRegistrations(ctx context.Context, in *GetTemplateRegistrationsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetTemplateRegistrationResponse], error) - GetSideChainUtxos(ctx context.Context, in *GetSideChainUtxosRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetSideChainUtxosResponse], error) - GetNetworkState(ctx context.Context, in *GetNetworkStateRequest, opts ...grpc.CallOption) (*GetNetworkStateResponse, error) - // PayRef (Payment Reference) lookup for block explorers and external services - SearchPaymentReferences(ctx context.Context, in *SearchPaymentReferencesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PaymentReferenceResponse], error) -} - -type baseNodeClient struct { - cc grpc.ClientConnInterface -} - -func NewBaseNodeClient(cc grpc.ClientConnInterface) BaseNodeClient { - return &baseNodeClient{cc} -} - -func (c *baseNodeClient) ListHeaders(ctx context.Context, in *ListHeadersRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[BlockHeaderResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[0], BaseNode_ListHeaders_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[ListHeadersRequest, BlockHeaderResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_ListHeadersClient = grpc.ServerStreamingClient[BlockHeaderResponse] - -func (c *baseNodeClient) GetHeaderByHash(ctx context.Context, in *GetHeaderByHashRequest, opts ...grpc.CallOption) (*BlockHeaderResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(BlockHeaderResponse) - err := c.cc.Invoke(ctx, BaseNode_GetHeaderByHash_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetBlocks(ctx context.Context, in *GetBlocksRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[block.HistoricalBlock], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[1], BaseNode_GetBlocks_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[GetBlocksRequest, block.HistoricalBlock]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetBlocksClient = grpc.ServerStreamingClient[block.HistoricalBlock] - -func (c *baseNodeClient) GetBlockTiming(ctx context.Context, in *HeightRequest, opts ...grpc.CallOption) (*BlockTimingResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(BlockTimingResponse) - err := c.cc.Invoke(ctx, BaseNode_GetBlockTiming_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetConstants(ctx context.Context, in *types.BlockHeight, opts ...grpc.CallOption) (*types.ConsensusConstants, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(types.ConsensusConstants) - err := c.cc.Invoke(ctx, BaseNode_GetConstants_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetBlockSize(ctx context.Context, in *BlockGroupRequest, opts ...grpc.CallOption) (*BlockGroupResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(BlockGroupResponse) - err := c.cc.Invoke(ctx, BaseNode_GetBlockSize_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetBlockFees(ctx context.Context, in *BlockGroupRequest, opts ...grpc.CallOption) (*BlockGroupResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(BlockGroupResponse) - err := c.cc.Invoke(ctx, BaseNode_GetBlockFees_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetVersion(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*StringValue, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(StringValue) - err := c.cc.Invoke(ctx, BaseNode_GetVersion_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) CheckForUpdates(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.SoftwareUpdate, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(net_work.SoftwareUpdate) - err := c.cc.Invoke(ctx, BaseNode_CheckForUpdates_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetTokensInCirculation(ctx context.Context, in *GetBlocksRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ValueAtHeightResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[2], BaseNode_GetTokensInCirculation_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[GetBlocksRequest, ValueAtHeightResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetTokensInCirculationClient = grpc.ServerStreamingClient[ValueAtHeightResponse] - -func (c *baseNodeClient) GetNetworkDifficulty(ctx context.Context, in *HeightRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[NetworkDifficultyResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[3], BaseNode_GetNetworkDifficulty_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[HeightRequest, NetworkDifficultyResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetNetworkDifficultyClient = grpc.ServerStreamingClient[NetworkDifficultyResponse] - -func (c *baseNodeClient) GetNewBlockTemplate(ctx context.Context, in *NewBlockTemplateRequest, opts ...grpc.CallOption) (*NewBlockTemplateResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(NewBlockTemplateResponse) - err := c.cc.Invoke(ctx, BaseNode_GetNewBlockTemplate_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetNewBlock(ctx context.Context, in *block.NewBlockTemplate, opts ...grpc.CallOption) (*GetNewBlockResult, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetNewBlockResult) - err := c.cc.Invoke(ctx, BaseNode_GetNewBlock_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetNewBlockWithCoinbases(ctx context.Context, in *GetNewBlockWithCoinbasesRequest, opts ...grpc.CallOption) (*GetNewBlockResult, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetNewBlockResult) - err := c.cc.Invoke(ctx, BaseNode_GetNewBlockWithCoinbases_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetNewBlockTemplateWithCoinbases(ctx context.Context, in *GetNewBlockTemplateWithCoinbasesRequest, opts ...grpc.CallOption) (*GetNewBlockResult, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetNewBlockResult) - err := c.cc.Invoke(ctx, BaseNode_GetNewBlockTemplateWithCoinbases_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetNewBlockBlob(ctx context.Context, in *block.NewBlockTemplate, opts ...grpc.CallOption) (*GetNewBlockBlobResult, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetNewBlockBlobResult) - err := c.cc.Invoke(ctx, BaseNode_GetNewBlockBlob_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) SubmitBlock(ctx context.Context, in *block.Block, opts ...grpc.CallOption) (*SubmitBlockResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SubmitBlockResponse) - err := c.cc.Invoke(ctx, BaseNode_SubmitBlock_FullMethodName, in, out, cOpts...) - fmt.Println("[submit_block resp]:", out) - fmt.Println("[submit_block error]:", err) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) SubmitBlockBlob(ctx context.Context, in *BlockBlobRequest, opts ...grpc.CallOption) (*SubmitBlockResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SubmitBlockResponse) - err := c.cc.Invoke(ctx, BaseNode_SubmitBlockBlob_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) SubmitTransaction(ctx context.Context, in *SubmitTransactionRequest, opts ...grpc.CallOption) (*SubmitTransactionResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SubmitTransactionResponse) - err := c.cc.Invoke(ctx, BaseNode_SubmitTransaction_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetSyncInfo(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*SyncInfoResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SyncInfoResponse) - err := c.cc.Invoke(ctx, BaseNode_GetSyncInfo_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetSyncProgress(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*SyncProgressResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(SyncProgressResponse) - err := c.cc.Invoke(ctx, BaseNode_GetSyncProgress_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetTipInfo(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*TipInfoResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(TipInfoResponse) - err := c.cc.Invoke(ctx, BaseNode_GetTipInfo_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) SearchKernels(ctx context.Context, in *SearchKernelsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[block.HistoricalBlock], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[4], BaseNode_SearchKernels_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[SearchKernelsRequest, block.HistoricalBlock]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_SearchKernelsClient = grpc.ServerStreamingClient[block.HistoricalBlock] - -func (c *baseNodeClient) SearchUtxos(ctx context.Context, in *SearchUtxosRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[block.HistoricalBlock], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[5], BaseNode_SearchUtxos_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[SearchUtxosRequest, block.HistoricalBlock]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_SearchUtxosClient = grpc.ServerStreamingClient[block.HistoricalBlock] - -func (c *baseNodeClient) FetchMatchingUtxos(ctx context.Context, in *FetchMatchingUtxosRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[FetchMatchingUtxosResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[6], BaseNode_FetchMatchingUtxos_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[FetchMatchingUtxosRequest, FetchMatchingUtxosResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_FetchMatchingUtxosClient = grpc.ServerStreamingClient[FetchMatchingUtxosResponse] - -func (c *baseNodeClient) GetPeers(ctx context.Context, in *GetPeersRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetPeersResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[7], BaseNode_GetPeers_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[GetPeersRequest, GetPeersResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetPeersClient = grpc.ServerStreamingClient[GetPeersResponse] - -func (c *baseNodeClient) GetMempoolTransactions(ctx context.Context, in *GetMempoolTransactionsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetMempoolTransactionsResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[8], BaseNode_GetMempoolTransactions_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[GetMempoolTransactionsRequest, GetMempoolTransactionsResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetMempoolTransactionsClient = grpc.ServerStreamingClient[GetMempoolTransactionsResponse] - -func (c *baseNodeClient) TransactionState(ctx context.Context, in *TransactionStateRequest, opts ...grpc.CallOption) (*TransactionStateResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(TransactionStateResponse) - err := c.cc.Invoke(ctx, BaseNode_TransactionState_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) Identify(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.NodeIdentity, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(net_work.NodeIdentity) - err := c.cc.Invoke(ctx, BaseNode_Identify_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetNetworkStatus(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.NetworkStatusResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(net_work.NetworkStatusResponse) - err := c.cc.Invoke(ctx, BaseNode_GetNetworkStatus_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) ListConnectedPeers(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*net_work.ListConnectedPeersResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(net_work.ListConnectedPeersResponse) - err := c.cc.Invoke(ctx, BaseNode_ListConnectedPeers_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetMempoolStats(ctx context.Context, in *types.Empty, opts ...grpc.CallOption) (*MempoolStatsResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(MempoolStatsResponse) - err := c.cc.Invoke(ctx, BaseNode_GetMempoolStats_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetActiveValidatorNodes(ctx context.Context, in *GetActiveValidatorNodesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetActiveValidatorNodesResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[9], BaseNode_GetActiveValidatorNodes_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[GetActiveValidatorNodesRequest, GetActiveValidatorNodesResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetActiveValidatorNodesClient = grpc.ServerStreamingClient[GetActiveValidatorNodesResponse] - -func (c *baseNodeClient) GetShardKey(ctx context.Context, in *GetShardKeyRequest, opts ...grpc.CallOption) (*GetShardKeyResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetShardKeyResponse) - err := c.cc.Invoke(ctx, BaseNode_GetShardKey_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) GetTemplateRegistrations(ctx context.Context, in *GetTemplateRegistrationsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetTemplateRegistrationResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[10], BaseNode_GetTemplateRegistrations_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[GetTemplateRegistrationsRequest, GetTemplateRegistrationResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetTemplateRegistrationsClient = grpc.ServerStreamingClient[GetTemplateRegistrationResponse] - -func (c *baseNodeClient) GetSideChainUtxos(ctx context.Context, in *GetSideChainUtxosRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[GetSideChainUtxosResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[11], BaseNode_GetSideChainUtxos_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[GetSideChainUtxosRequest, GetSideChainUtxosResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetSideChainUtxosClient = grpc.ServerStreamingClient[GetSideChainUtxosResponse] - -func (c *baseNodeClient) GetNetworkState(ctx context.Context, in *GetNetworkStateRequest, opts ...grpc.CallOption) (*GetNetworkStateResponse, error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - out := new(GetNetworkStateResponse) - err := c.cc.Invoke(ctx, BaseNode_GetNetworkState_FullMethodName, in, out, cOpts...) - if err != nil { - return nil, err - } - return out, nil -} - -func (c *baseNodeClient) SearchPaymentReferences(ctx context.Context, in *SearchPaymentReferencesRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PaymentReferenceResponse], error) { - cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) - stream, err := c.cc.NewStream(ctx, &BaseNode_ServiceDesc.Streams[12], BaseNode_SearchPaymentReferences_FullMethodName, cOpts...) - if err != nil { - return nil, err - } - x := &grpc.GenericClientStream[SearchPaymentReferencesRequest, PaymentReferenceResponse]{ClientStream: stream} - if err := x.ClientStream.SendMsg(in); err != nil { - return nil, err - } - if err := x.ClientStream.CloseSend(); err != nil { - return nil, err - } - return x, nil -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_SearchPaymentReferencesClient = grpc.ServerStreamingClient[PaymentReferenceResponse] - -// BaseNodeServer is the server API for BaseNode service. -// All implementations must embed UnimplementedBaseNodeServer -// for forward compatibility. -// -// The gRPC interface for interacting with the base node. -type BaseNodeServer interface { - // Lists headers in the current best chain - ListHeaders(*ListHeadersRequest, grpc.ServerStreamingServer[BlockHeaderResponse]) error - // Get header by hash - GetHeaderByHash(context.Context, *GetHeaderByHashRequest) (*BlockHeaderResponse, error) - // Returns blocks in the current best chain. Currently only supports querying by height - GetBlocks(*GetBlocksRequest, grpc.ServerStreamingServer[block.HistoricalBlock]) error - // Returns the block timing for the chain heights - GetBlockTiming(context.Context, *HeightRequest) (*BlockTimingResponse, error) - // Returns the network Constants - GetConstants(context.Context, *types.BlockHeight) (*types.ConsensusConstants, error) - // Returns Block Sizes - GetBlockSize(context.Context, *BlockGroupRequest) (*BlockGroupResponse, error) - // Returns Block Fees - GetBlockFees(context.Context, *BlockGroupRequest) (*BlockGroupResponse, error) - // Get Version - GetVersion(context.Context, *types.Empty) (*StringValue, error) - // Check for new updates - CheckForUpdates(context.Context, *types.Empty) (*net_work.SoftwareUpdate, error) - // Get coins in circulation - GetTokensInCirculation(*GetBlocksRequest, grpc.ServerStreamingServer[ValueAtHeightResponse]) error - // Get network difficulties - GetNetworkDifficulty(*HeightRequest, grpc.ServerStreamingServer[NetworkDifficultyResponse]) error - // Get the block template - GetNewBlockTemplate(context.Context, *NewBlockTemplateRequest) (*NewBlockTemplateResponse, error) - // Construct a new block from a provided template - GetNewBlock(context.Context, *block.NewBlockTemplate) (*GetNewBlockResult, error) - // Construct a new block from a provided template - GetNewBlockWithCoinbases(context.Context, *GetNewBlockWithCoinbasesRequest) (*GetNewBlockResult, error) - // Construct a new block from a provided template - GetNewBlockTemplateWithCoinbases(context.Context, *GetNewBlockTemplateWithCoinbasesRequest) (*GetNewBlockResult, error) - // Construct a new block and header blob from a provided template - GetNewBlockBlob(context.Context, *block.NewBlockTemplate) (*GetNewBlockBlobResult, error) - // Submit a new block for propagation - SubmitBlock(context.Context, *block.Block) (*SubmitBlockResponse, error) - // Submit a new mined block blob for propagation - SubmitBlockBlob(context.Context, *BlockBlobRequest) (*SubmitBlockResponse, error) - // Submit a transaction for propagation - SubmitTransaction(context.Context, *SubmitTransactionRequest) (*SubmitTransactionResponse, error) - // Get the base node sync information - GetSyncInfo(context.Context, *types.Empty) (*SyncInfoResponse, error) - // Get the base node sync information - GetSyncProgress(context.Context, *types.Empty) (*SyncProgressResponse, error) - // Get the base node tip information - GetTipInfo(context.Context, *types.Empty) (*TipInfoResponse, error) - // Search for blocks containing the specified kernels - SearchKernels(*SearchKernelsRequest, grpc.ServerStreamingServer[block.HistoricalBlock]) error - // Search for blocks containing the specified commitments - SearchUtxos(*SearchUtxosRequest, grpc.ServerStreamingServer[block.HistoricalBlock]) error - // Fetch any utxos that exist in the main chain - FetchMatchingUtxos(*FetchMatchingUtxosRequest, grpc.ServerStreamingServer[FetchMatchingUtxosResponse]) error - // get all peers from the base node - GetPeers(*GetPeersRequest, grpc.ServerStreamingServer[GetPeersResponse]) error - GetMempoolTransactions(*GetMempoolTransactionsRequest, grpc.ServerStreamingServer[GetMempoolTransactionsResponse]) error - TransactionState(context.Context, *TransactionStateRequest) (*TransactionStateResponse, error) - // This returns the node's network identity - Identify(context.Context, *types.Empty) (*net_work.NodeIdentity, error) - // Get Base Node network connectivity status - GetNetworkStatus(context.Context, *types.Empty) (*net_work.NetworkStatusResponse, error) - // List currently connected peers - ListConnectedPeers(context.Context, *types.Empty) (*net_work.ListConnectedPeersResponse, error) - // Get mempool stats - GetMempoolStats(context.Context, *types.Empty) (*MempoolStatsResponse, error) - // Get VNs - GetActiveValidatorNodes(*GetActiveValidatorNodesRequest, grpc.ServerStreamingServer[GetActiveValidatorNodesResponse]) error - GetShardKey(context.Context, *GetShardKeyRequest) (*GetShardKeyResponse, error) - // Get templates - GetTemplateRegistrations(*GetTemplateRegistrationsRequest, grpc.ServerStreamingServer[GetTemplateRegistrationResponse]) error - GetSideChainUtxos(*GetSideChainUtxosRequest, grpc.ServerStreamingServer[GetSideChainUtxosResponse]) error - GetNetworkState(context.Context, *GetNetworkStateRequest) (*GetNetworkStateResponse, error) - // PayRef (Payment Reference) lookup for block explorers and external services - SearchPaymentReferences(*SearchPaymentReferencesRequest, grpc.ServerStreamingServer[PaymentReferenceResponse]) error - mustEmbedUnimplementedBaseNodeServer() -} - -// UnimplementedBaseNodeServer must be embedded to have -// forward compatible implementations. -// -// NOTE: this should be embedded by value instead of pointer to avoid a nil -// pointer dereference when methods are called. -type UnimplementedBaseNodeServer struct{} - -func (UnimplementedBaseNodeServer) ListHeaders(*ListHeadersRequest, grpc.ServerStreamingServer[BlockHeaderResponse]) error { - return status.Errorf(codes.Unimplemented, "method ListHeaders not implemented") -} -func (UnimplementedBaseNodeServer) GetHeaderByHash(context.Context, *GetHeaderByHashRequest) (*BlockHeaderResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetHeaderByHash not implemented") -} -func (UnimplementedBaseNodeServer) GetBlocks(*GetBlocksRequest, grpc.ServerStreamingServer[block.HistoricalBlock]) error { - return status.Errorf(codes.Unimplemented, "method GetBlocks not implemented") -} -func (UnimplementedBaseNodeServer) GetBlockTiming(context.Context, *HeightRequest) (*BlockTimingResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBlockTiming not implemented") -} -func (UnimplementedBaseNodeServer) GetConstants(context.Context, *types.BlockHeight) (*types.ConsensusConstants, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetConstants not implemented") -} -func (UnimplementedBaseNodeServer) GetBlockSize(context.Context, *BlockGroupRequest) (*BlockGroupResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBlockSize not implemented") -} -func (UnimplementedBaseNodeServer) GetBlockFees(context.Context, *BlockGroupRequest) (*BlockGroupResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetBlockFees not implemented") -} -func (UnimplementedBaseNodeServer) GetVersion(context.Context, *types.Empty) (*StringValue, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetVersion not implemented") -} -func (UnimplementedBaseNodeServer) CheckForUpdates(context.Context, *types.Empty) (*net_work.SoftwareUpdate, error) { - return nil, status.Errorf(codes.Unimplemented, "method CheckForUpdates not implemented") -} -func (UnimplementedBaseNodeServer) GetTokensInCirculation(*GetBlocksRequest, grpc.ServerStreamingServer[ValueAtHeightResponse]) error { - return status.Errorf(codes.Unimplemented, "method GetTokensInCirculation not implemented") -} -func (UnimplementedBaseNodeServer) GetNetworkDifficulty(*HeightRequest, grpc.ServerStreamingServer[NetworkDifficultyResponse]) error { - return status.Errorf(codes.Unimplemented, "method GetNetworkDifficulty not implemented") -} -func (UnimplementedBaseNodeServer) GetNewBlockTemplate(context.Context, *NewBlockTemplateRequest) (*NewBlockTemplateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNewBlockTemplate not implemented") -} -func (UnimplementedBaseNodeServer) GetNewBlock(context.Context, *block.NewBlockTemplate) (*GetNewBlockResult, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNewBlock not implemented") -} -func (UnimplementedBaseNodeServer) GetNewBlockWithCoinbases(context.Context, *GetNewBlockWithCoinbasesRequest) (*GetNewBlockResult, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNewBlockWithCoinbases not implemented") -} -func (UnimplementedBaseNodeServer) GetNewBlockTemplateWithCoinbases(context.Context, *GetNewBlockTemplateWithCoinbasesRequest) (*GetNewBlockResult, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNewBlockTemplateWithCoinbases not implemented") -} -func (UnimplementedBaseNodeServer) GetNewBlockBlob(context.Context, *block.NewBlockTemplate) (*GetNewBlockBlobResult, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNewBlockBlob not implemented") -} -func (UnimplementedBaseNodeServer) SubmitBlock(context.Context, *block.Block) (*SubmitBlockResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SubmitBlock not implemented") -} -func (UnimplementedBaseNodeServer) SubmitBlockBlob(context.Context, *BlockBlobRequest) (*SubmitBlockResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SubmitBlockBlob not implemented") -} -func (UnimplementedBaseNodeServer) SubmitTransaction(context.Context, *SubmitTransactionRequest) (*SubmitTransactionResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method SubmitTransaction not implemented") -} -func (UnimplementedBaseNodeServer) GetSyncInfo(context.Context, *types.Empty) (*SyncInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetSyncInfo not implemented") -} -func (UnimplementedBaseNodeServer) GetSyncProgress(context.Context, *types.Empty) (*SyncProgressResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetSyncProgress not implemented") -} -func (UnimplementedBaseNodeServer) GetTipInfo(context.Context, *types.Empty) (*TipInfoResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetTipInfo not implemented") -} -func (UnimplementedBaseNodeServer) SearchKernels(*SearchKernelsRequest, grpc.ServerStreamingServer[block.HistoricalBlock]) error { - return status.Errorf(codes.Unimplemented, "method SearchKernels not implemented") -} -func (UnimplementedBaseNodeServer) SearchUtxos(*SearchUtxosRequest, grpc.ServerStreamingServer[block.HistoricalBlock]) error { - return status.Errorf(codes.Unimplemented, "method SearchUtxos not implemented") -} -func (UnimplementedBaseNodeServer) FetchMatchingUtxos(*FetchMatchingUtxosRequest, grpc.ServerStreamingServer[FetchMatchingUtxosResponse]) error { - return status.Errorf(codes.Unimplemented, "method FetchMatchingUtxos not implemented") -} -func (UnimplementedBaseNodeServer) GetPeers(*GetPeersRequest, grpc.ServerStreamingServer[GetPeersResponse]) error { - return status.Errorf(codes.Unimplemented, "method GetPeers not implemented") -} -func (UnimplementedBaseNodeServer) GetMempoolTransactions(*GetMempoolTransactionsRequest, grpc.ServerStreamingServer[GetMempoolTransactionsResponse]) error { - return status.Errorf(codes.Unimplemented, "method GetMempoolTransactions not implemented") -} -func (UnimplementedBaseNodeServer) TransactionState(context.Context, *TransactionStateRequest) (*TransactionStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method TransactionState not implemented") -} -func (UnimplementedBaseNodeServer) Identify(context.Context, *types.Empty) (*net_work.NodeIdentity, error) { - return nil, status.Errorf(codes.Unimplemented, "method Identify not implemented") -} -func (UnimplementedBaseNodeServer) GetNetworkStatus(context.Context, *types.Empty) (*net_work.NetworkStatusResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNetworkStatus not implemented") -} -func (UnimplementedBaseNodeServer) ListConnectedPeers(context.Context, *types.Empty) (*net_work.ListConnectedPeersResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method ListConnectedPeers not implemented") -} -func (UnimplementedBaseNodeServer) GetMempoolStats(context.Context, *types.Empty) (*MempoolStatsResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetMempoolStats not implemented") -} -func (UnimplementedBaseNodeServer) GetActiveValidatorNodes(*GetActiveValidatorNodesRequest, grpc.ServerStreamingServer[GetActiveValidatorNodesResponse]) error { - return status.Errorf(codes.Unimplemented, "method GetActiveValidatorNodes not implemented") -} -func (UnimplementedBaseNodeServer) GetShardKey(context.Context, *GetShardKeyRequest) (*GetShardKeyResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetShardKey not implemented") -} -func (UnimplementedBaseNodeServer) GetTemplateRegistrations(*GetTemplateRegistrationsRequest, grpc.ServerStreamingServer[GetTemplateRegistrationResponse]) error { - return status.Errorf(codes.Unimplemented, "method GetTemplateRegistrations not implemented") -} -func (UnimplementedBaseNodeServer) GetSideChainUtxos(*GetSideChainUtxosRequest, grpc.ServerStreamingServer[GetSideChainUtxosResponse]) error { - return status.Errorf(codes.Unimplemented, "method GetSideChainUtxos not implemented") -} -func (UnimplementedBaseNodeServer) GetNetworkState(context.Context, *GetNetworkStateRequest) (*GetNetworkStateResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetNetworkState not implemented") -} -func (UnimplementedBaseNodeServer) SearchPaymentReferences(*SearchPaymentReferencesRequest, grpc.ServerStreamingServer[PaymentReferenceResponse]) error { - return status.Errorf(codes.Unimplemented, "method SearchPaymentReferences not implemented") -} -func (UnimplementedBaseNodeServer) mustEmbedUnimplementedBaseNodeServer() {} -func (UnimplementedBaseNodeServer) testEmbeddedByValue() {} - -// UnsafeBaseNodeServer may be embedded to opt out of forward compatibility for this service. -// Use of this interface is not recommended, as added methods to BaseNodeServer will -// result in compilation errors. -type UnsafeBaseNodeServer interface { - mustEmbedUnimplementedBaseNodeServer() -} - -func RegisterBaseNodeServer(s grpc.ServiceRegistrar, srv BaseNodeServer) { - // If the following call pancis, it indicates UnimplementedBaseNodeServer was - // embedded by pointer and is nil. This will cause panics if an - // unimplemented method is ever invoked, so we test this at initialization - // time to prevent it from happening at runtime later due to I/O. - if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { - t.testEmbeddedByValue() - } - s.RegisterService(&BaseNode_ServiceDesc, srv) -} - -func _BaseNode_ListHeaders_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(ListHeadersRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).ListHeaders(m, &grpc.GenericServerStream[ListHeadersRequest, BlockHeaderResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_ListHeadersServer = grpc.ServerStreamingServer[BlockHeaderResponse] - -func _BaseNode_GetHeaderByHash_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetHeaderByHashRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetHeaderByHash(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetHeaderByHash_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetHeaderByHash(ctx, req.(*GetHeaderByHashRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetBlocks_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetBlocksRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetBlocks(m, &grpc.GenericServerStream[GetBlocksRequest, block.HistoricalBlock]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetBlocksServer = grpc.ServerStreamingServer[block.HistoricalBlock] - -func _BaseNode_GetBlockTiming_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(HeightRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetBlockTiming(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetBlockTiming_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetBlockTiming(ctx, req.(*HeightRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetConstants_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.BlockHeight) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetConstants(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetConstants_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetConstants(ctx, req.(*types.BlockHeight)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetBlockSize_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(BlockGroupRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetBlockSize(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetBlockSize_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetBlockSize(ctx, req.(*BlockGroupRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetBlockFees_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(BlockGroupRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetBlockFees(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetBlockFees_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetBlockFees(ctx, req.(*BlockGroupRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetVersion_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetVersion(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetVersion_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetVersion(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_CheckForUpdates_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).CheckForUpdates(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_CheckForUpdates_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).CheckForUpdates(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetTokensInCirculation_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetBlocksRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetTokensInCirculation(m, &grpc.GenericServerStream[GetBlocksRequest, ValueAtHeightResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetTokensInCirculationServer = grpc.ServerStreamingServer[ValueAtHeightResponse] - -func _BaseNode_GetNetworkDifficulty_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(HeightRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetNetworkDifficulty(m, &grpc.GenericServerStream[HeightRequest, NetworkDifficultyResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetNetworkDifficultyServer = grpc.ServerStreamingServer[NetworkDifficultyResponse] - -func _BaseNode_GetNewBlockTemplate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(NewBlockTemplateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetNewBlockTemplate(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetNewBlockTemplate_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetNewBlockTemplate(ctx, req.(*NewBlockTemplateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetNewBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(block.NewBlockTemplate) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetNewBlock(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetNewBlock_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetNewBlock(ctx, req.(*block.NewBlockTemplate)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetNewBlockWithCoinbases_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetNewBlockWithCoinbasesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetNewBlockWithCoinbases(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetNewBlockWithCoinbases_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetNewBlockWithCoinbases(ctx, req.(*GetNewBlockWithCoinbasesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetNewBlockTemplateWithCoinbases_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetNewBlockTemplateWithCoinbasesRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetNewBlockTemplateWithCoinbases(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetNewBlockTemplateWithCoinbases_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetNewBlockTemplateWithCoinbases(ctx, req.(*GetNewBlockTemplateWithCoinbasesRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetNewBlockBlob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(block.NewBlockTemplate) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetNewBlockBlob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetNewBlockBlob_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetNewBlockBlob(ctx, req.(*block.NewBlockTemplate)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_SubmitBlock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(block.Block) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).SubmitBlock(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_SubmitBlock_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).SubmitBlock(ctx, req.(*block.Block)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_SubmitBlockBlob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(BlockBlobRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).SubmitBlockBlob(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_SubmitBlockBlob_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).SubmitBlockBlob(ctx, req.(*BlockBlobRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_SubmitTransaction_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SubmitTransactionRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).SubmitTransaction(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_SubmitTransaction_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).SubmitTransaction(ctx, req.(*SubmitTransactionRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetSyncInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetSyncInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetSyncInfo_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetSyncInfo(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetSyncProgress_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetSyncProgress(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetSyncProgress_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetSyncProgress(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetTipInfo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetTipInfo(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetTipInfo_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetTipInfo(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_SearchKernels_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SearchKernelsRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).SearchKernels(m, &grpc.GenericServerStream[SearchKernelsRequest, block.HistoricalBlock]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_SearchKernelsServer = grpc.ServerStreamingServer[block.HistoricalBlock] - -func _BaseNode_SearchUtxos_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SearchUtxosRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).SearchUtxos(m, &grpc.GenericServerStream[SearchUtxosRequest, block.HistoricalBlock]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_SearchUtxosServer = grpc.ServerStreamingServer[block.HistoricalBlock] - -func _BaseNode_FetchMatchingUtxos_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(FetchMatchingUtxosRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).FetchMatchingUtxos(m, &grpc.GenericServerStream[FetchMatchingUtxosRequest, FetchMatchingUtxosResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_FetchMatchingUtxosServer = grpc.ServerStreamingServer[FetchMatchingUtxosResponse] - -func _BaseNode_GetPeers_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetPeersRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetPeers(m, &grpc.GenericServerStream[GetPeersRequest, GetPeersResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetPeersServer = grpc.ServerStreamingServer[GetPeersResponse] - -func _BaseNode_GetMempoolTransactions_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetMempoolTransactionsRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetMempoolTransactions(m, &grpc.GenericServerStream[GetMempoolTransactionsRequest, GetMempoolTransactionsResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetMempoolTransactionsServer = grpc.ServerStreamingServer[GetMempoolTransactionsResponse] - -func _BaseNode_TransactionState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(TransactionStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).TransactionState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_TransactionState_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).TransactionState(ctx, req.(*TransactionStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_Identify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).Identify(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_Identify_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).Identify(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetNetworkStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetNetworkStatus(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetNetworkStatus_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetNetworkStatus(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_ListConnectedPeers_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).ListConnectedPeers(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_ListConnectedPeers_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).ListConnectedPeers(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetMempoolStats_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetMempoolStats(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetMempoolStats_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetMempoolStats(ctx, req.(*types.Empty)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetActiveValidatorNodes_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetActiveValidatorNodesRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetActiveValidatorNodes(m, &grpc.GenericServerStream[GetActiveValidatorNodesRequest, GetActiveValidatorNodesResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetActiveValidatorNodesServer = grpc.ServerStreamingServer[GetActiveValidatorNodesResponse] - -func _BaseNode_GetShardKey_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetShardKeyRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetShardKey(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetShardKey_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetShardKey(ctx, req.(*GetShardKeyRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_GetTemplateRegistrations_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetTemplateRegistrationsRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetTemplateRegistrations(m, &grpc.GenericServerStream[GetTemplateRegistrationsRequest, GetTemplateRegistrationResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetTemplateRegistrationsServer = grpc.ServerStreamingServer[GetTemplateRegistrationResponse] - -func _BaseNode_GetSideChainUtxos_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(GetSideChainUtxosRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).GetSideChainUtxos(m, &grpc.GenericServerStream[GetSideChainUtxosRequest, GetSideChainUtxosResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_GetSideChainUtxosServer = grpc.ServerStreamingServer[GetSideChainUtxosResponse] - -func _BaseNode_GetNetworkState_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(GetNetworkStateRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BaseNodeServer).GetNetworkState(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: BaseNode_GetNetworkState_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BaseNodeServer).GetNetworkState(ctx, req.(*GetNetworkStateRequest)) - } - return interceptor(ctx, in, info, handler) -} - -func _BaseNode_SearchPaymentReferences_Handler(srv interface{}, stream grpc.ServerStream) error { - m := new(SearchPaymentReferencesRequest) - if err := stream.RecvMsg(m); err != nil { - return err - } - return srv.(BaseNodeServer).SearchPaymentReferences(m, &grpc.GenericServerStream[SearchPaymentReferencesRequest, PaymentReferenceResponse]{ServerStream: stream}) -} - -// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name. -type BaseNode_SearchPaymentReferencesServer = grpc.ServerStreamingServer[PaymentReferenceResponse] - -// BaseNode_ServiceDesc is the grpc.ServiceDesc for BaseNode service. -// It's only intended for direct use with grpc.RegisterService, -// and not to be introspected or modified (even as a copy) -var BaseNode_ServiceDesc = grpc.ServiceDesc{ - ServiceName: "tari.rpc.BaseNode", - HandlerType: (*BaseNodeServer)(nil), - Methods: []grpc.MethodDesc{ - { - MethodName: "GetHeaderByHash", - Handler: _BaseNode_GetHeaderByHash_Handler, - }, - { - MethodName: "GetBlockTiming", - Handler: _BaseNode_GetBlockTiming_Handler, - }, - { - MethodName: "GetConstants", - Handler: _BaseNode_GetConstants_Handler, - }, - { - MethodName: "GetBlockSize", - Handler: _BaseNode_GetBlockSize_Handler, - }, - { - MethodName: "GetBlockFees", - Handler: _BaseNode_GetBlockFees_Handler, - }, - { - MethodName: "GetVersion", - Handler: _BaseNode_GetVersion_Handler, - }, - { - MethodName: "CheckForUpdates", - Handler: _BaseNode_CheckForUpdates_Handler, - }, - { - MethodName: "GetNewBlockTemplate", - Handler: _BaseNode_GetNewBlockTemplate_Handler, - }, - { - MethodName: "GetNewBlock", - Handler: _BaseNode_GetNewBlock_Handler, - }, - { - MethodName: "GetNewBlockWithCoinbases", - Handler: _BaseNode_GetNewBlockWithCoinbases_Handler, - }, - { - MethodName: "GetNewBlockTemplateWithCoinbases", - Handler: _BaseNode_GetNewBlockTemplateWithCoinbases_Handler, - }, - { - MethodName: "GetNewBlockBlob", - Handler: _BaseNode_GetNewBlockBlob_Handler, - }, - { - MethodName: "SubmitBlock", - Handler: _BaseNode_SubmitBlock_Handler, - }, - { - MethodName: "SubmitBlockBlob", - Handler: _BaseNode_SubmitBlockBlob_Handler, - }, - { - MethodName: "SubmitTransaction", - Handler: _BaseNode_SubmitTransaction_Handler, - }, - { - MethodName: "GetSyncInfo", - Handler: _BaseNode_GetSyncInfo_Handler, - }, - { - MethodName: "GetSyncProgress", - Handler: _BaseNode_GetSyncProgress_Handler, - }, - { - MethodName: "GetTipInfo", - Handler: _BaseNode_GetTipInfo_Handler, - }, - { - MethodName: "TransactionState", - Handler: _BaseNode_TransactionState_Handler, - }, - { - MethodName: "Identify", - Handler: _BaseNode_Identify_Handler, - }, - { - MethodName: "GetNetworkStatus", - Handler: _BaseNode_GetNetworkStatus_Handler, - }, - { - MethodName: "ListConnectedPeers", - Handler: _BaseNode_ListConnectedPeers_Handler, - }, - { - MethodName: "GetMempoolStats", - Handler: _BaseNode_GetMempoolStats_Handler, - }, - { - MethodName: "GetShardKey", - Handler: _BaseNode_GetShardKey_Handler, - }, - { - MethodName: "GetNetworkState", - Handler: _BaseNode_GetNetworkState_Handler, - }, - }, - Streams: []grpc.StreamDesc{ - { - StreamName: "ListHeaders", - Handler: _BaseNode_ListHeaders_Handler, - ServerStreams: true, - }, - { - StreamName: "GetBlocks", - Handler: _BaseNode_GetBlocks_Handler, - ServerStreams: true, - }, - { - StreamName: "GetTokensInCirculation", - Handler: _BaseNode_GetTokensInCirculation_Handler, - ServerStreams: true, - }, - { - StreamName: "GetNetworkDifficulty", - Handler: _BaseNode_GetNetworkDifficulty_Handler, - ServerStreams: true, - }, - { - StreamName: "SearchKernels", - Handler: _BaseNode_SearchKernels_Handler, - ServerStreams: true, - }, - { - StreamName: "SearchUtxos", - Handler: _BaseNode_SearchUtxos_Handler, - ServerStreams: true, - }, - { - StreamName: "FetchMatchingUtxos", - Handler: _BaseNode_FetchMatchingUtxos_Handler, - ServerStreams: true, - }, - { - StreamName: "GetPeers", - Handler: _BaseNode_GetPeers_Handler, - ServerStreams: true, - }, - { - StreamName: "GetMempoolTransactions", - Handler: _BaseNode_GetMempoolTransactions_Handler, - ServerStreams: true, - }, - { - StreamName: "GetActiveValidatorNodes", - Handler: _BaseNode_GetActiveValidatorNodes_Handler, - ServerStreams: true, - }, - { - StreamName: "GetTemplateRegistrations", - Handler: _BaseNode_GetTemplateRegistrations_Handler, - ServerStreams: true, - }, - { - StreamName: "GetSideChainUtxos", - Handler: _BaseNode_GetSideChainUtxos_Handler, - ServerStreams: true, - }, - { - StreamName: "SearchPaymentReferences", - Handler: _BaseNode_SearchPaymentReferences_Handler, - ServerStreams: true, - }, - }, - Metadata: "base_node.proto", -} diff --git a/internal/gbt/tari/proto/block.proto b/internal/gbt/tari/proto/block.proto deleted file mode 100644 index 9a4971c..0000000 --- a/internal/gbt/tari/proto/block.proto +++ /dev/null @@ -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; -} - diff --git a/internal/gbt/tari/proto/block/block.pb.go b/internal/gbt/tari/proto/block/block.pb.go deleted file mode 100644 index 428b15b..0000000 --- a/internal/gbt/tari/proto/block/block.pb.go +++ /dev/null @@ -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 -} diff --git a/internal/gbt/tari/proto/net_work/network.pb.go b/internal/gbt/tari/proto/net_work/network.pb.go deleted file mode 100644 index fae006c..0000000 --- a/internal/gbt/tari/proto/net_work/network.pb.go +++ /dev/null @@ -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 -} diff --git a/internal/gbt/tari/proto/network.proto b/internal/gbt/tari/proto/network.proto deleted file mode 100644 index fba0614..0000000 --- a/internal/gbt/tari/proto/network.proto +++ /dev/null @@ -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; -} diff --git a/internal/gbt/tari/proto/p2pool.proto b/internal/gbt/tari/proto/p2pool.proto deleted file mode 100644 index bb5fd37..0000000 --- a/internal/gbt/tari/proto/p2pool.proto +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/internal/gbt/tari/proto/sidechain_types.proto b/internal/gbt/tari/proto/sidechain_types.proto deleted file mode 100644 index 184a321..0000000 --- a/internal/gbt/tari/proto/sidechain_types.proto +++ /dev/null @@ -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; -} diff --git a/internal/gbt/tari/proto/sidechain_types/sidechain_types.pb.go b/internal/gbt/tari/proto/sidechain_types/sidechain_types.pb.go deleted file mode 100644 index c6eb653..0000000 --- a/internal/gbt/tari/proto/sidechain_types/sidechain_types.pb.go +++ /dev/null @@ -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 -} diff --git a/internal/gbt/tari/proto/transaction.proto b/internal/gbt/tari/proto/transaction.proto deleted file mode 100644 index 0e8ab2c..0000000 --- a/internal/gbt/tari/proto/transaction.proto +++ /dev/null @@ -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; -} - diff --git a/internal/gbt/tari/proto/transaction/transaction.pb.go b/internal/gbt/tari/proto/transaction/transaction.pb.go deleted file mode 100644 index f9b355a..0000000 --- a/internal/gbt/tari/proto/transaction/transaction.pb.go +++ /dev/null @@ -1,1012 +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: transaction.proto - -package transaction - -import ( - sidechain_types "pool/internal/gbt/tari/proto/sidechain_types" - 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) -) - -// 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. -type TransactionKernel struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Options for a kernel's structure or use - Features uint32 `protobuf:"varint,1,opt,name=features,proto3" json:"features,omitempty"` - // / Fee originally included in the transaction this proof is for (in MicroMinotari) - Fee uint64 `protobuf:"varint,2,opt,name=fee,proto3" json:"fee,omitempty"` - // This kernel is not valid earlier than lock_height blocks - // The max lock_height of all *inputs* to this transaction - LockHeight uint64 `protobuf:"varint,3,opt,name=lock_height,json=lockHeight,proto3" json:"lock_height,omitempty"` - // 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. - Excess []byte `protobuf:"bytes,6,opt,name=excess,proto3" json:"excess,omitempty"` - // The signature proving the excess is a valid public key, which signs - // the transaction fee. - ExcessSig *types.Signature `protobuf:"bytes,7,opt,name=excess_sig,json=excessSig,proto3" json:"excess_sig,omitempty"` - // The hash of the kernel, as it appears in the MMR - Hash []byte `protobuf:"bytes,8,opt,name=hash,proto3" json:"hash,omitempty"` - // Version - Version uint32 `protobuf:"varint,9,opt,name=version,proto3" json:"version,omitempty"` - // Optional burned commitment - BurnCommitment []byte `protobuf:"bytes,10,opt,name=burn_commitment,json=burnCommitment,proto3" json:"burn_commitment,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TransactionKernel) Reset() { - *x = TransactionKernel{} - mi := &file_transaction_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TransactionKernel) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransactionKernel) ProtoMessage() {} - -func (x *TransactionKernel) ProtoReflect() protoreflect.Message { - mi := &file_transaction_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 TransactionKernel.ProtoReflect.Descriptor instead. -func (*TransactionKernel) Descriptor() ([]byte, []int) { - return file_transaction_proto_rawDescGZIP(), []int{0} -} - -func (x *TransactionKernel) GetFeatures() uint32 { - if x != nil { - return x.Features - } - return 0 -} - -func (x *TransactionKernel) GetFee() uint64 { - if x != nil { - return x.Fee - } - return 0 -} - -func (x *TransactionKernel) GetLockHeight() uint64 { - if x != nil { - return x.LockHeight - } - return 0 -} - -func (x *TransactionKernel) GetExcess() []byte { - if x != nil { - return x.Excess - } - return nil -} - -func (x *TransactionKernel) GetExcessSig() *types.Signature { - if x != nil { - return x.ExcessSig - } - return nil -} - -func (x *TransactionKernel) GetHash() []byte { - if x != nil { - return x.Hash - } - return nil -} - -func (x *TransactionKernel) GetVersion() uint32 { - if x != nil { - return x.Version - } - return 0 -} - -func (x *TransactionKernel) GetBurnCommitment() []byte { - if x != nil { - return x.BurnCommitment - } - return nil -} - -// A transaction input. -// -// Primarily a reference to an output being spent by the transaction. -type TransactionInput struct { - state protoimpl.MessageState `protogen:"open.v1"` - // The features of the output being spent. We will check maturity for all outputs. - Features *OutputFeatures `protobuf:"bytes,1,opt,name=features,proto3" json:"features,omitempty"` - // The commitment referencing the output being spent. - Commitment []byte `protobuf:"bytes,2,opt,name=commitment,proto3" json:"commitment,omitempty"` - // Hash of the input, as it appears in the MMR - Hash []byte `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty"` - // The serialised script - Script []byte `protobuf:"bytes,4,opt,name=script,proto3" json:"script,omitempty"` - // The script input data, if any - InputData []byte `protobuf:"bytes,5,opt,name=input_data,json=inputData,proto3" json:"input_data,omitempty"` - // A signature with k_s, signing the script, input data, and mined height - ScriptSignature *types.ComAndPubSignature `protobuf:"bytes,7,opt,name=script_signature,json=scriptSignature,proto3" json:"script_signature,omitempty"` - // The offset public key, K_O - SenderOffsetPublicKey []byte `protobuf:"bytes,8,opt,name=sender_offset_public_key,json=senderOffsetPublicKey,proto3" json:"sender_offset_public_key,omitempty"` - // The hash of the output this input is spending - OutputHash []byte `protobuf:"bytes,9,opt,name=output_hash,json=outputHash,proto3" json:"output_hash,omitempty"` - // Covenant - Covenant []byte `protobuf:"bytes,10,opt,name=covenant,proto3" json:"covenant,omitempty"` - // Version - Version uint32 `protobuf:"varint,11,opt,name=version,proto3" json:"version,omitempty"` - // The encrypted data - EncryptedData []byte `protobuf:"bytes,12,opt,name=encrypted_data,json=encryptedData,proto3" json:"encrypted_data,omitempty"` - // The minimum value of the commitment that is proven by the range proof (in MicroMinotari) - MinimumValuePromise uint64 `protobuf:"varint,13,opt,name=minimum_value_promise,json=minimumValuePromise,proto3" json:"minimum_value_promise,omitempty"` - // The metadata signature for output this input is spending - MetadataSignature *types.ComAndPubSignature `protobuf:"bytes,14,opt,name=metadata_signature,json=metadataSignature,proto3" json:"metadata_signature,omitempty"` - // The rangeproof hash for output this input is spending - RangeproofHash []byte `protobuf:"bytes,15,opt,name=rangeproof_hash,json=rangeproofHash,proto3" json:"rangeproof_hash,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TransactionInput) Reset() { - *x = TransactionInput{} - mi := &file_transaction_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TransactionInput) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransactionInput) ProtoMessage() {} - -func (x *TransactionInput) ProtoReflect() protoreflect.Message { - mi := &file_transaction_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 TransactionInput.ProtoReflect.Descriptor instead. -func (*TransactionInput) Descriptor() ([]byte, []int) { - return file_transaction_proto_rawDescGZIP(), []int{1} -} - -func (x *TransactionInput) GetFeatures() *OutputFeatures { - if x != nil { - return x.Features - } - return nil -} - -func (x *TransactionInput) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -func (x *TransactionInput) GetHash() []byte { - if x != nil { - return x.Hash - } - return nil -} - -func (x *TransactionInput) GetScript() []byte { - if x != nil { - return x.Script - } - return nil -} - -func (x *TransactionInput) GetInputData() []byte { - if x != nil { - return x.InputData - } - return nil -} - -func (x *TransactionInput) GetScriptSignature() *types.ComAndPubSignature { - if x != nil { - return x.ScriptSignature - } - return nil -} - -func (x *TransactionInput) GetSenderOffsetPublicKey() []byte { - if x != nil { - return x.SenderOffsetPublicKey - } - return nil -} - -func (x *TransactionInput) GetOutputHash() []byte { - if x != nil { - return x.OutputHash - } - return nil -} - -func (x *TransactionInput) GetCovenant() []byte { - if x != nil { - return x.Covenant - } - return nil -} - -func (x *TransactionInput) GetVersion() uint32 { - if x != nil { - return x.Version - } - return 0 -} - -func (x *TransactionInput) GetEncryptedData() []byte { - if x != nil { - return x.EncryptedData - } - return nil -} - -func (x *TransactionInput) GetMinimumValuePromise() uint64 { - if x != nil { - return x.MinimumValuePromise - } - return 0 -} - -func (x *TransactionInput) GetMetadataSignature() *types.ComAndPubSignature { - if x != nil { - return x.MetadataSignature - } - return nil -} - -func (x *TransactionInput) GetRangeproofHash() []byte { - if x != nil { - return x.RangeproofHash - } - return nil -} - -// 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. -type TransactionOutput struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Options for an output's structure or use - Features *OutputFeatures `protobuf:"bytes,1,opt,name=features,proto3" json:"features,omitempty"` - // The homomorphic commitment representing the output amount - Commitment []byte `protobuf:"bytes,2,opt,name=commitment,proto3" json:"commitment,omitempty"` - // A proof that the commitment is in the right range - RangeProof *types.RangeProof `protobuf:"bytes,3,opt,name=range_proof,json=rangeProof,proto3" json:"range_proof,omitempty"` - // The hash of the output, as it appears in the MMR - Hash []byte `protobuf:"bytes,4,opt,name=hash,proto3" json:"hash,omitempty"` - // Tari script serialised script - Script []byte `protobuf:"bytes,5,opt,name=script,proto3" json:"script,omitempty"` - // Tari script offset public key, K_O - SenderOffsetPublicKey []byte `protobuf:"bytes,6,opt,name=sender_offset_public_key,json=senderOffsetPublicKey,proto3" json:"sender_offset_public_key,omitempty"` - // Metadata signature with the homomorphic commitment private values (amount and blinding factor) and the sender - // offset private key - MetadataSignature *types.ComAndPubSignature `protobuf:"bytes,7,opt,name=metadata_signature,json=metadataSignature,proto3" json:"metadata_signature,omitempty"` - // Covenant - Covenant []byte `protobuf:"bytes,8,opt,name=covenant,proto3" json:"covenant,omitempty"` - // Version - Version uint32 `protobuf:"varint,9,opt,name=version,proto3" json:"version,omitempty"` - // Encrypted Pedersen commitment openings (value and mask) for the output - EncryptedData []byte `protobuf:"bytes,10,opt,name=encrypted_data,json=encryptedData,proto3" json:"encrypted_data,omitempty"` - // The minimum value of the commitment that is proven by the range proof (in MicroMinotari) - MinimumValuePromise uint64 `protobuf:"varint,11,opt,name=minimum_value_promise,json=minimumValuePromise,proto3" json:"minimum_value_promise,omitempty"` - // 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 - PaymentReference []byte `protobuf:"bytes,12,opt,name=payment_reference,json=paymentReference,proto3" json:"payment_reference,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *TransactionOutput) Reset() { - *x = TransactionOutput{} - mi := &file_transaction_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *TransactionOutput) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*TransactionOutput) ProtoMessage() {} - -func (x *TransactionOutput) ProtoReflect() protoreflect.Message { - mi := &file_transaction_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 TransactionOutput.ProtoReflect.Descriptor instead. -func (*TransactionOutput) Descriptor() ([]byte, []int) { - return file_transaction_proto_rawDescGZIP(), []int{2} -} - -func (x *TransactionOutput) GetFeatures() *OutputFeatures { - if x != nil { - return x.Features - } - return nil -} - -func (x *TransactionOutput) GetCommitment() []byte { - if x != nil { - return x.Commitment - } - return nil -} - -func (x *TransactionOutput) GetRangeProof() *types.RangeProof { - if x != nil { - return x.RangeProof - } - return nil -} - -func (x *TransactionOutput) GetHash() []byte { - if x != nil { - return x.Hash - } - return nil -} - -func (x *TransactionOutput) GetScript() []byte { - if x != nil { - return x.Script - } - return nil -} - -func (x *TransactionOutput) GetSenderOffsetPublicKey() []byte { - if x != nil { - return x.SenderOffsetPublicKey - } - return nil -} - -func (x *TransactionOutput) GetMetadataSignature() *types.ComAndPubSignature { - if x != nil { - return x.MetadataSignature - } - return nil -} - -func (x *TransactionOutput) GetCovenant() []byte { - if x != nil { - return x.Covenant - } - return nil -} - -func (x *TransactionOutput) GetVersion() uint32 { - if x != nil { - return x.Version - } - return 0 -} - -func (x *TransactionOutput) GetEncryptedData() []byte { - if x != nil { - return x.EncryptedData - } - return nil -} - -func (x *TransactionOutput) GetMinimumValuePromise() uint64 { - if x != nil { - return x.MinimumValuePromise - } - return 0 -} - -func (x *TransactionOutput) GetPaymentReference() []byte { - if x != nil { - return x.PaymentReference - } - return nil -} - -// Options for UTXOs -type OutputFeatures struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Version - Version uint32 `protobuf:"varint,1,opt,name=version,proto3" json:"version,omitempty"` - // The type of output, eg Coinbase, all of which have different consensus rules - OutputType uint32 `protobuf:"varint,2,opt,name=output_type,json=outputType,proto3" json:"output_type,omitempty"` - // 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. - Maturity uint64 `protobuf:"varint,3,opt,name=maturity,proto3" json:"maturity,omitempty"` - // Additional arbitrary info in coinbase transactions supplied by miners - CoinbaseExtra []byte `protobuf:"bytes,4,opt,name=coinbase_extra,json=coinbaseExtra,proto3" json:"coinbase_extra,omitempty"` - // Features that are specific to a side chain - SidechainFeature *sidechain_types.SideChainFeature `protobuf:"bytes,5,opt,name=sidechain_feature,json=sidechainFeature,proto3" json:"sidechain_feature,omitempty"` - // The type of range proof used in the output - RangeProofType uint32 `protobuf:"varint,6,opt,name=range_proof_type,json=rangeProofType,proto3" json:"range_proof_type,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OutputFeatures) Reset() { - *x = OutputFeatures{} - mi := &file_transaction_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OutputFeatures) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutputFeatures) ProtoMessage() {} - -func (x *OutputFeatures) ProtoReflect() protoreflect.Message { - mi := &file_transaction_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 OutputFeatures.ProtoReflect.Descriptor instead. -func (*OutputFeatures) Descriptor() ([]byte, []int) { - return file_transaction_proto_rawDescGZIP(), []int{3} -} - -func (x *OutputFeatures) GetVersion() uint32 { - if x != nil { - return x.Version - } - return 0 -} - -func (x *OutputFeatures) GetOutputType() uint32 { - if x != nil { - return x.OutputType - } - return 0 -} - -func (x *OutputFeatures) GetMaturity() uint64 { - if x != nil { - return x.Maturity - } - return 0 -} - -func (x *OutputFeatures) GetCoinbaseExtra() []byte { - if x != nil { - return x.CoinbaseExtra - } - return nil -} - -func (x *OutputFeatures) GetSidechainFeature() *sidechain_types.SideChainFeature { - if x != nil { - return x.SidechainFeature - } - return nil -} - -func (x *OutputFeatures) GetRangeProofType() uint32 { - if x != nil { - return x.RangeProofType - } - return 0 -} - -// 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 -type AggregateBody struct { - state protoimpl.MessageState `protogen:"open.v1"` - // List of inputs spent by the transaction. - Inputs []*TransactionInput `protobuf:"bytes,1,rep,name=inputs,proto3" json:"inputs,omitempty"` - // List of outputs the transaction produces. - Outputs []*TransactionOutput `protobuf:"bytes,2,rep,name=outputs,proto3" json:"outputs,omitempty"` - // Kernels contain the excesses and their signatures for transaction - Kernels []*TransactionKernel `protobuf:"bytes,3,rep,name=kernels,proto3" json:"kernels,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *AggregateBody) Reset() { - *x = AggregateBody{} - mi := &file_transaction_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *AggregateBody) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*AggregateBody) ProtoMessage() {} - -func (x *AggregateBody) ProtoReflect() protoreflect.Message { - mi := &file_transaction_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 AggregateBody.ProtoReflect.Descriptor instead. -func (*AggregateBody) Descriptor() ([]byte, []int) { - return file_transaction_proto_rawDescGZIP(), []int{4} -} - -func (x *AggregateBody) GetInputs() []*TransactionInput { - if x != nil { - return x.Inputs - } - return nil -} - -func (x *AggregateBody) GetOutputs() []*TransactionOutput { - if x != nil { - return x.Outputs - } - return nil -} - -func (x *AggregateBody) GetKernels() []*TransactionKernel { - if x != nil { - return x.Kernels - } - return nil -} - -// A transaction which consists of a kernel offset and an aggregate body made up of inputs, outputs and kernels. -type Transaction struct { - state protoimpl.MessageState `protogen:"open.v1"` - Offset []byte `protobuf:"bytes,1,opt,name=offset,proto3" json:"offset,omitempty"` - Body *AggregateBody `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` - ScriptOffset []byte `protobuf:"bytes,3,opt,name=script_offset,json=scriptOffset,proto3" json:"script_offset,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Transaction) Reset() { - *x = Transaction{} - mi := &file_transaction_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Transaction) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Transaction) ProtoMessage() {} - -func (x *Transaction) ProtoReflect() protoreflect.Message { - mi := &file_transaction_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 Transaction.ProtoReflect.Descriptor instead. -func (*Transaction) Descriptor() ([]byte, []int) { - return file_transaction_proto_rawDescGZIP(), []int{5} -} - -func (x *Transaction) GetOffset() []byte { - if x != nil { - return x.Offset - } - return nil -} - -func (x *Transaction) GetBody() *AggregateBody { - if x != nil { - return x.Body - } - return nil -} - -func (x *Transaction) GetScriptOffset() []byte { - if x != nil { - return x.ScriptOffset - } - return nil -} - -type UnblindedOutput struct { - state protoimpl.MessageState `protogen:"open.v1"` - // Value of the output - Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` - // Spending key of the output - SpendingKey []byte `protobuf:"bytes,2,opt,name=spending_key,json=spendingKey,proto3" json:"spending_key,omitempty"` - // Options for an output's structure or use - Features *OutputFeatures `protobuf:"bytes,3,opt,name=features,proto3" json:"features,omitempty"` - // Tari script serialised script - Script []byte `protobuf:"bytes,4,opt,name=script,proto3" json:"script,omitempty"` - // Tari script input data for spending - InputData []byte `protobuf:"bytes,5,opt,name=input_data,json=inputData,proto3" json:"input_data,omitempty"` - // Tari script private key - ScriptPrivateKey []byte `protobuf:"bytes,7,opt,name=script_private_key,json=scriptPrivateKey,proto3" json:"script_private_key,omitempty"` - // Tari script offset pubkey, K_O - SenderOffsetPublicKey []byte `protobuf:"bytes,8,opt,name=sender_offset_public_key,json=senderOffsetPublicKey,proto3" json:"sender_offset_public_key,omitempty"` - // UTXO signature with the script offset private key, k_O - MetadataSignature *types.ComAndPubSignature `protobuf:"bytes,9,opt,name=metadata_signature,json=metadataSignature,proto3" json:"metadata_signature,omitempty"` - // The minimum height the script allows this output to be spent - ScriptLockHeight uint64 `protobuf:"varint,10,opt,name=script_lock_height,json=scriptLockHeight,proto3" json:"script_lock_height,omitempty"` - // Covenant - Covenant []byte `protobuf:"bytes,11,opt,name=covenant,proto3" json:"covenant,omitempty"` - // Encrypted data - EncryptedData []byte `protobuf:"bytes,12,opt,name=encrypted_data,json=encryptedData,proto3" json:"encrypted_data,omitempty"` - // The minimum value of the commitment that is proven by the range proof (in MicroMinotari) - MinimumValuePromise uint64 `protobuf:"varint,13,opt,name=minimum_value_promise,json=minimumValuePromise,proto3" json:"minimum_value_promise,omitempty"` - // The range proof - RangeProof *types.RangeProof `protobuf:"bytes,14,opt,name=range_proof,json=rangeProof,proto3" json:"range_proof,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *UnblindedOutput) Reset() { - *x = UnblindedOutput{} - mi := &file_transaction_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *UnblindedOutput) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*UnblindedOutput) ProtoMessage() {} - -func (x *UnblindedOutput) ProtoReflect() protoreflect.Message { - mi := &file_transaction_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 UnblindedOutput.ProtoReflect.Descriptor instead. -func (*UnblindedOutput) Descriptor() ([]byte, []int) { - return file_transaction_proto_rawDescGZIP(), []int{6} -} - -func (x *UnblindedOutput) GetValue() uint64 { - if x != nil { - return x.Value - } - return 0 -} - -func (x *UnblindedOutput) GetSpendingKey() []byte { - if x != nil { - return x.SpendingKey - } - return nil -} - -func (x *UnblindedOutput) GetFeatures() *OutputFeatures { - if x != nil { - return x.Features - } - return nil -} - -func (x *UnblindedOutput) GetScript() []byte { - if x != nil { - return x.Script - } - return nil -} - -func (x *UnblindedOutput) GetInputData() []byte { - if x != nil { - return x.InputData - } - return nil -} - -func (x *UnblindedOutput) GetScriptPrivateKey() []byte { - if x != nil { - return x.ScriptPrivateKey - } - return nil -} - -func (x *UnblindedOutput) GetSenderOffsetPublicKey() []byte { - if x != nil { - return x.SenderOffsetPublicKey - } - return nil -} - -func (x *UnblindedOutput) GetMetadataSignature() *types.ComAndPubSignature { - if x != nil { - return x.MetadataSignature - } - return nil -} - -func (x *UnblindedOutput) GetScriptLockHeight() uint64 { - if x != nil { - return x.ScriptLockHeight - } - return 0 -} - -func (x *UnblindedOutput) GetCovenant() []byte { - if x != nil { - return x.Covenant - } - return nil -} - -func (x *UnblindedOutput) GetEncryptedData() []byte { - if x != nil { - return x.EncryptedData - } - return nil -} - -func (x *UnblindedOutput) GetMinimumValuePromise() uint64 { - if x != nil { - return x.MinimumValuePromise - } - return 0 -} - -func (x *UnblindedOutput) GetRangeProof() *types.RangeProof { - if x != nil { - return x.RangeProof - } - return nil -} - -var File_transaction_proto protoreflect.FileDescriptor - -const file_transaction_proto_rawDesc = "" + - "\n" + - "\x11transaction.proto\x12\btari.rpc\x1a\vtypes.proto\x1a\x15sidechain_types.proto\"\x85\x02\n" + - "\x11TransactionKernel\x12\x1a\n" + - "\bfeatures\x18\x01 \x01(\rR\bfeatures\x12\x10\n" + - "\x03fee\x18\x02 \x01(\x04R\x03fee\x12\x1f\n" + - "\vlock_height\x18\x03 \x01(\x04R\n" + - "lockHeight\x12\x16\n" + - "\x06excess\x18\x06 \x01(\fR\x06excess\x122\n" + - "\n" + - "excess_sig\x18\a \x01(\v2\x13.tari.rpc.SignatureR\texcessSig\x12\x12\n" + - "\x04hash\x18\b \x01(\fR\x04hash\x12\x18\n" + - "\aversion\x18\t \x01(\rR\aversion\x12'\n" + - "\x0fburn_commitment\x18\n" + - " \x01(\fR\x0eburnCommitment\"\xdd\x04\n" + - "\x10TransactionInput\x124\n" + - "\bfeatures\x18\x01 \x01(\v2\x18.tari.rpc.OutputFeaturesR\bfeatures\x12\x1e\n" + - "\n" + - "commitment\x18\x02 \x01(\fR\n" + - "commitment\x12\x12\n" + - "\x04hash\x18\x03 \x01(\fR\x04hash\x12\x16\n" + - "\x06script\x18\x04 \x01(\fR\x06script\x12\x1d\n" + - "\n" + - "input_data\x18\x05 \x01(\fR\tinputData\x12G\n" + - "\x10script_signature\x18\a \x01(\v2\x1c.tari.rpc.ComAndPubSignatureR\x0fscriptSignature\x127\n" + - "\x18sender_offset_public_key\x18\b \x01(\fR\x15senderOffsetPublicKey\x12\x1f\n" + - "\voutput_hash\x18\t \x01(\fR\n" + - "outputHash\x12\x1a\n" + - "\bcovenant\x18\n" + - " \x01(\fR\bcovenant\x12\x18\n" + - "\aversion\x18\v \x01(\rR\aversion\x12%\n" + - "\x0eencrypted_data\x18\f \x01(\fR\rencryptedData\x122\n" + - "\x15minimum_value_promise\x18\r \x01(\x04R\x13minimumValuePromise\x12K\n" + - "\x12metadata_signature\x18\x0e \x01(\v2\x1c.tari.rpc.ComAndPubSignatureR\x11metadataSignature\x12'\n" + - "\x0frangeproof_hash\x18\x0f \x01(\fR\x0erangeproofHash\"\x90\x04\n" + - "\x11TransactionOutput\x124\n" + - "\bfeatures\x18\x01 \x01(\v2\x18.tari.rpc.OutputFeaturesR\bfeatures\x12\x1e\n" + - "\n" + - "commitment\x18\x02 \x01(\fR\n" + - "commitment\x125\n" + - "\vrange_proof\x18\x03 \x01(\v2\x14.tari.rpc.RangeProofR\n" + - "rangeProof\x12\x12\n" + - "\x04hash\x18\x04 \x01(\fR\x04hash\x12\x16\n" + - "\x06script\x18\x05 \x01(\fR\x06script\x127\n" + - "\x18sender_offset_public_key\x18\x06 \x01(\fR\x15senderOffsetPublicKey\x12K\n" + - "\x12metadata_signature\x18\a \x01(\v2\x1c.tari.rpc.ComAndPubSignatureR\x11metadataSignature\x12\x1a\n" + - "\bcovenant\x18\b \x01(\fR\bcovenant\x12\x18\n" + - "\aversion\x18\t \x01(\rR\aversion\x12%\n" + - "\x0eencrypted_data\x18\n" + - " \x01(\fR\rencryptedData\x122\n" + - "\x15minimum_value_promise\x18\v \x01(\x04R\x13minimumValuePromise\x12+\n" + - "\x11payment_reference\x18\f \x01(\fR\x10paymentReference\"\x81\x02\n" + - "\x0eOutputFeatures\x12\x18\n" + - "\aversion\x18\x01 \x01(\rR\aversion\x12\x1f\n" + - "\voutput_type\x18\x02 \x01(\rR\n" + - "outputType\x12\x1a\n" + - "\bmaturity\x18\x03 \x01(\x04R\bmaturity\x12%\n" + - "\x0ecoinbase_extra\x18\x04 \x01(\fR\rcoinbaseExtra\x12G\n" + - "\x11sidechain_feature\x18\x05 \x01(\v2\x1a.tari.rpc.SideChainFeatureR\x10sidechainFeature\x12(\n" + - "\x10range_proof_type\x18\x06 \x01(\rR\x0erangeProofType\"\xb1\x01\n" + - "\rAggregateBody\x122\n" + - "\x06inputs\x18\x01 \x03(\v2\x1a.tari.rpc.TransactionInputR\x06inputs\x125\n" + - "\aoutputs\x18\x02 \x03(\v2\x1b.tari.rpc.TransactionOutputR\aoutputs\x125\n" + - "\akernels\x18\x03 \x03(\v2\x1b.tari.rpc.TransactionKernelR\akernels\"w\n" + - "\vTransaction\x12\x16\n" + - "\x06offset\x18\x01 \x01(\fR\x06offset\x12+\n" + - "\x04body\x18\x02 \x01(\v2\x17.tari.rpc.AggregateBodyR\x04body\x12#\n" + - "\rscript_offset\x18\x03 \x01(\fR\fscriptOffset\"\xc7\x04\n" + - "\x0fUnblindedOutput\x12\x14\n" + - "\x05value\x18\x01 \x01(\x04R\x05value\x12!\n" + - "\fspending_key\x18\x02 \x01(\fR\vspendingKey\x124\n" + - "\bfeatures\x18\x03 \x01(\v2\x18.tari.rpc.OutputFeaturesR\bfeatures\x12\x16\n" + - "\x06script\x18\x04 \x01(\fR\x06script\x12\x1d\n" + - "\n" + - "input_data\x18\x05 \x01(\fR\tinputData\x12,\n" + - "\x12script_private_key\x18\a \x01(\fR\x10scriptPrivateKey\x127\n" + - "\x18sender_offset_public_key\x18\b \x01(\fR\x15senderOffsetPublicKey\x12K\n" + - "\x12metadata_signature\x18\t \x01(\v2\x1c.tari.rpc.ComAndPubSignatureR\x11metadataSignature\x12,\n" + - "\x12script_lock_height\x18\n" + - " \x01(\x04R\x10scriptLockHeight\x12\x1a\n" + - "\bcovenant\x18\v \x01(\fR\bcovenant\x12%\n" + - "\x0eencrypted_data\x18\f \x01(\fR\rencryptedData\x122\n" + - "\x15minimum_value_promise\x18\r \x01(\x04R\x13minimumValuePromise\x125\n" + - "\vrange_proof\x18\x0e \x01(\v2\x14.tari.rpc.RangeProofR\n" + - "rangeProofB0Z.pool/internal/gbt/tari/transaction;transactionb\x06proto3" - -var ( - file_transaction_proto_rawDescOnce sync.Once - file_transaction_proto_rawDescData []byte -) - -func file_transaction_proto_rawDescGZIP() []byte { - file_transaction_proto_rawDescOnce.Do(func() { - file_transaction_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_transaction_proto_rawDesc), len(file_transaction_proto_rawDesc))) - }) - return file_transaction_proto_rawDescData -} - -var file_transaction_proto_msgTypes = make([]protoimpl.MessageInfo, 7) -var file_transaction_proto_goTypes = []any{ - (*TransactionKernel)(nil), // 0: tari.rpc.TransactionKernel - (*TransactionInput)(nil), // 1: tari.rpc.TransactionInput - (*TransactionOutput)(nil), // 2: tari.rpc.TransactionOutput - (*OutputFeatures)(nil), // 3: tari.rpc.OutputFeatures - (*AggregateBody)(nil), // 4: tari.rpc.AggregateBody - (*Transaction)(nil), // 5: tari.rpc.Transaction - (*UnblindedOutput)(nil), // 6: tari.rpc.UnblindedOutput - (*types.Signature)(nil), // 7: tari.rpc.Signature - (*types.ComAndPubSignature)(nil), // 8: tari.rpc.ComAndPubSignature - (*types.RangeProof)(nil), // 9: tari.rpc.RangeProof - (*sidechain_types.SideChainFeature)(nil), // 10: tari.rpc.SideChainFeature -} -var file_transaction_proto_depIdxs = []int32{ - 7, // 0: tari.rpc.TransactionKernel.excess_sig:type_name -> tari.rpc.Signature - 3, // 1: tari.rpc.TransactionInput.features:type_name -> tari.rpc.OutputFeatures - 8, // 2: tari.rpc.TransactionInput.script_signature:type_name -> tari.rpc.ComAndPubSignature - 8, // 3: tari.rpc.TransactionInput.metadata_signature:type_name -> tari.rpc.ComAndPubSignature - 3, // 4: tari.rpc.TransactionOutput.features:type_name -> tari.rpc.OutputFeatures - 9, // 5: tari.rpc.TransactionOutput.range_proof:type_name -> tari.rpc.RangeProof - 8, // 6: tari.rpc.TransactionOutput.metadata_signature:type_name -> tari.rpc.ComAndPubSignature - 10, // 7: tari.rpc.OutputFeatures.sidechain_feature:type_name -> tari.rpc.SideChainFeature - 1, // 8: tari.rpc.AggregateBody.inputs:type_name -> tari.rpc.TransactionInput - 2, // 9: tari.rpc.AggregateBody.outputs:type_name -> tari.rpc.TransactionOutput - 0, // 10: tari.rpc.AggregateBody.kernels:type_name -> tari.rpc.TransactionKernel - 4, // 11: tari.rpc.Transaction.body:type_name -> tari.rpc.AggregateBody - 3, // 12: tari.rpc.UnblindedOutput.features:type_name -> tari.rpc.OutputFeatures - 8, // 13: tari.rpc.UnblindedOutput.metadata_signature:type_name -> tari.rpc.ComAndPubSignature - 9, // 14: tari.rpc.UnblindedOutput.range_proof:type_name -> tari.rpc.RangeProof - 15, // [15:15] is the sub-list for method output_type - 15, // [15:15] is the sub-list for method input_type - 15, // [15:15] is the sub-list for extension type_name - 15, // [15:15] is the sub-list for extension extendee - 0, // [0:15] is the sub-list for field type_name -} - -func init() { file_transaction_proto_init() } -func file_transaction_proto_init() { - if File_transaction_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_transaction_proto_rawDesc), len(file_transaction_proto_rawDesc)), - NumEnums: 0, - NumMessages: 7, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_transaction_proto_goTypes, - DependencyIndexes: file_transaction_proto_depIdxs, - MessageInfos: file_transaction_proto_msgTypes, - }.Build() - File_transaction_proto = out.File - file_transaction_proto_goTypes = nil - file_transaction_proto_depIdxs = nil -} diff --git a/internal/gbt/tari/proto/types.proto b/internal/gbt/tari/proto/types.proto deleted file mode 100644 index d25b5ad..0000000 --- a/internal/gbt/tari/proto/types.proto +++ /dev/null @@ -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 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; -} diff --git a/internal/gbt/tari/proto/types/types.pb.go b/internal/gbt/tari/proto/types/types.pb.go deleted file mode 100644 index bbba83f..0000000 --- a/internal/gbt/tari/proto/types/types.pb.go +++ /dev/null @@ -1,1239 +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: types.proto - -package types - -import ( - 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) -) - -// / Output types -type OutputType int32 - -const ( - OutputType_STANDARD OutputType = 0 - OutputType_COINBASE OutputType = 1 - OutputType_BURN OutputType = 2 - OutputType_VALIDATOR_NODE_REGISTRATION OutputType = 3 - OutputType_CODE_TEMPLATE_REGISTRATION OutputType = 4 -) - -// Enum value maps for OutputType. -var ( - OutputType_name = map[int32]string{ - 0: "STANDARD", - 1: "COINBASE", - 2: "BURN", - 3: "VALIDATOR_NODE_REGISTRATION", - 4: "CODE_TEMPLATE_REGISTRATION", - } - OutputType_value = map[string]int32{ - "STANDARD": 0, - "COINBASE": 1, - "BURN": 2, - "VALIDATOR_NODE_REGISTRATION": 3, - "CODE_TEMPLATE_REGISTRATION": 4, - } -) - -func (x OutputType) Enum() *OutputType { - p := new(OutputType) - *p = x - return p -} - -func (x OutputType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (OutputType) Descriptor() protoreflect.EnumDescriptor { - return file_types_proto_enumTypes[0].Descriptor() -} - -func (OutputType) Type() protoreflect.EnumType { - return &file_types_proto_enumTypes[0] -} - -func (x OutputType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use OutputType.Descriptor instead. -func (OutputType) EnumDescriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{0} -} - -// / Range proof types -type RangeProofType int32 - -const ( - RangeProofType_BULLETPROOF_PLUS RangeProofType = 0 - RangeProofType_REVEALED_VALUE RangeProofType = 1 -) - -// Enum value maps for RangeProofType. -var ( - RangeProofType_name = map[int32]string{ - 0: "BULLETPROOF_PLUS", - 1: "REVEALED_VALUE", - } - RangeProofType_value = map[string]int32{ - "BULLETPROOF_PLUS": 0, - "REVEALED_VALUE": 1, - } -) - -func (x RangeProofType) Enum() *RangeProofType { - p := new(RangeProofType) - *p = x - return p -} - -func (x RangeProofType) String() string { - return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) -} - -func (RangeProofType) Descriptor() protoreflect.EnumDescriptor { - return file_types_proto_enumTypes[1].Descriptor() -} - -func (RangeProofType) Type() protoreflect.EnumType { - return &file_types_proto_enumTypes[1] -} - -func (x RangeProofType) Number() protoreflect.EnumNumber { - return protoreflect.EnumNumber(x) -} - -// Deprecated: Use RangeProofType.Descriptor instead. -func (RangeProofType) EnumDescriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{1} -} - -// / An unsigned range interface to more accurately represent Rust native Range's -type Range struct { - state protoimpl.MessageState `protogen:"open.v1"` - Min uint64 `protobuf:"varint,1,opt,name=min,proto3" json:"min,omitempty"` - Max uint64 `protobuf:"varint,2,opt,name=max,proto3" json:"max,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Range) Reset() { - *x = Range{} - mi := &file_types_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Range) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Range) ProtoMessage() {} - -func (x *Range) ProtoReflect() protoreflect.Message { - mi := &file_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 Range.ProtoReflect.Descriptor instead. -func (*Range) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{0} -} - -func (x *Range) GetMin() uint64 { - if x != nil { - return x.Min - } - return 0 -} - -func (x *Range) GetMax() uint64 { - if x != nil { - return x.Max - } - return 0 -} - -// / An Empty placeholder for endpoints without request parameters -type Empty struct { - state protoimpl.MessageState `protogen:"open.v1"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Empty) Reset() { - *x = Empty{} - mi := &file_types_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Empty) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Empty) ProtoMessage() {} - -func (x *Empty) ProtoReflect() protoreflect.Message { - mi := &file_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 Empty.ProtoReflect.Descriptor instead. -func (*Empty) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{1} -} - -// / Define an interface for block height -type BlockHeight struct { - state protoimpl.MessageState `protogen:"open.v1"` - BlockHeight uint64 `protobuf:"varint,1,opt,name=block_height,json=blockHeight,proto3" json:"block_height,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *BlockHeight) Reset() { - *x = BlockHeight{} - mi := &file_types_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *BlockHeight) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*BlockHeight) ProtoMessage() {} - -func (x *BlockHeight) ProtoReflect() protoreflect.Message { - mi := &file_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 BlockHeight.ProtoReflect.Descriptor instead. -func (*BlockHeight) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{2} -} - -func (x *BlockHeight) GetBlockHeight() uint64 { - if x != nil { - return x.BlockHeight - } - return 0 -} - -// Define the explicit Signature implementation for the Minotari base layer. A different signature scheme can be -// employed by redefining this type. -type Signature struct { - state protoimpl.MessageState `protogen:"open.v1"` - PublicNonce []byte `protobuf:"bytes,1,opt,name=public_nonce,json=publicNonce,proto3" json:"public_nonce,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *Signature) Reset() { - *x = Signature{} - mi := &file_types_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *Signature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Signature) ProtoMessage() {} - -func (x *Signature) ProtoReflect() protoreflect.Message { - mi := &file_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 Signature.ProtoReflect.Descriptor instead. -func (*Signature) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{3} -} - -func (x *Signature) GetPublicNonce() []byte { - if x != nil { - return x.PublicNonce - } - return nil -} - -func (x *Signature) GetSignature() []byte { - if x != nil { - return x.Signature - } - return nil -} - -// Define the explicit ComAndPubSignature implementation for the Minotari base layer. A different signature scheme can be -// employed by redefining this type. -type ComAndPubSignature struct { - state protoimpl.MessageState `protogen:"open.v1"` - EphemeralCommitment []byte `protobuf:"bytes,1,opt,name=ephemeral_commitment,json=ephemeralCommitment,proto3" json:"ephemeral_commitment,omitempty"` - EphemeralPubkey []byte `protobuf:"bytes,2,opt,name=ephemeral_pubkey,json=ephemeralPubkey,proto3" json:"ephemeral_pubkey,omitempty"` - UA []byte `protobuf:"bytes,3,opt,name=u_a,json=uA,proto3" json:"u_a,omitempty"` - UX []byte `protobuf:"bytes,4,opt,name=u_x,json=uX,proto3" json:"u_x,omitempty"` - UY []byte `protobuf:"bytes,5,opt,name=u_y,json=uY,proto3" json:"u_y,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ComAndPubSignature) Reset() { - *x = ComAndPubSignature{} - mi := &file_types_proto_msgTypes[4] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ComAndPubSignature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ComAndPubSignature) ProtoMessage() {} - -func (x *ComAndPubSignature) ProtoReflect() protoreflect.Message { - mi := &file_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 ComAndPubSignature.ProtoReflect.Descriptor instead. -func (*ComAndPubSignature) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{4} -} - -func (x *ComAndPubSignature) GetEphemeralCommitment() []byte { - if x != nil { - return x.EphemeralCommitment - } - return nil -} - -func (x *ComAndPubSignature) GetEphemeralPubkey() []byte { - if x != nil { - return x.EphemeralPubkey - } - return nil -} - -func (x *ComAndPubSignature) GetUA() []byte { - if x != nil { - return x.UA - } - return nil -} - -func (x *ComAndPubSignature) GetUX() []byte { - if x != nil { - return x.UX - } - return nil -} - -func (x *ComAndPubSignature) GetUY() []byte { - if x != nil { - return x.UY - } - return nil -} - -// Define the explicit CommitmentSignature implementation for the Minotari base layer. A different signature scheme can be -// employed by redefining this type -type CommitmentSignature struct { - state protoimpl.MessageState `protogen:"open.v1"` - PublicNonce []byte `protobuf:"bytes,1,opt,name=public_nonce,json=publicNonce,proto3" json:"public_nonce,omitempty"` - U []byte `protobuf:"bytes,2,opt,name=u,proto3" json:"u,omitempty"` - V []byte `protobuf:"bytes,3,opt,name=v,proto3" json:"v,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *CommitmentSignature) Reset() { - *x = CommitmentSignature{} - mi := &file_types_proto_msgTypes[5] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *CommitmentSignature) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CommitmentSignature) ProtoMessage() {} - -func (x *CommitmentSignature) ProtoReflect() protoreflect.Message { - mi := &file_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 CommitmentSignature.ProtoReflect.Descriptor instead. -func (*CommitmentSignature) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{5} -} - -func (x *CommitmentSignature) GetPublicNonce() []byte { - if x != nil { - return x.PublicNonce - } - return nil -} - -func (x *CommitmentSignature) GetU() []byte { - if x != nil { - return x.U - } - return nil -} - -func (x *CommitmentSignature) GetV() []byte { - if x != nil { - return x.V - } - return nil -} - -// / PoW Algorithm constants -type PowAlgorithmConstants struct { - state protoimpl.MessageState `protogen:"open.v1"` - MinDifficulty uint64 `protobuf:"varint,2,opt,name=min_difficulty,json=minDifficulty,proto3" json:"min_difficulty,omitempty"` - MaxDifficulty uint64 `protobuf:"varint,3,opt,name=max_difficulty,json=maxDifficulty,proto3" json:"max_difficulty,omitempty"` - TargetTime uint64 `protobuf:"varint,4,opt,name=target_time,json=targetTime,proto3" json:"target_time,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PowAlgorithmConstants) Reset() { - *x = PowAlgorithmConstants{} - mi := &file_types_proto_msgTypes[6] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PowAlgorithmConstants) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PowAlgorithmConstants) ProtoMessage() {} - -func (x *PowAlgorithmConstants) ProtoReflect() protoreflect.Message { - mi := &file_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 PowAlgorithmConstants.ProtoReflect.Descriptor instead. -func (*PowAlgorithmConstants) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{6} -} - -func (x *PowAlgorithmConstants) GetMinDifficulty() uint64 { - if x != nil { - return x.MinDifficulty - } - return 0 -} - -func (x *PowAlgorithmConstants) GetMaxDifficulty() uint64 { - if x != nil { - return x.MaxDifficulty - } - return 0 -} - -func (x *PowAlgorithmConstants) GetTargetTime() uint64 { - if x != nil { - return x.TargetTime - } - return 0 -} - -// / Weight params -type WeightParams struct { - state protoimpl.MessageState `protogen:"open.v1"` - KernelWeight uint64 `protobuf:"varint,1,opt,name=kernel_weight,json=kernelWeight,proto3" json:"kernel_weight,omitempty"` - InputWeight uint64 `protobuf:"varint,2,opt,name=input_weight,json=inputWeight,proto3" json:"input_weight,omitempty"` - OutputWeight uint64 `protobuf:"varint,3,opt,name=output_weight,json=outputWeight,proto3" json:"output_weight,omitempty"` - FeaturesAndScriptsBytesPerGram uint64 `protobuf:"varint,4,opt,name=features_and_scripts_bytes_per_gram,json=featuresAndScriptsBytesPerGram,proto3" json:"features_and_scripts_bytes_per_gram,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *WeightParams) Reset() { - *x = WeightParams{} - mi := &file_types_proto_msgTypes[7] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *WeightParams) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*WeightParams) ProtoMessage() {} - -func (x *WeightParams) ProtoReflect() protoreflect.Message { - mi := &file_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 WeightParams.ProtoReflect.Descriptor instead. -func (*WeightParams) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{7} -} - -func (x *WeightParams) GetKernelWeight() uint64 { - if x != nil { - return x.KernelWeight - } - return 0 -} - -func (x *WeightParams) GetInputWeight() uint64 { - if x != nil { - return x.InputWeight - } - return 0 -} - -func (x *WeightParams) GetOutputWeight() uint64 { - if x != nil { - return x.OutputWeight - } - return 0 -} - -func (x *WeightParams) GetFeaturesAndScriptsBytesPerGram() uint64 { - if x != nil { - return x.FeaturesAndScriptsBytesPerGram - } - return 0 -} - -// / Output version -type OutputsVersion struct { - state protoimpl.MessageState `protogen:"open.v1"` - Outputs *Range `protobuf:"bytes,1,opt,name=outputs,proto3" json:"outputs,omitempty"` - Features *Range `protobuf:"bytes,2,opt,name=features,proto3" json:"features,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *OutputsVersion) Reset() { - *x = OutputsVersion{} - mi := &file_types_proto_msgTypes[8] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *OutputsVersion) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*OutputsVersion) ProtoMessage() {} - -func (x *OutputsVersion) ProtoReflect() protoreflect.Message { - mi := &file_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 OutputsVersion.ProtoReflect.Descriptor instead. -func (*OutputsVersion) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{8} -} - -func (x *OutputsVersion) GetOutputs() *Range { - if x != nil { - return x.Outputs - } - return nil -} - -func (x *OutputsVersion) GetFeatures() *Range { - if x != nil { - return x.Features - } - return nil -} - -type PermittedRangeProofs struct { - state protoimpl.MessageState `protogen:"open.v1"` - OutputType OutputType `protobuf:"varint,1,opt,name=output_type,json=outputType,proto3,enum=tari.rpc.OutputType" json:"output_type,omitempty"` - RangeProofTypes []RangeProofType `protobuf:"varint,2,rep,packed,name=range_proof_types,json=rangeProofTypes,proto3,enum=tari.rpc.RangeProofType" json:"range_proof_types,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *PermittedRangeProofs) Reset() { - *x = PermittedRangeProofs{} - mi := &file_types_proto_msgTypes[9] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *PermittedRangeProofs) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*PermittedRangeProofs) ProtoMessage() {} - -func (x *PermittedRangeProofs) ProtoReflect() protoreflect.Message { - mi := &file_types_proto_msgTypes[9] - 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 PermittedRangeProofs.ProtoReflect.Descriptor instead. -func (*PermittedRangeProofs) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{9} -} - -func (x *PermittedRangeProofs) GetOutputType() OutputType { - if x != nil { - return x.OutputType - } - return OutputType_STANDARD -} - -func (x *PermittedRangeProofs) GetRangeProofTypes() []RangeProofType { - if x != nil { - return x.RangeProofTypes - } - return nil -} - -// / Range proof -type RangeProof struct { - state protoimpl.MessageState `protogen:"open.v1"` - ProofBytes []byte `protobuf:"bytes,1,opt,name=proof_bytes,json=proofBytes,proto3" json:"proof_bytes,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *RangeProof) Reset() { - *x = RangeProof{} - mi := &file_types_proto_msgTypes[10] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *RangeProof) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RangeProof) ProtoMessage() {} - -func (x *RangeProof) ProtoReflect() protoreflect.Message { - mi := &file_types_proto_msgTypes[10] - 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 RangeProof.ProtoReflect.Descriptor instead. -func (*RangeProof) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{10} -} - -func (x *RangeProof) GetProofBytes() []byte { - if x != nil { - return x.ProofBytes - } - return nil -} - -// / Consensus Constants response -type ConsensusConstants struct { - state protoimpl.MessageState `protogen:"open.v1"` - CoinbaseMinMaturity uint64 `protobuf:"varint,1,opt,name=coinbase_min_maturity,json=coinbaseMinMaturity,proto3" json:"coinbase_min_maturity,omitempty"` - BlockchainVersion uint32 `protobuf:"varint,2,opt,name=blockchain_version,json=blockchainVersion,proto3" json:"blockchain_version,omitempty"` - FutureTimeLimit uint64 `protobuf:"varint,3,opt,name=future_time_limit,json=futureTimeLimit,proto3" json:"future_time_limit,omitempty"` - DifficultyBlockWindow uint64 `protobuf:"varint,5,opt,name=difficulty_block_window,json=difficultyBlockWindow,proto3" json:"difficulty_block_window,omitempty"` - MaxBlockTransactionWeight uint64 `protobuf:"varint,7,opt,name=max_block_transaction_weight,json=maxBlockTransactionWeight,proto3" json:"max_block_transaction_weight,omitempty"` - PowAlgoCount uint64 `protobuf:"varint,8,opt,name=pow_algo_count,json=powAlgoCount,proto3" json:"pow_algo_count,omitempty"` - MedianTimestampCount uint64 `protobuf:"varint,9,opt,name=median_timestamp_count,json=medianTimestampCount,proto3" json:"median_timestamp_count,omitempty"` - EmissionInitial uint64 `protobuf:"varint,10,opt,name=emission_initial,json=emissionInitial,proto3" json:"emission_initial,omitempty"` - EmissionDecay []uint64 `protobuf:"varint,11,rep,packed,name=emission_decay,json=emissionDecay,proto3" json:"emission_decay,omitempty"` - // Deprecated: Marked as deprecated in types.proto. - EmissionTail uint64 `protobuf:"varint,12,opt,name=emission_tail,json=emissionTail,proto3" json:"emission_tail,omitempty"` - MinSha3XPowDifficulty uint64 `protobuf:"varint,13,opt,name=min_sha3x_pow_difficulty,json=minSha3xPowDifficulty,proto3" json:"min_sha3x_pow_difficulty,omitempty"` - BlockWeightInputs uint64 `protobuf:"varint,14,opt,name=block_weight_inputs,json=blockWeightInputs,proto3" json:"block_weight_inputs,omitempty"` - BlockWeightOutputs uint64 `protobuf:"varint,15,opt,name=block_weight_outputs,json=blockWeightOutputs,proto3" json:"block_weight_outputs,omitempty"` - BlockWeightKernels uint64 `protobuf:"varint,16,opt,name=block_weight_kernels,json=blockWeightKernels,proto3" json:"block_weight_kernels,omitempty"` - PreMineValue uint64 `protobuf:"varint,17,opt,name=pre_mine_value,json=preMineValue,proto3" json:"pre_mine_value,omitempty"` - MaxScriptByteSize uint64 `protobuf:"varint,18,opt,name=max_script_byte_size,json=maxScriptByteSize,proto3" json:"max_script_byte_size,omitempty"` - ValidatorNodeValidityPeriod uint64 `protobuf:"varint,19,opt,name=validator_node_validity_period,json=validatorNodeValidityPeriod,proto3" json:"validator_node_validity_period,omitempty"` - EffectiveFromHeight uint64 `protobuf:"varint,20,opt,name=effective_from_height,json=effectiveFromHeight,proto3" json:"effective_from_height,omitempty"` - ValidBlockchainVersionRange *Range `protobuf:"bytes,21,opt,name=valid_blockchain_version_range,json=validBlockchainVersionRange,proto3" json:"valid_blockchain_version_range,omitempty"` - MaxRandomxSeedHeight uint64 `protobuf:"varint,22,opt,name=max_randomx_seed_height,json=maxRandomxSeedHeight,proto3" json:"max_randomx_seed_height,omitempty"` - ProofOfWork map[uint32]*PowAlgorithmConstants `protobuf:"bytes,23,rep,name=proof_of_work,json=proofOfWork,proto3" json:"proof_of_work,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"` - TransactionWeight *WeightParams `protobuf:"bytes,24,opt,name=transaction_weight,json=transactionWeight,proto3" json:"transaction_weight,omitempty"` - InputVersionRange *Range `protobuf:"bytes,26,opt,name=input_version_range,json=inputVersionRange,proto3" json:"input_version_range,omitempty"` - OutputVersionRange *OutputsVersion `protobuf:"bytes,27,opt,name=output_version_range,json=outputVersionRange,proto3" json:"output_version_range,omitempty"` - KernelVersionRange *Range `protobuf:"bytes,28,opt,name=kernel_version_range,json=kernelVersionRange,proto3" json:"kernel_version_range,omitempty"` - PermittedOutputTypes []OutputType `protobuf:"varint,29,rep,packed,name=permitted_output_types,json=permittedOutputTypes,proto3,enum=tari.rpc.OutputType" json:"permitted_output_types,omitempty"` - EpochLength uint64 `protobuf:"varint,30,opt,name=epoch_length,json=epochLength,proto3" json:"epoch_length,omitempty"` - ValidatorNodeRegistrationMinDepositAmount uint64 `protobuf:"varint,31,opt,name=validator_node_registration_min_deposit_amount,json=validatorNodeRegistrationMinDepositAmount,proto3" json:"validator_node_registration_min_deposit_amount,omitempty"` - ValidatorNodeRegistrationMinLockHeight uint64 `protobuf:"varint,32,opt,name=validator_node_registration_min_lock_height,json=validatorNodeRegistrationMinLockHeight,proto3" json:"validator_node_registration_min_lock_height,omitempty"` - ValidatorNodeRegistrationShuffleIntervalEpoch uint64 `protobuf:"varint,33,opt,name=validator_node_registration_shuffle_interval_epoch,json=validatorNodeRegistrationShuffleIntervalEpoch,proto3" json:"validator_node_registration_shuffle_interval_epoch,omitempty"` - PermittedRangeProofTypes []*PermittedRangeProofs `protobuf:"bytes,34,rep,name=permitted_range_proof_types,json=permittedRangeProofTypes,proto3" json:"permitted_range_proof_types,omitempty"` - InflationBips uint64 `protobuf:"varint,35,opt,name=inflation_bips,json=inflationBips,proto3" json:"inflation_bips,omitempty"` - TailEpochLength uint64 `protobuf:"varint,36,opt,name=tail_epoch_length,json=tailEpochLength,proto3" json:"tail_epoch_length,omitempty"` - MaxBlockCoinbaseCount uint64 `protobuf:"varint,37,opt,name=max_block_coinbase_count,json=maxBlockCoinbaseCount,proto3" json:"max_block_coinbase_count,omitempty"` - unknownFields protoimpl.UnknownFields - sizeCache protoimpl.SizeCache -} - -func (x *ConsensusConstants) Reset() { - *x = ConsensusConstants{} - mi := &file_types_proto_msgTypes[11] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) -} - -func (x *ConsensusConstants) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ConsensusConstants) ProtoMessage() {} - -func (x *ConsensusConstants) ProtoReflect() protoreflect.Message { - mi := &file_types_proto_msgTypes[11] - 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 ConsensusConstants.ProtoReflect.Descriptor instead. -func (*ConsensusConstants) Descriptor() ([]byte, []int) { - return file_types_proto_rawDescGZIP(), []int{11} -} - -func (x *ConsensusConstants) GetCoinbaseMinMaturity() uint64 { - if x != nil { - return x.CoinbaseMinMaturity - } - return 0 -} - -func (x *ConsensusConstants) GetBlockchainVersion() uint32 { - if x != nil { - return x.BlockchainVersion - } - return 0 -} - -func (x *ConsensusConstants) GetFutureTimeLimit() uint64 { - if x != nil { - return x.FutureTimeLimit - } - return 0 -} - -func (x *ConsensusConstants) GetDifficultyBlockWindow() uint64 { - if x != nil { - return x.DifficultyBlockWindow - } - return 0 -} - -func (x *ConsensusConstants) GetMaxBlockTransactionWeight() uint64 { - if x != nil { - return x.MaxBlockTransactionWeight - } - return 0 -} - -func (x *ConsensusConstants) GetPowAlgoCount() uint64 { - if x != nil { - return x.PowAlgoCount - } - return 0 -} - -func (x *ConsensusConstants) GetMedianTimestampCount() uint64 { - if x != nil { - return x.MedianTimestampCount - } - return 0 -} - -func (x *ConsensusConstants) GetEmissionInitial() uint64 { - if x != nil { - return x.EmissionInitial - } - return 0 -} - -func (x *ConsensusConstants) GetEmissionDecay() []uint64 { - if x != nil { - return x.EmissionDecay - } - return nil -} - -// Deprecated: Marked as deprecated in types.proto. -func (x *ConsensusConstants) GetEmissionTail() uint64 { - if x != nil { - return x.EmissionTail - } - return 0 -} - -func (x *ConsensusConstants) GetMinSha3XPowDifficulty() uint64 { - if x != nil { - return x.MinSha3XPowDifficulty - } - return 0 -} - -func (x *ConsensusConstants) GetBlockWeightInputs() uint64 { - if x != nil { - return x.BlockWeightInputs - } - return 0 -} - -func (x *ConsensusConstants) GetBlockWeightOutputs() uint64 { - if x != nil { - return x.BlockWeightOutputs - } - return 0 -} - -func (x *ConsensusConstants) GetBlockWeightKernels() uint64 { - if x != nil { - return x.BlockWeightKernels - } - return 0 -} - -func (x *ConsensusConstants) GetPreMineValue() uint64 { - if x != nil { - return x.PreMineValue - } - return 0 -} - -func (x *ConsensusConstants) GetMaxScriptByteSize() uint64 { - if x != nil { - return x.MaxScriptByteSize - } - return 0 -} - -func (x *ConsensusConstants) GetValidatorNodeValidityPeriod() uint64 { - if x != nil { - return x.ValidatorNodeValidityPeriod - } - return 0 -} - -func (x *ConsensusConstants) GetEffectiveFromHeight() uint64 { - if x != nil { - return x.EffectiveFromHeight - } - return 0 -} - -func (x *ConsensusConstants) GetValidBlockchainVersionRange() *Range { - if x != nil { - return x.ValidBlockchainVersionRange - } - return nil -} - -func (x *ConsensusConstants) GetMaxRandomxSeedHeight() uint64 { - if x != nil { - return x.MaxRandomxSeedHeight - } - return 0 -} - -func (x *ConsensusConstants) GetProofOfWork() map[uint32]*PowAlgorithmConstants { - if x != nil { - return x.ProofOfWork - } - return nil -} - -func (x *ConsensusConstants) GetTransactionWeight() *WeightParams { - if x != nil { - return x.TransactionWeight - } - return nil -} - -func (x *ConsensusConstants) GetInputVersionRange() *Range { - if x != nil { - return x.InputVersionRange - } - return nil -} - -func (x *ConsensusConstants) GetOutputVersionRange() *OutputsVersion { - if x != nil { - return x.OutputVersionRange - } - return nil -} - -func (x *ConsensusConstants) GetKernelVersionRange() *Range { - if x != nil { - return x.KernelVersionRange - } - return nil -} - -func (x *ConsensusConstants) GetPermittedOutputTypes() []OutputType { - if x != nil { - return x.PermittedOutputTypes - } - return nil -} - -func (x *ConsensusConstants) GetEpochLength() uint64 { - if x != nil { - return x.EpochLength - } - return 0 -} - -func (x *ConsensusConstants) GetValidatorNodeRegistrationMinDepositAmount() uint64 { - if x != nil { - return x.ValidatorNodeRegistrationMinDepositAmount - } - return 0 -} - -func (x *ConsensusConstants) GetValidatorNodeRegistrationMinLockHeight() uint64 { - if x != nil { - return x.ValidatorNodeRegistrationMinLockHeight - } - return 0 -} - -func (x *ConsensusConstants) GetValidatorNodeRegistrationShuffleIntervalEpoch() uint64 { - if x != nil { - return x.ValidatorNodeRegistrationShuffleIntervalEpoch - } - return 0 -} - -func (x *ConsensusConstants) GetPermittedRangeProofTypes() []*PermittedRangeProofs { - if x != nil { - return x.PermittedRangeProofTypes - } - return nil -} - -func (x *ConsensusConstants) GetInflationBips() uint64 { - if x != nil { - return x.InflationBips - } - return 0 -} - -func (x *ConsensusConstants) GetTailEpochLength() uint64 { - if x != nil { - return x.TailEpochLength - } - return 0 -} - -func (x *ConsensusConstants) GetMaxBlockCoinbaseCount() uint64 { - if x != nil { - return x.MaxBlockCoinbaseCount - } - return 0 -} - -var File_types_proto protoreflect.FileDescriptor - -const file_types_proto_rawDesc = "" + - "\n" + - "\vtypes.proto\x12\btari.rpc\"+\n" + - "\x05Range\x12\x10\n" + - "\x03min\x18\x01 \x01(\x04R\x03min\x12\x10\n" + - "\x03max\x18\x02 \x01(\x04R\x03max\"\a\n" + - "\x05Empty\"0\n" + - "\vBlockHeight\x12!\n" + - "\fblock_height\x18\x01 \x01(\x04R\vblockHeight\"L\n" + - "\tSignature\x12!\n" + - "\fpublic_nonce\x18\x01 \x01(\fR\vpublicNonce\x12\x1c\n" + - "\tsignature\x18\x02 \x01(\fR\tsignature\"\xa5\x01\n" + - "\x12ComAndPubSignature\x121\n" + - "\x14ephemeral_commitment\x18\x01 \x01(\fR\x13ephemeralCommitment\x12)\n" + - "\x10ephemeral_pubkey\x18\x02 \x01(\fR\x0fephemeralPubkey\x12\x0f\n" + - "\x03u_a\x18\x03 \x01(\fR\x02uA\x12\x0f\n" + - "\x03u_x\x18\x04 \x01(\fR\x02uX\x12\x0f\n" + - "\x03u_y\x18\x05 \x01(\fR\x02uY\"T\n" + - "\x13CommitmentSignature\x12!\n" + - "\fpublic_nonce\x18\x01 \x01(\fR\vpublicNonce\x12\f\n" + - "\x01u\x18\x02 \x01(\fR\x01u\x12\f\n" + - "\x01v\x18\x03 \x01(\fR\x01v\"\x86\x01\n" + - "\x15PowAlgorithmConstants\x12%\n" + - "\x0emin_difficulty\x18\x02 \x01(\x04R\rminDifficulty\x12%\n" + - "\x0emax_difficulty\x18\x03 \x01(\x04R\rmaxDifficulty\x12\x1f\n" + - "\vtarget_time\x18\x04 \x01(\x04R\n" + - "targetTime\"\xc8\x01\n" + - "\fWeightParams\x12#\n" + - "\rkernel_weight\x18\x01 \x01(\x04R\fkernelWeight\x12!\n" + - "\finput_weight\x18\x02 \x01(\x04R\vinputWeight\x12#\n" + - "\routput_weight\x18\x03 \x01(\x04R\foutputWeight\x12K\n" + - "#features_and_scripts_bytes_per_gram\x18\x04 \x01(\x04R\x1efeaturesAndScriptsBytesPerGram\"h\n" + - "\x0eOutputsVersion\x12)\n" + - "\aoutputs\x18\x01 \x01(\v2\x0f.tari.rpc.RangeR\aoutputs\x12+\n" + - "\bfeatures\x18\x02 \x01(\v2\x0f.tari.rpc.RangeR\bfeatures\"\x93\x01\n" + - "\x14PermittedRangeProofs\x125\n" + - "\voutput_type\x18\x01 \x01(\x0e2\x14.tari.rpc.OutputTypeR\n" + - "outputType\x12D\n" + - "\x11range_proof_types\x18\x02 \x03(\x0e2\x18.tari.rpc.RangeProofTypeR\x0frangeProofTypes\"-\n" + - "\n" + - "RangeProof\x12\x1f\n" + - "\vproof_bytes\x18\x01 \x01(\fR\n" + - "proofBytes\"\xed\x10\n" + - "\x12ConsensusConstants\x122\n" + - "\x15coinbase_min_maturity\x18\x01 \x01(\x04R\x13coinbaseMinMaturity\x12-\n" + - "\x12blockchain_version\x18\x02 \x01(\rR\x11blockchainVersion\x12*\n" + - "\x11future_time_limit\x18\x03 \x01(\x04R\x0ffutureTimeLimit\x126\n" + - "\x17difficulty_block_window\x18\x05 \x01(\x04R\x15difficultyBlockWindow\x12?\n" + - "\x1cmax_block_transaction_weight\x18\a \x01(\x04R\x19maxBlockTransactionWeight\x12$\n" + - "\x0epow_algo_count\x18\b \x01(\x04R\fpowAlgoCount\x124\n" + - "\x16median_timestamp_count\x18\t \x01(\x04R\x14medianTimestampCount\x12)\n" + - "\x10emission_initial\x18\n" + - " \x01(\x04R\x0femissionInitial\x12%\n" + - "\x0eemission_decay\x18\v \x03(\x04R\remissionDecay\x12'\n" + - "\remission_tail\x18\f \x01(\x04B\x02\x18\x01R\femissionTail\x127\n" + - "\x18min_sha3x_pow_difficulty\x18\r \x01(\x04R\x15minSha3xPowDifficulty\x12.\n" + - "\x13block_weight_inputs\x18\x0e \x01(\x04R\x11blockWeightInputs\x120\n" + - "\x14block_weight_outputs\x18\x0f \x01(\x04R\x12blockWeightOutputs\x120\n" + - "\x14block_weight_kernels\x18\x10 \x01(\x04R\x12blockWeightKernels\x12$\n" + - "\x0epre_mine_value\x18\x11 \x01(\x04R\fpreMineValue\x12/\n" + - "\x14max_script_byte_size\x18\x12 \x01(\x04R\x11maxScriptByteSize\x12C\n" + - "\x1evalidator_node_validity_period\x18\x13 \x01(\x04R\x1bvalidatorNodeValidityPeriod\x122\n" + - "\x15effective_from_height\x18\x14 \x01(\x04R\x13effectiveFromHeight\x12T\n" + - "\x1evalid_blockchain_version_range\x18\x15 \x01(\v2\x0f.tari.rpc.RangeR\x1bvalidBlockchainVersionRange\x125\n" + - "\x17max_randomx_seed_height\x18\x16 \x01(\x04R\x14maxRandomxSeedHeight\x12Q\n" + - "\rproof_of_work\x18\x17 \x03(\v2-.tari.rpc.ConsensusConstants.ProofOfWorkEntryR\vproofOfWork\x12E\n" + - "\x12transaction_weight\x18\x18 \x01(\v2\x16.tari.rpc.WeightParamsR\x11transactionWeight\x12?\n" + - "\x13input_version_range\x18\x1a \x01(\v2\x0f.tari.rpc.RangeR\x11inputVersionRange\x12J\n" + - "\x14output_version_range\x18\x1b \x01(\v2\x18.tari.rpc.OutputsVersionR\x12outputVersionRange\x12A\n" + - "\x14kernel_version_range\x18\x1c \x01(\v2\x0f.tari.rpc.RangeR\x12kernelVersionRange\x12J\n" + - "\x16permitted_output_types\x18\x1d \x03(\x0e2\x14.tari.rpc.OutputTypeR\x14permittedOutputTypes\x12!\n" + - "\fepoch_length\x18\x1e \x01(\x04R\vepochLength\x12a\n" + - ".validator_node_registration_min_deposit_amount\x18\x1f \x01(\x04R)validatorNodeRegistrationMinDepositAmount\x12[\n" + - "+validator_node_registration_min_lock_height\x18 \x01(\x04R&validatorNodeRegistrationMinLockHeight\x12i\n" + - "2validator_node_registration_shuffle_interval_epoch\x18! \x01(\x04R-validatorNodeRegistrationShuffleIntervalEpoch\x12]\n" + - "\x1bpermitted_range_proof_types\x18\" \x03(\v2\x1e.tari.rpc.PermittedRangeProofsR\x18permittedRangeProofTypes\x12%\n" + - "\x0einflation_bips\x18# \x01(\x04R\rinflationBips\x12*\n" + - "\x11tail_epoch_length\x18$ \x01(\x04R\x0ftailEpochLength\x127\n" + - "\x18max_block_coinbase_count\x18% \x01(\x04R\x15maxBlockCoinbaseCount\x1a_\n" + - "\x10ProofOfWorkEntry\x12\x10\n" + - "\x03key\x18\x01 \x01(\rR\x03key\x125\n" + - "\x05value\x18\x02 \x01(\v2\x1f.tari.rpc.PowAlgorithmConstantsR\x05value:\x028\x01*s\n" + - "\n" + - "OutputType\x12\f\n" + - "\bSTANDARD\x10\x00\x12\f\n" + - "\bCOINBASE\x10\x01\x12\b\n" + - "\x04BURN\x10\x02\x12\x1f\n" + - "\x1bVALIDATOR_NODE_REGISTRATION\x10\x03\x12\x1e\n" + - "\x1aCODE_TEMPLATE_REGISTRATION\x10\x04*:\n" + - "\x0eRangeProofType\x12\x14\n" + - "\x10BULLETPROOF_PLUS\x10\x00\x12\x12\n" + - "\x0eREVEALED_VALUE\x10\x01B$Z\"pool/internal/gbt/tari/types;typesb\x06proto3" - -var ( - file_types_proto_rawDescOnce sync.Once - file_types_proto_rawDescData []byte -) - -func file_types_proto_rawDescGZIP() []byte { - file_types_proto_rawDescOnce.Do(func() { - file_types_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc))) - }) - return file_types_proto_rawDescData -} - -var file_types_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_types_proto_msgTypes = make([]protoimpl.MessageInfo, 13) -var file_types_proto_goTypes = []any{ - (OutputType)(0), // 0: tari.rpc.OutputType - (RangeProofType)(0), // 1: tari.rpc.RangeProofType - (*Range)(nil), // 2: tari.rpc.Range - (*Empty)(nil), // 3: tari.rpc.Empty - (*BlockHeight)(nil), // 4: tari.rpc.BlockHeight - (*Signature)(nil), // 5: tari.rpc.Signature - (*ComAndPubSignature)(nil), // 6: tari.rpc.ComAndPubSignature - (*CommitmentSignature)(nil), // 7: tari.rpc.CommitmentSignature - (*PowAlgorithmConstants)(nil), // 8: tari.rpc.PowAlgorithmConstants - (*WeightParams)(nil), // 9: tari.rpc.WeightParams - (*OutputsVersion)(nil), // 10: tari.rpc.OutputsVersion - (*PermittedRangeProofs)(nil), // 11: tari.rpc.PermittedRangeProofs - (*RangeProof)(nil), // 12: tari.rpc.RangeProof - (*ConsensusConstants)(nil), // 13: tari.rpc.ConsensusConstants - nil, // 14: tari.rpc.ConsensusConstants.ProofOfWorkEntry -} -var file_types_proto_depIdxs = []int32{ - 2, // 0: tari.rpc.OutputsVersion.outputs:type_name -> tari.rpc.Range - 2, // 1: tari.rpc.OutputsVersion.features:type_name -> tari.rpc.Range - 0, // 2: tari.rpc.PermittedRangeProofs.output_type:type_name -> tari.rpc.OutputType - 1, // 3: tari.rpc.PermittedRangeProofs.range_proof_types:type_name -> tari.rpc.RangeProofType - 2, // 4: tari.rpc.ConsensusConstants.valid_blockchain_version_range:type_name -> tari.rpc.Range - 14, // 5: tari.rpc.ConsensusConstants.proof_of_work:type_name -> tari.rpc.ConsensusConstants.ProofOfWorkEntry - 9, // 6: tari.rpc.ConsensusConstants.transaction_weight:type_name -> tari.rpc.WeightParams - 2, // 7: tari.rpc.ConsensusConstants.input_version_range:type_name -> tari.rpc.Range - 10, // 8: tari.rpc.ConsensusConstants.output_version_range:type_name -> tari.rpc.OutputsVersion - 2, // 9: tari.rpc.ConsensusConstants.kernel_version_range:type_name -> tari.rpc.Range - 0, // 10: tari.rpc.ConsensusConstants.permitted_output_types:type_name -> tari.rpc.OutputType - 11, // 11: tari.rpc.ConsensusConstants.permitted_range_proof_types:type_name -> tari.rpc.PermittedRangeProofs - 8, // 12: tari.rpc.ConsensusConstants.ProofOfWorkEntry.value:type_name -> tari.rpc.PowAlgorithmConstants - 13, // [13:13] is the sub-list for method output_type - 13, // [13:13] is the sub-list for method input_type - 13, // [13:13] is the sub-list for extension type_name - 13, // [13:13] is the sub-list for extension extendee - 0, // [0:13] is the sub-list for field type_name -} - -func init() { file_types_proto_init() } -func file_types_proto_init() { - if File_types_proto != nil { - return - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: unsafe.Slice(unsafe.StringData(file_types_proto_rawDesc), len(file_types_proto_rawDesc)), - NumEnums: 2, - NumMessages: 13, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_types_proto_goTypes, - DependencyIndexes: file_types_proto_depIdxs, - EnumInfos: file_types_proto_enumTypes, - MessageInfos: file_types_proto_msgTypes, - }.Build() - File_types_proto = out.File - file_types_proto_goTypes = nil - file_types_proto_depIdxs = nil -} diff --git a/internal/gbt/tari/proto/validator_node.proto b/internal/gbt/tari/proto/validator_node.proto deleted file mode 100644 index 9b8d73e..0000000 --- a/internal/gbt/tari/proto/validator_node.proto +++ /dev/null @@ -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; -} diff --git a/internal/gbt/tari/proto/wallet.proto b/internal/gbt/tari/proto/wallet.proto deleted file mode 100644 index 5ec6d35..0000000 --- a/internal/gbt/tari/proto/wallet.proto +++ /dev/null @@ -1,1582 +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"; -import "types.proto"; -import "transaction.proto"; -import "sidechain_types.proto"; -import "network.proto"; - -// The gRPC interface for interacting with the wallet. -service Wallet { - // Returns the current version of the running wallet service. - // - // This method retrieves the semantic version of the wallet software as defined in the Cargo.toml file (e.g., "1.2.3"). Useful for diagnostics and compatibility checks. - // - // Example usage (JavaScript gRPC client): - // ```javascript - // const response = await client.getVersion({}); - // console.log(response.version); // e.g., "1.2.3" - // ``` - // - // Example response: - // ```json - // { - // "version": "1.2.3" - // } - // ``` - - rpc GetVersion (GetVersionRequest) returns (GetVersionResponse); - - // Returns the current operational state of the wallet. - // - // This RPC provides an overview of the wallet's internal status, including: - // - The latest blockchain height scanned by the wallet - // - The current balance (available, pending incoming/outgoing) - // - Network connectivity status with the base node - // - // This is commonly used by UI clients or backend systems to confirm the wallet is healthy, - // synchronized, and connected to the Tari network. - // - // Example usage (JavaScript): - // ```javascript - // const response = await client.getState({}); - // console.log(response.scanned_height); // e.g., 1523493 - // console.log(response.balance.available_balance); // e.g., 1234567890 - // console.log(response.network.status); // e.g., "Online" - // ``` - // - // Example response: - // ```json - // { - // "scanned_height": 1523493, - // "balance": { - // "available_balance": 1234567890, - // "pending_incoming_balance": 100000000, - // "pending_outgoing_balance": 0 - // }, - // "network": { - // "status": "Online", - // "avg_latency_ms": 28, - // "num_node_connections": 8 - // } - // } - // ``` - rpc GetState (GetStateRequest) returns (GetStateResponse); - - // This RPC returns a lightweight response indicating whether the wallet is connected to the network, attempting to connect, or currently offline. This is useful for UIs or clients to determine if network interactions like transactions or syncs are possible. - // - // Example usage (JavaScript): - // ```javascript - // const response = await client.checkConnectivity({}); - // console.log(response.status); // e.g., 1 (Online) - // ``` - // - // Example response: - // ```json - // { - // "status": "Online" - // } - // ``` - rpc CheckConnectivity(GetConnectivityRequest) returns (CheckConnectivityResponse); - - // Check for new updates - rpc CheckForUpdates (Empty) returns (SoftwareUpdate); - - // The `Identify` RPC call returns the identity information of the wallet node. - // This includes: - // - **Public Key**: The wallet's cryptographic public key. - // - **Public Address**: The wallet's public address used to receive funds. - // - **Node ID**: The unique identifier of the wallet node in the network. - // - // Example usage (JavaScript): - // ```javascript - // // Call the Identify RPC method - // client.Identify({}, (error, response) => { - // if (error) { - // console.error('Error:', error); - // } else { - // console.log('Identity Response:', response); - // } - // }); - // ``` - // - // **Sample JSON Response:** - // - // ```json - // { - // "public_key": "0x04b2c5f3fe65bb1c3cde019e34f3eab1234598c820dca43bbf4d5686a980ddc69e0d4b180d85990d0a5e4aee46e0a6ad9283f0a41783992a70c548e53e47321fa", - // "public_address": "14HVCEeZC2RGE4SDn3yGwqzXepJ2LDqXva7kb4fherYMQR9dF7341T3TjMZobB1a6xouGvS5SXwEvXKwK3zLz2rgReh", - // "node_id": "0x1234abcd5678efgh9012ijkl3456mnop" - // } - // ``` - rpc Identify (GetIdentityRequest) returns (GetIdentityResponse); - - // This RPC returns two types of wallet addresses: interactive and one-sided addresses. - // It provides these addresses in byte format as part of the response. - // - **Interactive Address**: This is a type of address used for interaction and communication with the wallet. - // - **One-Sided Address**: This is another address type, typically used in scenarios where a one-way interaction or transaction is needed. - // - // Example usage (JavaScript): - // // Call the GetAddress RPC method - // client.GetAddress({}, (error, response) => { - // if (error) { - // console.error('Error:', error); - // } else { - // console.log('Address Response:', response); - // } - // }); - // ``` - // - // **Sample JSON Response:** - // // ```json - // { - // "interactive_address": "0x14b27bde3f7d9c9d7455f16b056a3c439c663af93356f56e16d2b2c79e6995c44c9c6c7c", - // "one_sided_address": "0x12b35ddcb2270a72d7b327abc7cd4f607a492c6e13e72e65c34742069e48bd3bc462df63" - // } - // ``` - rpc GetAddress (Empty) returns (GetAddressResponse); - - // This RPC returns addresses generated for a specific payment ID. It provides both the interactive - // and one-sided addresses for the given payment ID, along with their respective representations in - // base58 and emoji formats. - // - // Example usage (JavaScript): - // - // ```javascript - // // Prepare the payment ID for the request - // const paymentId = Buffer.from('your_payment_id_here', 'hex'); - // const request = { payment_id: paymentId }; - // - // // Call the GetPaymentIdAddress RPC method - // client.GetPaymentIdAddress(request, (error, response) => { - // if (error) { - // console.error('Error:', error); - // } else { - // console.log('Payment ID Address Response:', response); - // } - // }); - // ``` - // - // **Sample JSON Response:** - // - // ```json - //{ - // "interactive_address": "0411aabbccddeeff00112233445566778899aabbccddeeff0011223344556677", - // "one_sided_address": "02ff8899aabbccddeeff00112233445566778899aabbccddeeff001122334455", - // "interactive_address_base58": "14HVCEeZC2RGE4SDn3yG.....6xouGvS5SXwEvXKwK3zLz2rgReh", - // "one_sided_address_base58": "12HVCEeZC2RGE4SDn3yGwqz.....obB1a6xouGvS5SXwEvXKwK3zLz2rgReL", - // "interactive_address_emoji": "🐢🌊💤🔌🚑🐛🏦⚽🍓🐭🚁🎢🔪🥐👛🍞.....🍐🍟💵🎉🍯🎁🎾🎼💻💄🍳🍐🤔🥝🍫👅🚀🐬🎭", - // "one_sided_address_emoji": "🐢📟💤🔌🚑🐛🏦⚽🍓🐭🚁🎢🔪🥐👛🍞📜.....🍐🍟💵🎉🍯🎁🎾🎼💻💄🍳🍐🤔🥝🍫👅🚀🐬🎭" - //} - //``` - // - rpc GetPaymentIdAddress (GetPaymentIdAddressRequest) returns (GetCompleteAddressResponse); - - // This RPC call that retrieves the current wallet's interactive and one-sided addresses in multiple formats and returns them in a structured response. - // The response includes: - // - Raw binary - // - Base58-encoded (human-readable) - // - Emoji-encoded (for fun and friendliness) - // - // Example usage (JavaScript with gRPC): - // - // ```js - // const client = new WalletClient('localhost:50051', grpc.credentials.createInsecure()); - // client.getCompleteAddress({}, (err, response) => { - // if (err) console.error(err); - // else console.log(response); - // }); - // ``` - // - // Sample response: - // ```json - // { - // "interactive_address": "0411aabbccddeeff00112233445566778899aabbccddeeff0011223344556677", - // "one_sided_address": "02ff8899aabbccddeeff00112233445566778899aabbccddeeff001122334455", - // "interactive_address_base58": "14HVCEeZC2RGE4SDn3yG.....6xouGvS5SXwEvXKwK3zLz2rgReh", - // "one_sided_address_base58": "12HVCEeZC2RGE4SDn3yGwqz.....obB1a6xouGvS5SXwEvXKwK3zLz2rgReL", - // "interactive_address_emoji": "🐢🌊💤🔌🚑🐛🏦⚽🍓🐭🚁🎢🔪🥐👛🍞.....🍐🍟💵🎉🍯🎁🎾🎼💻💄🍳🍐🤔🥝🍫👅🚀🐬🎭", - // "one_sided_address_emoji": "🐢📟💤🔌🚑🐛🏦⚽🍓🐭🚁🎢🔪🥐👛🍞📜.....🍐🍟💵🎉🍯🎁🎾🎼💻💄🍳🍐🤔🥝🍫👅🚀🐬🎭" - // } - // ``` - rpc GetCompleteAddress (Empty) returns (GetCompleteAddressResponse); - - // This call supports standard interactive transactions (Mimblewimble), - // one-sided transactions, and one-sided-to-stealth-address transactions. - // Each recipient must include a valid Tari address, amount, fee, and payment type. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const recipient = new PaymentRecipient(); - // recipient.setAddress("14HVCEeZ..."); - // recipient.setAmount(1000000); // 1 T - // recipient.setFeePerGram(25); - // recipient.setPaymentType(PaymentType.ONE_SIDED); - // recipient.setPaymentId(Buffer.from("abc123", "utf-8")); - // - // const request = new TransferRequest(); - // request.setRecipientsList([recipient]); - // - // client.transfer(request, (err, response) => { - // if (err) console.error(err); - // else console.log(response.toObject()); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "results": [ - // { - // "address": "14HVCEeZ...", - // "transaction_id": 12345, - // "is_success": true, - // "failure_message": "" - // } - // ] - // } - rpc Transfer (TransferRequest) returns (TransferResponse); - - // Returns the transaction details for the given transaction IDs. - // - // The GetTransactionInfo RPC retrieves detailed information about specific transactions based on their IDs. - // The response includes details such as transaction status, direction, amount, fee, and more. - // - // ### Request Parameters: - // - // - `transaction_ids` (required): - // - **Type**: `repeated uint64` - // - **Description**: A list of transaction IDs to query. - // - **Restrictions**: - // - Must contain at least one ID. - // - All IDs must be valid unsigned 64-bit integers. - // - Duplicates will be ignored; only the first occurrence is processed. - // - If a transaction ID is not found, it will be returned with a `status` of `NOT_FOUND`. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { transaction_ids: [12345, 67890] }; - // client.getTransactionInfo(request, (err, response) => { - // if (err) console.error(err); - // else console.log(response.transactions); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "transactions": [ - // { - // "tx_id": 12345, - // "source_address": "0x1234abcd...", - // "dest_address": "0x5678efgh...", - // "status": "TRANSACTION_STATUS_MINED_CONFIRMED", - // "direction": "TRANSACTION_DIRECTION_OUTBOUND", - // "amount": 1000000, - // "fee": 25, - // "is_cancelled": false, - // "excess_sig": "0xabcdef...", - // "timestamp": 1681234567, - // "payment_id": "0xdeadbeef...", - // "mined_in_block_height": 1523493 - // } - // ] - // } - rpc GetTransactionInfo (GetTransactionInfoRequest) returns (GetTransactionInfoResponse); - - // Streams completed transactions for a given user payment ID. - // - // The `GetCompletedTransactions` call retrieves all completed wallet transactions, - // optionally filtered by a specific `payment_id` and/or block hash. The response is streamed back to the client - // one transaction at a time, with each transaction including details such as status, direction, - // amount, fees, and associated metadata. - // - // ### Request Parameters: - // - // - `payment_id` (optional): - // - **Type**: `UserPaymentId` (a flexible ID object) - // - **Description**: Allows filtering the completed transactions by a specific payment ID. - // - **Accepted Formats** (must provide **only one**): - // - `u256`: a 32-byte hexadecimal string. - // - `utf8_string`: a UTF-8 string. - // - `user_bytes`: raw bytes. - // - **Restrictions**: - // - Exactly **one format must be set**. Providing more than one or none results in an error. - // - If no `payment_id` is provided, all completed transactions will be returned. - // - // - `block_hash` (optional): - // - **Type**: `string` - // - **Description**: A specific block hash to filter transactions by. - // - **Accepted Formats** - // - Hexadecimal string representing the block hash. - // - **Restrictions**: - // - If provided, the transactions will be filtered to only those included in the specified block. - // - // - `block_height` (optional): - // - **Type**: `uint64` - // - **Description**: A specific block height to filter transactions by. - // - **Restrictions**: - // - If provided, the transactions will be filtered to only those included in the specified height. - - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { - // payment_id: { - // utf8_string: "invoice-001" - // } - // }; - // const call = client.getCompletedTransactions(request); - // call.on('data', (response) => { - // console.log(response.transaction); - // }); - // call.on('error', console.error); - // call.on('end', () => console.log("Stream ended")); - // ``` - // - // ### Sample Streamed JSON Response: - // - // ```json - // { - // "transaction": { - // "tx_id": 12345, - // "source_address": "0x1234abcd...", - // "dest_address": "0x5678efgh...", - // "status": "TRANSACTION_STATUS_MINED_CONFIRMED", - // "direction": "TRANSACTION_DIRECTION_INBOUND", - // "amount": 500000, - // "fee": 20, - // "is_cancelled": false, - // "excess_sig": "0xabcdef...", - // "timestamp": 1681234567, - // "payment_id": "0xdeadbeef...", - // "mined_in_block_height": 1523493 - // } - // } - // ``` - rpc GetCompletedTransactions (GetCompletedTransactionsRequest) returns (stream GetCompletedTransactionsResponse); - - // Returns all transactions that were mined at a specific block height. - // - // The `GetBlockHeightTransactions` call retrieves all wallet transactions that were mined - // at the specified block height. The response includes all transactions in a single response, - // with each transaction including details such as status, direction, amount, - // fees, and associated metadata. - // - // ### Request Parameters: - // - // - `block_height` (required): - // - **Type**: `uint64` - // - **Description**: The specific block height to fetch transactions for. - // - **Restrictions**: - // - Must be a valid block height (greater than 0). - // - If the block height is beyond the current chain height, no transactions will be returned. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { - // block_height: 1523493 - // }; - // const response = await client.getBlockHeightTransactions(request); - // console.log(response.transactions); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "transactions": [ - // { - // "tx_id": 12345, - // "source_address": "0x1234abcd...", - // "dest_address": "0x5678efgh...", - // "status": "TRANSACTION_STATUS_MINED_CONFIRMED", - // "direction": "TRANSACTION_DIRECTION_INBOUND", - // "amount": 500000, - // "fee": 20, - // "is_cancelled": false, - // "excess_sig": "0xabcdef...", - // "timestamp": 1681234567, - // "payment_id": "0xdeadbeef...", - // "mined_in_block_height": 1523493 - // } - // ] - // } - // ``` - rpc GetBlockHeightTransactions (GetBlockHeightTransactionsRequest) returns (GetBlockHeightTransactionsResponse); - - // Returns all PayRefs (payment references) for a specific transaction. - // - // The `GetTransactionPayRefs` call retrieves all PayRefs associated with the specified - // transaction ID. PayRefs are cryptographic references generated from output hashes - // that allow recipients to verify payments without revealing sensitive transaction details. - // - // ### Request Parameters: - // - // - `transaction_id` (required): - // - **Type**: `uint64` - // - **Description**: The transaction ID to retrieve PayRefs for. - // - **Restrictions**: - // - Must be a valid transaction ID that exists in the wallet. - // - If the transaction ID is invalid or not found, an error will be returned. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { - // transaction_id: 12345 - // }; - // const response = await client.getTransactionPayRefs(request); - // console.log("PayRefs:", response.payment_references.map(ref => Buffer.from(ref).toString('hex'))); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "payment_references": [ - // "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - // "0xfedcba0987654321fedcba0987654321fedcba0987654321fedcba0987654321" - // ] - // } - // ``` - rpc GetTransactionPayRefs (GetTransactionPayRefsRequest) returns (GetTransactionPayRefsResponse); - - - // Returns the wallet balance details. - // - // The `GetBalance` call retrieves the current balance status of the wallet, - // optionally filtered by a specific `payment_id`. The response includes detailed - // breakdowns of available, pending incoming/outgoing, and timelocked balances. - // - // ### Request Parameters: - // - // - `payment_id` (optional): - // - **Type**: `UserPaymentId` (one of several formats). - // - **Description**: An optional filter to retrieve the balance associated with a specific payment ID. - // - **Accepted Formats** (must provide **only one**): - // - `u256`: a 32-byte hexadecimal identifier. - // - `utf8_string`: a human-readable string ID. - // - `user_bytes`: raw binary bytes. - // - **Restrictions**: - // - Only one format must be provided at a time. - // - If multiple or no formats are provided within `payment_id`, the request will return an error. - // - If `payment_id` is omitted, the total wallet balance is returned. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { - // payment_id: { - // utf8_string: "invoice-002" - // } - // }; - // client.getBalance(request, (err, response) => { - // if (err) console.error(err); - // else console.log("Balance:", response); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "available_balance": 950000, - // "pending_incoming_balance": 200000, - // "pending_outgoing_balance": 50000, - // "timelocked_balance": 100000 - // } - // ``` - rpc GetBalance (GetBalanceRequest) returns (GetBalanceResponse); - - // Returns the total value of unspent outputs in the wallet. - // - // The `GetUnspentAmounts` call retrieves the sum of all unspent output amounts - // currently held by the wallet. These are outputs that have not yet been spent or time-locked, - // and are available for future transactions. - // - // ### Request Parameters: - // - // - *(none)* - // - This method uses an empty request body (`google.protobuf.Empty`). - // - No filters or arguments are required. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // client.getUnspentAmounts({}, (err, response) => { - // if (err) console.error(err); - // else console.log("Total unspent amount:", response.amount); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "amount": 1250000 - // } - // ``` - rpc GetUnspentAmounts (Empty) returns (GetUnspentAmountsResponse); - - // Creates a transaction that splits funds into multiple smaller outputs. - // - // The `CoinSplit` call initiates a transaction that divides wallet funds into several equal-sized outputs. - // This is useful for preparing a wallet for many small transactions (e.g., for micropayments or batching). - // The resulting transaction is broadcast and can be tracked via its transaction ID. - // - // ### Request Parameters: - // - // - `amount_per_split` (required): - // - **Type**: `uint64` - // - **Description**: The value of each individual output in the split. - // - **Restrictions**: Must be greater than zero. - // - // - `split_count` (required): - // - **Type**: `uint64` - // - **Description**: The number of outputs to create. - // - **Restrictions**: Must be greater than zero and within practical system limits. - // - // - `fee_per_gram` (required): - // - **Type**: `uint64` - // - **Description**: The transaction fee rate (per gram of weight). - // - **Restrictions**: Should be set high enough to ensure confirmation. - // - // - `lock_height` (optional): - // - **Type**: `uint64` - // - **Description**: The earliest block height at which the transaction becomes valid. - // - **Restrictions**: Defaults to 0 if not specified. - // - // - `payment_id` (optional): - // - **Type**: `bytes` - // - **Description**: A user-defined identifier for tracking or referencing the transaction. - // - **Restrictions**: Optional; can be left empty. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { - // amount_per_split: 100000, - // split_count: 5, - // fee_per_gram: 25, - // lock_height: 0, - // payment_id: new Uint8Array([]) - // }; - // client.coinSplit(request, (err, response) => { - // if (err) console.error(err); - // else console.log("Created CoinSplit Tx ID:", response.tx_id); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "tx_id": 987654321 - // } - // ``` - rpc CoinSplit (CoinSplitRequest) returns (CoinSplitResponse); - - // Imports UTXOs into the wallet as spendable outputs. - // - // The `ImportUtxos` call allows you to manually insert one or more previously received UTXOs - // into the wallet, marking them as spendable without needing rewindable metadata. - // Each UTXO is associated with a transaction ID in the response. - // - // ### Request Parameters: - // - // - `outputs` (required): - // - **Type**: `repeated UnblindedOutput` - // - **Description**: A list of unblinded outputs to import into the wallet. - // - **Restrictions**: - // - Each output must be valid and convertible to an internal UTXO format. - // - The list must contain at least one item. - // - // - `payment_id` (optional): - // - **Type**: `bytes` - // - **Description**: An optional user-defined identifier to associate with the imported outputs. - // - **Restrictions**: - // - Can be left empty if not needed. - // - Must be a valid byte string if provided. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { - // outputs: [/* array of unblinded outputs */], - // payment_id: new Uint8Array([]) - // }; - // client.importUtxos(request, (err, response) => { - // if (err) console.error(err); - // else console.log("Imported Tx IDs:", response.tx_ids); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "tx_ids": [101, 102, 103] - // } - // ``` - rpc ImportUtxos (ImportUtxosRequest) returns (ImportUtxosResponse); - - // Returns the wallet's current network connectivity status. - // - // The `GetNetworkStatus` call provides a snapshot of the wallet's connection to the Tari network, - // including whether it is online, the number of active peer connections, and the average latency - // to the configured base node. - // - // ### Request Parameters: - // - // - *(none)* - // - This method uses an empty request body (`google.protobuf.Empty`). - // - No filters or arguments are required. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // client.getNetworkStatus({}, (err, response) => { - // if (err) console.error(err); - // else console.log("Network Status:", response); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "status": "ONLINE", - // "avg_latency_ms": 142, - // "num_node_connections": 8 - // } - // ``` - // - // ### Status Field Values: - // - // The `status` field indicates the current network connectivity of the wallet. Possible values are: - // - // - `ONLINE`: - // - The wallet is fully connected to the network and functioning normally. - // - The node has enough active peer connections to operate efficiently. - // - // - `DEGRADED`: - // - The wallet is connected to some peers but not enough to maintain full functionality. - // - This could indicate issues with network connectivity, such as intermittent disconnections or insufficient peers, leading to reduced performance or reliability. - // - // - `OFFLINE`: - // - The wallet is not connected to any peers. - // - This status means the wallet is unable to communicate with the network and cannot perform any network-related operations. - // - rpc GetNetworkStatus(Empty) returns (NetworkStatusResponse); - - // Returns a list of peers currently connected to the wallet. - // - // The `ListConnectedPeers` call retrieves information about peers that the wallet is currently - // connected to. This includes details such as peer addresses, connection status, supported protocols, - // and other metadata relevant to the connection. - // - // ### Request Parameters: - // - // - *(none)* - // - This method uses an empty request body (`google.protobuf.Empty`). - // - No filters or arguments are required. - // - // ### Response Fields: - // - // - **connected_peers**: List of peers currently connected to the wallet. - // - **public_key**: The peer's public key (bytes). - // - **node_id**: The unique node ID of the peer (bytes). - // - **addresses**: List of the peer's addresses (repeated Address). - // - **last_connection**: The timestamp of the last connection attempt (uint64). - // - **flags**: Flags associated with the peer (uint32). - // - **banned_until**: The timestamp until which the peer is banned (uint64, 0 if not banned). - // - **banned_reason**: The reason for banning the peer (string, empty if not banned). - // - **offline_at**: The timestamp indicating when the peer went offline (uint64, 0 if online). - // - **features**: The features supported by the peer (uint32). - // - **supported_protocols**: List of supported protocols by the peer (repeated bytes). - // - **user_agent**: The user agent advertised by the peer (string). - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // client.listConnectedPeers({}, (err, response) => { - // if (err) console.error(err); - // else console.log("Connected Peers:", response); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "connected_peers": [ - // { - // "public_key": "0x1234abcd...", - // "node_id": "0x5678efgh...", - // "addresses": [ - // "127.0.0.1:18080", - // "192.168.1.2:18080" - // ], - // "last_connection": 1625493123, - // "flags": 1, - // "banned_until": 0, - // "banned_reason": "", - // "offline_at": 0, - // "features": 10, - // "supported_protocols": [ - // "protocol_v1", - // "protocol_v2" - // ], - // "user_agent": "TariBaseNode/1.0.0" - // } - // ] - // } - // ``` - rpc ListConnectedPeers(Empty) returns (ListConnectedPeersResponse); - - // Cancels a specific transaction by its ID. - // - // The `CancelTransaction` call allows a transaction to be cancelled by its unique transaction ID (TxId). - // If the cancellation is successful, the response will indicate success. Otherwise, the response will - // contain a failure message with the reason for the failure. - // - // ### Request Parameters: - // - // - **tx_id**: The unique identifier for the transaction to be cancelled (uint64). - // - // ### Response Fields: - // - // - **is_success**: A boolean indicating whether the cancellation was successful (bool). - // - `true` if the cancellation was successful, `false` if not. - // - **failure_message**: A string that provides the reason for the failure, if applicable (string). - // - This field will be empty if the cancellation was successful. - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { tx_id: 12345 }; - // client.cancelTransaction(request, (err, response) => { - // if (err) console.error(err); - // else console.log(response); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "is_success": true, - // "failure_message": "" - // } - // ``` - rpc CancelTransaction (CancelTransactionRequest) returns (CancelTransactionResponse); - - // Will trigger a complete revalidation of all wallet outputs. - rpc RevalidateAllTransactions (RevalidateRequest) returns (RevalidateResponse); - - // Will trigger a validation of all wallet outputs. - rpc ValidateAllTransactions (ValidateRequest) returns (ValidateResponse); - - // Sends a XTR SHA Atomic Swap transaction. - // - // The `SendShaAtomicSwapTransaction` call is used to initiate an Atomic Swap - // transaction using SHA. It allows the sender to send a payment to the recipient - // in exchange for an atomic swap, with SHA used as the secret for the swap. - // The method accepts the recipient's information and initiates the transaction. - // - // ### Request Parameters: - // - **recipient** (required): A PaymentRecipient object containing the recipient's address, - // the amount to be swapped, the fee per gram, and the payment ID to identify the transaction. - // - // ### Response Fields: - // - **transaction_id**: The ID of the transaction. - // - **pre_image**: The SHA pre-image of the atomic swap. - // - **output_hash**: The hash of the output associated with the transaction. - // - **is_success**: Indicates whether the transaction was successful (true) or failed (false). - // - **failure_message**: Provides an error message if the transaction failed. - // - // ### Example JavaScript gRPC client usage: - // ```javascript - // const request = { - // recipient: { - // address: "t1abc12345", - // amount: 1000000, - // fee_per_gram: 10, - // payment_id: "0xdeadbeef" - // } - // }; - // client.sendShaAtomicSwapTransaction(request, (err, response) => { - // if (err) console.error(err); - // else console.log(response); - // }); - // ``` - // - // ### Sample JSON Response: - // ```json - // { - // "transaction_id": 123456789, - // "pre_image": "0xabcdef1234567890", - // "output_hash": "0x123456abcdef7890", - // "is_success": true, - // "failure_message": "" - // } - rpc SendShaAtomicSwapTransaction(SendShaAtomicSwapRequest) returns (SendShaAtomicSwapResponse); - - // Creates a burn transaction for burning a specified amount of Tari currency. - // - // The `CreateBurnTransaction` call facilitates burning a certain amount of Tari - // by initiating a burn transaction. It allows the user to specify the amount to burn, - // along with a fee per gram and optionally a payment ID and claim public key. - // - // ### Request Parameters: - // - **amount** (required): The amount of Tari to be burned. - // - **fee_per_gram** (required): The fee per gram for the transaction. - // - **claim_public_key** (optional): The public key to claim ownership of the burned coins. - // - **payment_id** (optional): A unique identifier for the payment associated with the burn transaction. - // - // ### Response Fields: - // - **transaction_id**: The ID of the burn transaction. - // - **is_success**: Indicates whether the burn transaction was successfully created. - // - **failure_message**: Provides an error message if the transaction creation failed. - // - **commitment**: The commitment associated with the burn transaction. - // - **ownership_proof**: A proof of ownership for the burned coins. - // - **range_proof**: The range proof associated with the burned coins. - // - **reciprocal_claim_public_key**: The public key of the reciprocal claim for the burn. - // - // ### Example JavaScript gRPC client usage: - // ```javascript - // const request = { - // amount: 1000000, - // fee_per_gram: 10, - // claim_public_key: "0xabcdef1234567890", - // payment_id: "0xdeadbeef" - // }; - // client.createBurnTransaction(request, (err, response) => { - // if (err) console.error(err); - // else console.log(response); - // }); - // ``` - // - // ### Sample JSON Response: - // ```json - // { - // "transaction_id": 123456789, - // "is_success": true, - // "failure_message": "", - // "commitment": "0xcommitmenthash", - // "ownership_proof": "0xownershipproof", - // "range_proof": "0xrangeproof", - // "reciprocal_claim_public_key": "0xreciprocalpublickey" - // } - rpc CreateBurnTransaction(CreateBurnTransactionRequest) returns (CreateBurnTransactionResponse); - - // Claims a SHA Atomic Swap transaction using a pre-image and output hash. - // - // The `ClaimShaAtomicSwapTransaction` call allows the user to unlock and claim funds from - // a hash-time-locked contract (HTLC) by supplying the correct pre-image that matches a - // previously committed SHA-256 hash. This pre-image proves the user's knowledge of the - // secret required to spend the output. - // - // ### Request Parameters: - // - **output** (required): The hex-encoded output hash (SHA-256 digest) that was locked in the atomic swap. - // - **pre_image** (required): The hex-encoded original pre-image (raw bytes, *not* hashed) which, when hashed with SHA-256, must match the `output` hash. - // - **fee_per_gram** (required): The transaction fee per gram, specified as an unsigned integer. - // - // ### Input Validation: - // - `output` must be a valid hex-encoded SHA-256 hash (64 hex characters). - // - `pre_image` must be a valid hex string representing the original secret (any byte length, commonly 32 bytes). - // - `fee_per_gram` must be a non-zero `uint64`; a fee of `0` may be rejected or deprioritized by the network. - // - // ### Response Fields: - // - **results**: A `TransferResult` object containing transaction ID, success status, and an error message if applicable. - // - // ### Example JavaScript gRPC client usage: - // ```javascript - // const request = { - // output: "3e1f89af...e923", // SHA-256 hash of the expected pre-image - // pre_image: "6a1b2c...eaf1", // raw pre-image (not hashed) - // fee_per_gram: 10 - // }; - // client.claimShaAtomicSwapTransaction(request, (err, response) => { - // if (err) console.error(err); - // else console.log(response.results); - // }); - // ``` - // - // ### Sample JSON Response: - // ```json - // { - // "results": { - // "address": "", - // "transaction_id": 789654, - // "is_success": true, - // "failure_message": "" - // } - // } - rpc ClaimShaAtomicSwapTransaction(ClaimShaAtomicSwapRequest) returns (ClaimShaAtomicSwapResponse); - - // Claims an HTLC refund transaction after the timelock period has passed. - // - // The `ClaimHtlcRefundTransaction` call enables the original sender of a Hash Time-Locked Contract (HTLC) - // to reclaim the locked funds if the recipient has not claimed them in time using the correct pre-image. - // This is possible only after the output's timelock has expired. - // - // ### Request Parameters: - // - **output_hash** (required): Hex-encoded SHA-256 hash of the HTLC output being refunded. - // - **fee_per_gram** (required): Transaction fee per gram, specified as a `uint64`. - // - // ### Input Validation: - // - `output_hash` must be a valid 64-character hex string representing the hash of the HTLC output. - // - `fee_per_gram` must be a non-zero `uint64` value. - // - // ### Response Fields: - // - **results**: A `TransferResult` object including transaction ID, success status, and failure reason if any. - // - // ### Example JavaScript gRPC client usage: - // ```javascript - // const request = { - // output_hash: "aabbccddeeff0011...99", - // fee_per_gram: 20 - // }; - // client.claimHtlcRefundTransaction(request, (err, response) => { - // if (err) console.error(err); - // else console.log(response.results); - // }); - // ``` - // - // ### Sample JSON Response: - // ```json - // { - // "results": { - // "address": "", - // "transaction_id": 889977, - // "is_success": true, - // "failure_message": "" - // } - // } - rpc ClaimHtlcRefundTransaction(ClaimHtlcRefundRequest) returns (ClaimHtlcRefundResponse); - - // Creates a transaction with a template registration output - rpc CreateTemplateRegistration(CreateTemplateRegistrationRequest) returns (CreateTemplateRegistrationResponse); - - // The SetBaseNode call configures the base node peer for the wallet. - // - // This RPC sets the public key and network address of the base node peer that the wallet should communicate with. - // - // ### Request Fields: - // - `public_key_hex` (string): The public key of the base node, provided as a hex string. - // - `net_address` (string): The multiaddress of the base node (e.g., `/ip4/127.0.0.1/tcp/18141`). - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const request = { - // public_key_hex: "0281bdfc...", - // net_address: "/ip4/127.0.0.1/tcp/18141" - // }; - // client.setBaseNode(request, (err, response) => { - // if (err) console.error(err); - // else console.log("Base node set successfully"); - // }); - // ``` - // - // ### Sample JSON Request: - // ```json - // { - // "public_key_hex": "0281bdfc...", - // "net_address": "/ip4/127.0.0.1/tcp/18141" - // } - // ``` - // - // ### Sample JSON Response: - // ```json - // {} - // ``` - rpc SetBaseNode(SetBaseNodeRequest) returns (SetBaseNodeResponse); - - // Streams real-time wallet transaction events to the client. - // - // The `StreamTransactionEvents` RPC provides a continuous stream of transaction events as they occur within the wallet. - // This allows clients to react to changes in transaction status such as received, sent, mined, or cancelled transactions, - // making it ideal for real-time UI updates or external monitoring. - // - // ### Request Parameters: - // - _(none)_ – This RPC does not take any parameters. - // - // ### Response Stream: - // - Each message in the response stream is a `TransactionEventResponse` containing: - // - **transaction**: A `TransactionEvent` object representing the latest event related to a wallet transaction. - // - // ### `TransactionEvent` Fields: - // - **event** (string): Human-readable event type. Examples include: `"Received"`, `"Mined"`, `"Cancelled"`, `"Sent"`. - // - **tx_id** (string): Transaction identifier. - // - **source_address** (bytes): Sender address, if applicable. - // - **dest_address** (bytes): Recipient address, if applicable. - // - **status** (string): Current status of the transaction. E.g., `"Completed"`, `"Pending"`, `"Cancelled"`. - // - **direction** (string): `"Inbound"` or `"Outbound"`. - // - **amount** (uint64): Transaction amount in microTari. - // - **payment_id** (bytes): Payment ID associated with the transaction. - // - - // ### Example JavaScript gRPC client usage: - // ```javascript - // const call = client.streamTransactionEvents({}); - // - // call.on("data", (response) => { - // console.log("Transaction Event:", response.transaction); - // }); - // - // call.on("end", () => { - // console.log("Stream ended."); - // }); - // - // call.on("error", (err) => { - // console.error("Stream error:", err); - // }); - // ``` - // - // ### Sample JSON Streamed Response: - // ```json - // { - // "transaction": { - // "event": "Mined", - // "tx_id": "103248", - // "source_address": "0xabc123...", - // "dest_address": "0xdef456...", - // "status": "Completed", - // "direction": "Outbound", - // "amount": 100000000, - // "payment_id": "0xdeadbeef..." - // } - // } - // ``` - rpc StreamTransactionEvents(TransactionEventRequest) returns (stream TransactionEventResponse); - - rpc RegisterValidatorNode(RegisterValidatorNodeRequest) returns (RegisterValidatorNodeResponse); - - rpc ImportTransactions(ImportTransactionsRequest) returns (ImportTransactionsResponse); - - // Get all completed transactions including cancelled ones, sorted by timestamp and paginated - rpc GetAllCompletedTransactions(GetAllCompletedTransactionsRequest) returns (GetAllCompletedTransactionsResponse); - - // Gets transaction information by payment reference (PayRef) - // - // The `GetPaymentByReference` call retrieves transaction information using a 32-byte payment reference hash. - // PayRefs are generated as Blake2b_256(block_hash || output_hash) and provide a stable way to look up - // transactions even after outputs are spent. - // - // ### Request Parameters: - // - // - `payment_reference` (required): - // - **Type**: `bytes` (32 bytes) - // - **Description**: The payment reference hash to look up - // - **Restrictions**: Must be exactly 32 bytes representing a valid PayRef - // - // ### Example JavaScript gRPC client usage: - // - // ```javascript - // const payref = Buffer.from('a1b2c3d4e5f6789012345678901234567890123456789012345678901234567890', 'hex'); - // const request = { payment_reference: payref }; - // client.getPaymentByReference(request, (err, response) => { - // if (err) console.error(err); - // else console.log('Transaction found:', response.transaction); - // }); - // ``` - // - // ### Sample JSON Response: - // - // ```json - // { - // "transaction": { - // "tx_id": 12345, - // "source_address": "0x1234abcd...", - // "dest_address": "0x5678efgh...", - // "status": "TRANSACTION_STATUS_MINED_CONFIRMED", - // "direction": "TRANSACTION_DIRECTION_INBOUND", - // "amount": 1000000, - // "fee": 20, - // "is_cancelled": false, - // "excess_sig": "0xabcdef...", - // "timestamp": 1681234567, - // "payment_id": "0xdeadbeef...", - // "mined_in_block_height": 150000 - // } - // } - // ``` - rpc GetPaymentByReference(GetPaymentByReferenceRequest) returns (GetPaymentByReferenceResponse); -} - - -message GetVersionRequest {} - - -message GetVersionResponse { - string version = 1; -} - -message GetAddressResponse { - bytes interactive_address = 1; - bytes one_sided_address = 2; -} - -message GetPaymentIdAddressRequest { - bytes payment_id = 1; -} -// Response message containing all formats of wallet addresses. -message GetCompleteAddressResponse { - // Binary form of the interactive address. - bytes interactive_address = 1; - // Binary form of the one-sided address. - bytes one_sided_address = 2; - // Base58-encoded version of the interactive address. - string interactive_address_base58 = 3; - // Base58-encoded version of the one-sided address. - string one_sided_address_base58 = 4; - // Emoji-encoded version of the interactive address. - string interactive_address_emoji = 5; - // Emoji-encoded version of the one-sided address. - string one_sided_address_emoji = 6; -} - -// A request to send funds to one or more recipients. -message TransferRequest { - repeated PaymentRecipient recipients = 1; -} - -message SendShaAtomicSwapRequest { - PaymentRecipient recipient = 1; -} - -message CreateBurnTransactionRequest{ - uint64 amount = 1; - uint64 fee_per_gram = 2; - bytes claim_public_key = 4; - bytes payment_id = 5; -} - -// A recipient for a transfer, including address, amount, fee, and optional payment ID. -message PaymentRecipient { - // Base58 Tari address of the recipient. - string address = 1; - // Amount to send in microTari (1 T = 1_000_000 µT). - uint64 amount = 2; - // Fee rate per gram. - uint64 fee_per_gram = 3; - enum PaymentType { - // Default Mimblewimble-style transaction. - STANDARD_MIMBLEWIMBLE = 0 [deprecated = true] ; - // One-sided transaction (receiver not required to participate). - ONE_SIDED = 1 [deprecated = true] ; - // One-sided stealth address (adds privacy by hiding destination). - ONE_SIDED_TO_STEALTH_ADDRESS = 2; - } - // The type of payment to perform. - PaymentType payment_type = 5; - // raw payment id - bytes raw_payment_id = 6; - // Optional user encrypted payment ID for reference (max 256 bytes). - UserPaymentId user_payment_id = 7; -} - -message TransferResponse { - repeated TransferResult results = 1; -} - -message SendShaAtomicSwapResponse { - uint64 transaction_id = 1; - string pre_image = 2; - string output_hash = 3; - bool is_success = 4; - string failure_message = 5; -} - -message CreateBurnTransactionResponse{ - uint64 transaction_id = 1; - bool is_success = 2; - string failure_message = 3; - bytes commitment = 4; - CommitmentSignature ownership_proof = 5; - bytes range_proof = 6; - bytes reciprocal_claim_public_key = 7; -} - -message TransferResult { - string address = 1; - uint64 transaction_id = 2; - bool is_success = 3; - string failure_message = 4; - TransactionInfo transaction_info = 5; -} - -message ClaimShaAtomicSwapRequest{ - string output = 1; - string pre_image = 2; - uint64 fee_per_gram = 3; -} - -message ClaimShaAtomicSwapResponse { - TransferResult results = 1; -} - -message ClaimHtlcRefundRequest{ - string output_hash = 1; - uint64 fee_per_gram = 2; -} - -message ClaimHtlcRefundResponse { - TransferResult results = 1; -} - -message GetTransactionInfoRequest { - repeated uint64 transaction_ids = 1; -} - -message GetTransactionInfoResponse { - repeated TransactionInfo transactions = 1; -} - -message TransactionInfo { - uint64 tx_id = 1; - bytes source_address = 2; - bytes dest_address = 3; - TransactionStatus status = 4; - TransactionDirection direction = 5; - uint64 amount = 6; - uint64 fee = 7; - bool is_cancelled = 8; - bytes excess_sig = 9; - uint64 timestamp = 10; - bytes raw_payment_id = 12; - uint64 mined_in_block_height = 13; - bytes user_payment_id = 14; - repeated bytes input_commitments = 15; - repeated bytes output_commitments = 16; - repeated bytes payment_references_sent = 17; - repeated bytes payment_references_received = 18; - repeated bytes payment_references_change = 19; -} - -enum TransactionDirection { - TRANSACTION_DIRECTION_UNKNOWN = 0; - TRANSACTION_DIRECTION_INBOUND = 1; - TRANSACTION_DIRECTION_OUTBOUND = 2; -} - -enum TransactionStatus { - // This transaction has been completed between the parties but has not been broadcast to the base layer network. - TRANSACTION_STATUS_COMPLETED = 0; - // This transaction has been broadcast to the base layer network and is currently in one or more base node mempools. - TRANSACTION_STATUS_BROADCAST = 1; - // This transaction has been mined and included in a block. - TRANSACTION_STATUS_MINED_UNCONFIRMED = 2; - // This transaction was generated as part of importing a spendable UTXO - TRANSACTION_STATUS_IMPORTED = 3; - // This transaction is still being negotiated by the parties - TRANSACTION_STATUS_PENDING = 4; - // This is a created Coinbase Transaction - TRANSACTION_STATUS_COINBASE = 5; - // This transaction is mined and confirmed at the current base node's height - TRANSACTION_STATUS_MINED_CONFIRMED = 6; - // The transaction was rejected by the mempool - TRANSACTION_STATUS_REJECTED = 7; - // This is faux transaction mainly for one-sided transaction outputs or wallet recovery outputs have been found - TRANSACTION_STATUS_ONE_SIDED_UNCONFIRMED = 8; - // All Imported and FauxUnconfirmed transactions will end up with this status when the outputs have been confirmed - TRANSACTION_STATUS_ONE_SIDED_CONFIRMED = 9; - // This transaction is still being queued for sending - TRANSACTION_STATUS_QUEUED = 10; - // The transaction was not found by the wallet its in transaction database - TRANSACTION_STATUS_NOT_FOUND = 11; - // This is Coinbase transaction that is detected from chain - TRANSACTION_STATUS_COINBASE_UNCONFIRMED = 12; - // This is Coinbase transaction that is detected from chain - TRANSACTION_STATUS_COINBASE_CONFIRMED = 13; - // This is Coinbase transaction that is not currently detected as mined - TRANSACTION_STATUS_COINBASE_NOT_IN_BLOCK_CHAIN = 14; -} - -message GetCompletedTransactionsRequest { - UserPaymentId payment_id = 1; - BlockHashHex block_hash = 2; - BlockHeight block_height = 3; -} - -message BlockHashHex { - string hash = 1; -} - -message GetCompletedTransactionsResponse { - TransactionInfo transaction = 1; -} - - -// Request message for GetBalance RPC. -message GetBalanceRequest { - // Optional: A user-defined payment ID to filter balance data. - // Must provide only one of the following fields: u256, utf8_string, or user_bytes. - UserPaymentId payment_id = 1; -} - -message UserPaymentId { - bytes u256 = 1; - string utf8_string = 2; - bytes user_bytes = 3; -} - -message GetStateRequest {} - -message GetBalanceResponse { - uint64 available_balance = 1; - uint64 pending_incoming_balance = 2; - uint64 pending_outgoing_balance = 3; - uint64 timelocked_balance = 4; -} - -// Response message for GetState -message GetStateResponse { - // The blockchain height (in blocks) that the wallet has scanned up to - uint64 scanned_height = 1; - // Current wallet balance information (available, pending), based on the GetBalanceResponse - GetBalanceResponse balance = 2; - // Status of the wallet's connection to the base node, based on the NetworkStatusResponse - NetworkStatusResponse network = 3; -} - -// Response message for GetUnspentAmounts RPC. -message GetUnspentAmountsResponse { - // Total value of all unspent outputs, in the smallest unit (e.g., microTari). - repeated uint64 amount = 1; -} - -// Request message for the CoinSplit RPC. -message CoinSplitRequest { - // The value of each output to create. - uint64 amount_per_split = 1; - // The number of outputs to create in total. - uint64 split_count = 2; - // Fee rate per weight unit (gram). - uint64 fee_per_gram = 3; - // Block height when the transaction becomes valid. - uint64 lock_height = 5; - // Optional identifier for referencing the transaction. - bytes payment_id = 6; -} - -// Response message containing the transaction ID of the coin split. -message CoinSplitResponse { - // The unique ID of the transaction created. - uint64 tx_id = 1; -} - -// Request message for importing UTXOs into the wallet. -message ImportUtxosRequest { - // List of unblinded outputs to be imported as UTXOs. - repeated UnblindedOutput outputs = 1; - - // Optional payment ID to tag the imported outputs. - bytes payment_id = 2; -} - -// Response message containing transaction IDs for the imported outputs. -message ImportUtxosResponse { - // Transaction IDs corresponding to the imported UTXOs. - repeated uint64 tx_ids = 1; -} - -message CreateTemplateRegistrationRequest { - TemplateRegistration template_registration = 1; - uint64 fee_per_gram = 2; -} - -message CreateTemplateRegistrationResponse { - uint64 tx_id = 1; - bytes template_address = 2; -} - -// Request message for the CancelTransaction RPC. -message CancelTransactionRequest { - // The transaction ID to be cancelled. - uint64 tx_id = 1; -} - -// Response message for the CancelTransaction RPC. -message CancelTransactionResponse { - // Indicates whether the cancellation was successful. - bool is_success = 1; - - // The failure message if the cancellation was not successful. - string failure_message = 2; -} - -message RevalidateRequest{} - -message RevalidateResponse{} - -message ValidateRequest{} - -message ValidateResponse{} - -message SetBaseNodeRequest { - string public_key_hex = 1; - string net_address = 2; -} - -message SetBaseNodeResponse{} - -// Empty request for CheckConnectivity -message GetConnectivityRequest{} - -// Response indicating the wallet's connectivity status -message CheckConnectivityResponse{ - // Describes the wallet's network connection state - enum OnlineStatus { - // The wallet is attempting to connect to peers - Connecting = 0; - // The wallet is successfully connected to peers - Online = 1; - // The wallet is not connected to any peers - Offline = 2; - } - // The current connectivity state of the wallet - OnlineStatus status = 1; -} - -message TransactionEventRequest{ - -} - -message TransactionEvent { - string event = 1; - string tx_id = 2; - bytes source_address = 3; - bytes dest_address = 4; - string status = 5; - string direction = 6; - uint64 amount = 7; - bytes payment_id = 9; -} - -message TransactionEventResponse { - TransactionEvent transaction = 1; -} - -message RegisterValidatorNodeRequest { - bytes validator_node_public_key = 1; - Signature validator_node_signature = 2; - uint64 fee_per_gram = 3; - bytes payment_id = 5; -} - -message RegisterValidatorNodeResponse { - uint64 transaction_id = 1; - bool is_success = 2; - string failure_message = 3; -} - -message ImportTransactionsRequest { - string txs = 1; -} - -message ImportTransactionsResponse { - repeated uint64 tx_ids = 1; -} - -message GetAllCompletedTransactionsRequest { - uint64 offset = 1; - uint64 limit = 2; - uint64 status_bitflag = 3; -} - -message GetAllCompletedTransactionsResponse { - repeated TransactionInfo transactions = 1; -} - -// Request message for getting transactions at a specific block height -message GetBlockHeightTransactionsRequest { - // The block height to fetch transactions for - uint64 block_height = 1; -} - -message GetBlockHeightTransactionsResponse { - // List of transactions mined at the specified block height - repeated TransactionInfo transactions = 1; -} - -// PayRef (Payment Reference) related messages and enums - -// Request message for GetTransactionPayRefs RPC. -message GetTransactionPayRefsRequest { - // The transaction ID to retrieve PayRefs for. - uint64 transaction_id = 1; -} - -// Response message for GetTransactionPayRefs RPC. -message GetTransactionPayRefsResponse { - // List of PayRefs (32-byte payment references) for the transaction. - repeated bytes payment_references = 1; -} - - -// Response message for GetTransactionsWithPayRefs RPC. -message GetTransactionsWithPayRefsResponse { - // The transaction information. - TransactionInfo transaction = 1; - // List of PayRefs associated with this transaction. - repeated bytes payment_references = 2; - // Number of unique recipients for this transaction. - uint64 recipient_count = 3; -} - -// Request message for getting payment details by payment reference -message GetPaymentByReferenceRequest { - // The 32-byte payment reference hash to look up - bytes payment_reference = 1; -} - -// Response message containing transaction information for a payment reference -message GetPaymentByReferenceResponse { - // The transaction information if PayRef is found (optional). - // Returns full transaction details - TransactionInfo transaction = 1; -} - - -// Enum for payment direction -enum PaymentDirection { - // Unknown or unspecified direction - PAYMENT_DIRECTION_UNKNOWN = 0; - // Payment received by this wallet - PAYMENT_DIRECTION_INBOUND = 1; - // Payment sent from this wallet - PAYMENT_DIRECTION_OUTBOUND = 2; -} diff --git a/internal/gbt/tari/sha3x/sha3x.go b/internal/gbt/tari/sha3x/sha3x.go deleted file mode 100644 index 836ed08..0000000 --- a/internal/gbt/tari/sha3x/sha3x.go +++ /dev/null @@ -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 -} diff --git a/internal/gbt/tari/tari.go b/internal/gbt/tari/tari.go deleted file mode 100644 index dfb3206..0000000 --- a/internal/gbt/tari/tari.go +++ /dev/null @@ -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 -} diff --git a/internal/msg/msg.go b/internal/msg/msg.go index 119ba09..6089f2e 100644 --- a/internal/msg/msg.go +++ b/internal/msg/msg.go @@ -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"`