commit 953a76439a077292746dc73afd919626edd1d3f1 Author: lzx <393768033@qq.com> Date: Wed Sep 3 16:00:42 2025 +0800 create git diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..48f5dfb --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +rel +config +*.json +*.conf +/*.go \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..6b1e8f4 --- /dev/null +++ b/README.md @@ -0,0 +1,146 @@ +# tari-server + +一个基于 Go 的轻量化挖矿池服务内核,包含 Job 生成/分发与 Stratum 矿工端接入两大模块: +- gbt:区块模板生成与同步(GetBlockTemplate/Job Producer),通过 ZMQ 向服务端发布新任务 +- server:Stratum 挖矿服务(矿工接入、难度调整、提交校验、统计与缓存) + +当前代码启用了 `sha3x` 币种实现(其他如 `nexa`、`monero` 的代码结构已准备但默认关闭/注释)。 + +--- + +## 功能特性 +- Stratum 协议接入,支持 `mining.subscribe`、`mining.authorize`/`login`、`mining.submit`、`mining.ping/pong` +- 可配置的难度策略(含卡尔曼滤波驱动的 VarDiff 逻辑,按提交间隔动态调整) +- 任务分发与同步:gbt 通过 ZMQ 发布,server 订阅并向在线矿工广播 +- 连接数/同 IP 限流、存活监测、超时与心跳处理 +- Redis 用于在线状态与速率缓存,DB 持久化矿工/用户/池端统计 +- 日志:zap + 日志轮转 +- 内置 pprof 端口(从配置读取) + +--- + +## 目录结构 +``` +cmd/ + gbt/gbt.go # 区块模板生成/任务发布入口 + server/server.go # 挖矿池服务入口(Stratum 服务) +internal/ + server/ # 矿工接入、会话、难度、任务处理 + gbt/ # GBT/任务管线,各币种对接 + db/ # 数据库上下文与表结构 + cache/ # Redis 缓存读写 + stratum/ # Stratum 协议与消息结构 + utility/ # 工具、日志、ZMQ 初始化等 +config/ + nexa/ + server/server.conf # server 示例配置(按需拷贝/修改) + gbt/gbt.conf # gbt 示例配置(按需拷贝/修改) + db/db.conf # DB 配置(MySQL/SQLite) +``` + +--- + +## 环境依赖 +- Go 1.23+(go.mod 声明 `toolchain go1.23.1`) +- Redis(作为状态/速率缓存) +- 数据库:MySQL 或 SQLite(按 `config//db/db.conf` 配置) +- ZMQ(用于 gbt → server 的 Job 发布/订阅) +- 可选本地 C 库:目录 `internal/server/lib/` 下包含部分 `.so`/`.a`,用于特定算法;`sha3x` 默认主要为 Go 实现。建议在 Linux 环境下构建、运行;Windows 可能需要适配或禁用相关 C 扩展。 + +--- + +## 快速开始 +1) 准备配置文件(以 `sha3x` 为例) +- 将以下文件拷贝到运行目录(项目根或二进制同目录): + - `config/nexa/server/server.conf` → `server.conf` + - `config/nexa/gbt/gbt.conf` → `gbt.conf` + - `config/nexa/db/db.conf` → `db.conf` +- 打开并修改以上配置以匹配你的 Redis、DB、ZMQ 与监听地址。例如:`server.conf` 中的 Stratum 监听端口、pprof 端口,`gbt.conf` 中的上游节点与发布地址。 + +2) 构建 +``` +# 在项目根目录执行 +go build -o bin/server ./cmd/server +go build -o bin/gbt ./cmd/gbt +``` + +3) 运行 +``` +# 先启动 gbt(负责产生并发布 Job) +./bin/gbt + +# 再启动 server(负责矿工接入与提交校验) +./bin/server +``` +- 两个进程均会在工作目录读取同名配置:`gbt` 读取 `gbt.conf`,`server` 读取 `server.conf`。 +- `server` 会根据配置启动一个 pprof HTTP 端口,便于性能分析。 + +4) 矿工连接 +- 在矿工端配置你的 Stratum 地址,即 `server.conf` 中的 `Host.Listen`(例如:`stratum+tcp://:`)。 +- 账户名与 Miner 名按池的约定填写,对应鉴权在 `internal/stratum` 与 `internal/server/coin/*` 中处理。 + +--- + +## 配置说明(概览) +- server.conf(读取于工作目录) + - Host.Listen:Stratum 监听地址,形如 `0.0.0.0:端口` + - Redis:`Addr/Password/DB` + - ZMQ:`Pub`(向外发布)、`Sub`(订阅 gbt 发布的 Job) + - Diff:难度相关参数(起始、最小/最大、调整间隔、滤波模式等) + - Zaplog/Logrotate:日志级别、输出与轮转策略 + - pprof 端口:由 `cmd/server` 中 `utility.GetCoin("server.conf")` 返回的第二个值决定 +- gbt.conf(读取于工作目录) + - 上游节点/RPC 或 gRPC/GRPC/Tari/Monero 等对接参数 + - ZMQ:对外发布 Job 的地址(需与 server 的 `Zmq.Sub` 对应) +- db.conf + - MySQL 或 SQLite 连接信息(`internal/db` 负责加载与建表) + +注意:项目内示例配置位于 `config/nexa/...`,请根据目标币种复制调整;`sha3x` 仅需要确保 ZMQ/Redis/DB 与监听端口正常。 + +--- + +## 运行时行为要点 +- gbt → server:通过 ZMQ 发布/订阅通道传递新 Job,`server` 收到后同步标志并向矿工广播 +- 存活与心跳:`server` 为连接设置超时、心跳(ping/pong),并清理无效连接 +- 动态难度:根据提交间隔、方差与配置策略更新矿工难度 +- 速率与统计:接受/拒绝、哈希率、区块、孤块等统计通过内存与 Redis/DB 维护 +- 退出流程:`Stop()` 会清理连接、关闭 ZMQ、Redis、日志并回收内存结构 + +--- + +## 常见问题 +- 端口不通:确认 `server.conf` 中监听端口开放(防火墙/安全组),ZMQ 地址能互通 +- 配置找不到:`server` 与 `gbt` 均在工作目录读取 `*.conf`,请确保以正确的工作目录启动或将配置拷贝到同一目录 +- 构建失败(Windows):如遇 `.so/.a` 相关链接问题,建议在 Linux 构建或禁用/移除对应 C 扩展;`sha3x` 模块通常不依赖这些库 +- Redis/DB 未就绪:请先启动并配置正确连接串;否则启动会失败或无法持久化统计 + +--- + +## 开发与调试 +- 使用 pprof:根据 `server.conf` 暴露的地址访问 `http://:/debug/pprof/` +- 日志:默认使用 zap,按 `Zaplog` 与 `Logrotate` 配置输出与轮转 +- 关键位置: + - `internal/server/server.go`:连接处理、心跳、难度调整、Job 处理主流程 + - `internal/gbt/*`:各币种 GBT 接入与 Job 生成 + - `internal/stratum/*`:协议与消息体 + +--- + +## 构建与运行示例(Windows PowerShell) +``` +# 构建 +$env:CGO_ENABLED=0 +go build -o bin/server.exe ./cmd/server +go build -o bin/gbt.exe ./cmd/gbt + +# 运行前将 *.conf 复制到当前目录 +./bin/gbt.exe +./bin/server.exe +``` + +> 注:如需使用依赖本地 C 库的算法实现,建议在 Linux 环境构建并确保工具链与库依赖可用。 + +--- + +## 许可证 +本项目未在仓库根目录明确声明许可证。如需开源发布,请在根目录新增 LICENSE 并注明授权条款。 diff --git a/cmd/gbt/gbt.go b/cmd/gbt/gbt.go new file mode 100644 index 0000000..3d2a896 --- /dev/null +++ b/cmd/gbt/gbt.go @@ -0,0 +1,33 @@ +// gbt.go +package main + +import ( + "os" + "pool/internal/db" + "pool/internal/gbt" + "pool/internal/utility" +) + +func start(coin string, DbCtx *db.DbContext) { + + gbt.Start(coin, DbCtx) + +} + +func stop(coin string) { + + gbt.Stop(coin) + +} + +func main() { + coin, _ := utility.GetCoin("gbt.conf") + dbctx := db.InitDb(coin, "gbt") + start(coin, dbctx) + + stop(coin) + + db.StopDb(coin, "gbt") + + os.Exit(0) +} diff --git a/cmd/server/server.go b/cmd/server/server.go new file mode 100644 index 0000000..94b66d7 --- /dev/null +++ b/cmd/server/server.go @@ -0,0 +1,41 @@ +// server.go +package main + +import ( + "os" + "pool/internal/db" + "pool/internal/server" + + "log" + "net/http" + _ "net/http/pprof" + "pool/internal/utility" +) + +func start(coin string, DbCtx *db.DbContext) { + server.Start(coin, DbCtx) +} + +func stop() { + server.Stop() +} + +func main() { + + coin, pp := utility.GetCoin("server.conf") + + go func() { + //log.Println(http.ListenAndServe("localhost:6060", nil)) + log.Println(http.ListenAndServe(pp, nil)) + }() + + dbctx := db.InitDb(coin, "server") + + start(coin, dbctx) + + stop() + + db.StopDb(coin, "server") + + os.Exit(0) +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..df01694 --- /dev/null +++ b/go.mod @@ -0,0 +1,46 @@ +module pool + +go 1.23.0 + +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 +) + +require ( + filippo.io/edwards25519 v1.1.0 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.1.3 // indirect + github.com/btcsuite/btcd/btcutil v1.1.5 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 // indirect + github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f // indirect + github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd // indirect + github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/decred/dcrd/chaincfg/chainhash v1.0.4 + github.com/decred/dcrd/crypto/blake256 v1.0.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/go-sql-driver/mysql v1.8.1 + github.com/google/uuid v1.6.0 + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-sqlite3 v1.14.22 + github.com/redis/go-redis/v9 v9.5.4 + github.com/rs/zerolog v1.33.0 + go.uber.org/multierr v1.10.0 // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/sys v0.33.0 + google.golang.org/grpc v1.75.0 + gopkg.in/natefinch/lumberjack.v2 v2.2.1 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d76f6d1 --- /dev/null +++ b/go.sum @@ -0,0 +1,194 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= +github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs= +github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c= +github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA= +github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.23.5-0.20231215221805-96c9fd8078fd/go.mod h1:nm3Bko6zh6bWP60UxwoT5LzdGJsQJaPo6HjduXq9p6A= +github.com/btcsuite/btcd v0.24.2 h1:aLmxPguqxza+4ag8R1I2nnJjSu2iFn/kqtHTIImswcY= +github.com/btcsuite/btcd v0.24.2/go.mod h1:5C8ChTkl5ejr3WHj8tkQSCmydiMEPB0ZhQhehpq7Dgg= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcec/v2 v2.1.3 h1:xM/n3yIhHAhHy04z4i43C8p4ehixJZMsnrVJkgl+MTE= +github.com/btcsuite/btcd/btcec/v2 v2.1.3/go.mod h1:ctjw4H1kknNJmRN4iP1R7bTQ+v3GJkZBd6mui8ZsAZE= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= +github.com/btcsuite/btcd/btcutil v1.1.5 h1:+wER79R5670vs/ZusMTF1yTcRYE5GUsFbdjdisflzM8= +github.com/btcsuite/btcd/btcutil v1.1.5/go.mod h1:PSZZ4UitpLBWzxGd5VGOrLnmOjtPP/a6HaFo12zMs00= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0 h1:59Kx4K6lzOW5w6nFlA0v5+lk/6sjybR934QNHSJZPTQ= +github.com/btcsuite/btcd/chaincfg/chainhash v1.1.0/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/chaincfg/chainhash v1.0.4 h1:zRCv6tdncLfLTKYqu7hrXvs7hW+8FO/NvwoFvGsrluU= +github.com/decred/dcrd/chaincfg/chainhash v1.0.4/go.mod h1:hA86XxlBWwHivMvxzXTSD0ZCG/LoYsFdWnCekkTMCqY= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/crypto/blake256 v1.0.1 h1:7PltbUIQB7u/FfZ39+DGa/ShuMyJ5ilcvdfma9wOH6Y= +github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= +github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= +github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/redis/go-redis/v9 v9.5.4 h1:vOFYDKKVgrI5u++QvnMT7DksSMYg7Aw/Np4vLJLKLwY= +github.com/redis/go-redis/v9 v9.5.4/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= +github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= +github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= +github.com/zeromq/goczmq v4.1.0+incompatible h1:cGVQaU6kIwwrGso0Pgbl84tzAz/h7FJ3wYQjSonjFFc= +github.com/zeromq/goczmq v4.1.0+incompatible/go.mod h1:1uZybAJoSRCvZMH2rZxEwWBSmC4T7CB/xQOfChwPEzg= +go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= +go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= +go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= +go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ= +go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= +go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= +google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= +google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/cache/cache.go b/internal/cache/cache.go new file mode 100644 index 0000000..250fb9d --- /dev/null +++ b/internal/cache/cache.go @@ -0,0 +1,548 @@ +// cache.go +package cache + +import ( + "context" + "encoding/json" + "log" + "strconv" + "time" + + "github.com/redis/go-redis/v9" +) + +// reference, do not delete that +/*type CacheServer struct { + Submits int64 `json:"submits"` + Blocks int64 `json:"blocks"` + + Accepts float64 `json:"accepts"` + Rejects int64 `json:"rejects"` + Shares int64 `json:"shares"` + + Rewards float64 `json:"reward"` + Fees float64 `json:"fee"` + + RefDiff float64 `json:"refdiff"` + + //LastSubmit int64 `json:"lastsubmit"` +} + +type CacheUser struct { + Submits int64 `json:"submits"` + Blocks int64 `json:"blocks"` + + Accepts float64 `json:"accepts"` + Rejects int64 `json:"rejects"` + Shares int64 `json:"shares"` + + Rewards float64 `json:"reward"` + Fees float64 `json:"fee"` + + User string `json:"user"` +} + +type CacheMhs struct { + User string `json:"user"` + Miner string `json:"miner"` + Index string `json:"index"` + + Accepts []CacheMhsItem `json:"accepts"` + Rejects []CacheMhsItem `json:"rejects"` + + StartDayTime string `json:"startday"` +} + +type CacheMiner struct { + Submits int64 `json:"submits"` + Blocks int64 `json:"blocks"` + + Accepts float64 `json:"accepts"` + Rejects int64 `json:"rejects"` + Shares int64 `json:"shares"` + + LastDiff float64 `json:"diff"` + + Rewards float64 `json:"reward"` + Fees float64 `json:"fee"` + + Retry int `json:"retry"` + + LastSubmit int64 `json:"lastsubmit"` + + User string `json:"user"` + Miner string `json:"miner"` + Index string `json:"index"` + + ErrStaleds int64 `json:"staleds"` + ErrLowDiffs int64 `json:"lowdiffs"` + ErrDuplicates int64 `json:"duplicates"` + ErrFormats int64 `json:"formats"` + ErrOthers int64 `json:"others"` +}*/ + +// need used +type CacheMhsItem struct { + Tt string `json:"Tt"` + Diff float64 `json:"diff"` +} + +/* +type CacheMinerItem struct { + User string `json:"user"` + Miner string `json:"miner"` + Index string `json:"index"` +}*/ + +func LoadIntCache(client *redis.Client, key_int string) int64 { + val, err := client.Get(context.Background(), key_int).Result() + if err != nil { + log.Printf("[LoadIntCache]Error retrieving data from Redis: %s, %v\n", key_int, err) + return 0 + } + val_int, err := strconv.ParseInt(val, 10, 64) + if err != nil { + log.Printf("[LoadIntCache]Error parsing integer from string: %v\n", err) + return 0 + } + return val_int +} + +func StoreIntCache(client *redis.Client, key string, intNumber int64) bool { + numberStr := strconv.FormatInt(intNumber, 10) + expiration := 1 * 24 * time.Hour + err := client.Set(context.Background(), key, numberStr, expiration).Err() + if err != nil { + log.Printf("[StoreIntCache]Error storing data in Redis: %s, %v\n", key, err) + return false + } + return true +} + +func LoadFloatCache(client *redis.Client, key_float string) float64 { + val, err := client.Get(context.Background(), key_float).Result() + if err != nil { + log.Printf("[LoadFloatCache]Error retrieving data from Redis: %s, %v\n", key_float, err) + return 0 + } + val_f, err := strconv.ParseFloat(val, 64) + if err != nil { + log.Printf("[LoadFloatCache]Error parsing float from string: %v\n", err) + return 0 + } + return val_f +} + +func StoreFloatCache(client *redis.Client, key string, floatNumber float64) bool { + numberStr := strconv.FormatFloat(floatNumber, 'f', -1, 64) + expiration := 1 * 24 * time.Hour + err := client.Set(context.Background(), key, numberStr, expiration).Err() + if err != nil { + log.Printf("[StoreFloatCache]Error storing data in Redis: %s, %v\n", key, err) + return false + } + return true +} + +func LoadStringCache(client *redis.Client, keyStr string) string { + val, err := client.Get(context.Background(), keyStr).Result() + if err != nil { + log.Printf("[LoadStringCache]Error retrieving data from Redis: %s, %v\n", keyStr, err) + return "" + } + return val +} + +func StoreStringCache(client *redis.Client, key string, strValue string) bool { + expiration := 1 * 24 * time.Hour + err := client.Set(context.Background(), key, strValue, expiration).Err() + if err != nil { + log.Printf("[StoreStringCache]Error storing data in Redis: %s, %v\n", key, err) + return false + } + return true +} + +func LoadTimeCache(client *redis.Client, keyTime string) (time.Time, bool) { + val, err := client.Get(context.Background(), keyTime).Result() + if err != nil { + log.Printf("[LoadTimeCache]Error retrieving data from Redis: %s, %v\n", keyTime, err) + return time.Time{}, false + } + + t, err := time.Parse(time.RFC3339, val) + if err != nil { + log.Printf("[LoadTimeCache]Error parsing time from string: %v\n", err) + return time.Time{}, false + } + + return t, true +} + +func StoreTimeCache(client *redis.Client, key string, timeValue time.Time) bool { + numberStr := timeValue.Format(time.RFC3339) + expiration := 1 * 24 * time.Hour + err := client.Set(context.Background(), key, numberStr, expiration).Err() + if err != nil { + log.Printf("[StoreTimeCache]Error storing data in Redis: %s, %v\n", key, err) + return false + } + return true +} + +func LoadPoolCache(client *redis.Client, coin string, pool_key string) interface{} { + k := "pool_" + coin + "_" + pool_key + switch pool_key { + case "submits", "blocks", "rejects": + return LoadIntCache(client, k) + case "accepts", "rewards", "fee", "refdiff": + return LoadFloatCache(client, k) + default: + log.Printf("[LoadPoolCache]Unknown pool_key: %s\n", pool_key) + return nil + } +} + +func StorePoolCache(client *redis.Client, coin string, pool_key string, val interface{}) bool { + k := "pool_" + coin + "_" + pool_key + + switch pool_key { + case "submits", "blocks", "rejects": + if pool_key == "rejects" { + if intVal, ok := val.(float64); ok { + return StoreIntCache(client, k, int64(intVal)) + } + } else { + if intVal, ok := val.(int64); ok { + return StoreIntCache(client, k, intVal) + } + } + log.Printf("[StorePoolCache]Invalid type for key %s: expected int64, got %T\n", pool_key, val) + return false + case "accepts", "rewards", "fee", "refdiff": + if floatVal, ok := val.(float64); ok { + return StoreFloatCache(client, k, floatVal) + } + log.Printf("[StorePoolCache]Invalid type for key %s: expected float64, got %T\n", pool_key, val) + return false + default: + log.Printf("[StorePoolCache]Unknown pool_key: %s\n", pool_key) + return false + } +} + +/* +func LoadUserCache(client *redis.Client, coin string, user string, pool_key string) interface{} { + k := "pool_" + coin + "_" + user + "_" + pool_key + switch pool_key { + case "submits", "blocks", "rejects": + return LoadIntCache(client, k) + case "accepts", "rewards", "fee": + return LoadFloatCache(client, k) + default: + log.Printf("Unknown pool_key: %s\n", pool_key) + return nil + } +} + +func StoreUserCache(client *redis.Client, coin string, user string, pool_key string, val interface{}) bool { + k := "pool_" + coin + "_" + user + "_" + pool_key + + switch pool_key { + case "submits", "blocks", "rejects": + if intVal, ok := val.(int64); ok { + return StoreIntCache(client, k, intVal) + } + log.Printf("Invalid type for key %s: expected int64, got %T\n", pool_key, val) + return false + case "accepts", "rewards", "fee": + if floatVal, ok := val.(float64); ok { + return StoreFloatCache(client, k, floatVal) + } + log.Printf("Invalid type for key %s: expected float64, got %T\n", pool_key, val) + return false + default: + log.Printf("Unknown pool_key: %s\n", pool_key) + return false + } +}*/ + +func LoadMinerCache(client *redis.Client, coin string, user string, miner string, index string, pool_key string) interface{} { + k := "pool_" + coin + "_" + user + "_" + miner + "_" + index + "_" + pool_key + switch pool_key { + case "submits", "blocks", "rejects", "retry", "staleds", "lowdiffs", "duplicates", "formats", "others": + return LoadIntCache(client, k) + case "accepts", "rewards", "fee", "diff": + return LoadFloatCache(client, k) + case "lastsubmit", "startsubmit": + tT, ok := LoadTimeCache(client, k) + if ok { + return tT + } + return nil + default: + log.Printf("[LoadMinerCache]Unknown pool_key: %s\n", pool_key) + return nil + } +} + +func StoreMinerCache(client *redis.Client, coin string, user string, miner string, index string, pool_key string, val interface{}) bool { + k := "pool_" + coin + "_" + user + "_" + miner + "_" + index + "_" + pool_key + + switch pool_key { + case "submits", "blocks", "rejects", "retry", "staleds", "lowdiffs", "duplicates", "formats", "others": + if intVal, ok := val.(int64); ok { + return StoreIntCache(client, k, intVal) + } + log.Printf("[StoreMinerCache]Invalid type for %s: expected int64, got %T\n", pool_key, val) + return false + + case "accepts", "rewards", "fee", "diff": + if floatVal, ok := val.(float64); ok { + return StoreFloatCache(client, k, floatVal) + } + log.Printf("[StoreMinerCache]Invalid type for %s: expected float64, got %T\n", pool_key, val) + return false + + case "lastsubmit", "startsubmit": + if timeVal, ok := val.(time.Time); ok { + return StoreTimeCache(client, k, timeVal) + } + log.Printf("[StoreMinerCache]Invalid type for %s: expected time.Time, got %T\n", pool_key, val) + return false + + default: + log.Printf("[StoreMinerCache]Unknown pool_key: %s\n", pool_key) + return false + } +} + +func StoreCacheMhsItem(client *redis.Client, key string, item CacheMhsItem) bool { + data, err := json.Marshal(item) + if err != nil { + log.Printf("[StoreCacheMhsItem]Error marshalling CacheMhsItem to JSON: %v\n", err) + return false + } + + err = client.RPush(context.Background(), key, data).Err() + if err != nil { + log.Printf("[StoreCacheMhsItem]Error pushing data to Redis list: %v\n", err) + return false + } + + expiration := 1 * 24 * time.Hour + err = client.Expire(context.Background(), key, expiration).Err() + if err != nil { + log.Printf("[StoreCacheMhsItem] Error setting expiration for Redis key: %v\n", err) + return false + } + + return true +} + +func PopCacheMhsItem(client *redis.Client, key string) (*CacheMhsItem, bool) { + data, err := client.LPop(context.Background(), key).Result() + if err != nil { + log.Printf("[PopCacheMhsItem]Error retrieving data from Redis list: %v\n", err) + return nil, false + } + + var item CacheMhsItem + if err = json.Unmarshal([]byte(data), &item); err != nil { + log.Printf("[PopCacheMhsItem]Error unmarshalling JSON to CacheMhsItem: %v\n", err) + return nil, false + } + + return &item, true +} + +func RemoveMhsCache(client *redis.Client, coin string, user string, miner string, index string, key string) bool { + k := "mhs_" + coin + "_" + user + "_" + miner + "_" + index + "_" + key + switch key { + case "accepts", "rejects": + PopCacheMhsItem(client, k) + return true + } + return false +} + +func LoadMhsCache(client *redis.Client, coin string, user string, miner string, index string, key string) interface{} { + k := "mhs_" + coin + "_" + user + "_" + miner + "_" + index + "_" + key + switch key { + case "starttime": + tT, ok := LoadTimeCache(client, k) + if ok { + return tT + } + return nil + case "accepts", "rejects": + /*listLength, err := client.LLen(context.Background(), k).Result() + if err != nil { + log.Printf("Error getting list length: %v\n", err) + return nil + }*/ + values, err := client.LRange(context.Background(), k, 0, -1).Result() + if err != nil { + log.Printf("[LoadMhsCache]Error getting list values: %v\n", err) + } + var items []CacheMhsItem + for _, value := range values { + var item CacheMhsItem + if err = json.Unmarshal([]byte(value), &item); err != nil { + continue + } + temp_time, _ := time.Parse(time.RFC3339, item.Tt) + if temp_time.After(time.Now().Add(-24 * time.Hour)) { + items = append(items, item) + } + } + return &items + default: + return nil + } +} + +func StoreMhsCache(client *redis.Client, coin string, user string, miner string, index string, key string, val interface{}) bool { + k := "mhs_" + coin + "_" + user + "_" + miner + "_" + index + "_" + key + switch key { + case "starttime": + if t, ok := val.(time.Time); ok { + return StoreTimeCache(client, k, t) + } + log.Printf("[StoreMhsCache]Invalid type for starttime: expected time.Time, got %T\n", val) + return false + case "accepts", "rejects": + if item, ok := val.(CacheMhsItem); ok { + return StoreCacheMhsItem(client, k, item) + } + log.Printf("[StoreMhsCache]Invalid type for CacheMhsItem: expected CacheMhsItem, got %T\n", val) + return false + default: + log.Printf("[StoreMhsCache]Unknown key: %s\n", key) + return false + } +} + +/* +func StoreStringToSet(client *redis.Client, setKey string, value string) bool { + err := client.SAdd(context.Background(), setKey, value).Err() + if err != nil { + log.Printf("Error adding value to Redis set: %v\n", err) + return false + } + return true +} + +func LoadStringsFromSet(client *redis.Client, setKey string) ([]string, bool) { + members, err := client.SMembers(context.Background(), setKey).Result() + if err != nil { + log.Printf("Error retrieving data from Redis set: %v\n", err) + return nil, false + } + return members, true +} + +func RemoveStringFromSet(client *redis.Client, setKey string, value string) bool { + err := client.SRem(context.Background(), setKey, value).Err() + if err != nil { + log.Printf("Error removing value from Redis set: %v\n", err) + return false + } + return true +} + +func LoadUsersCache(client *redis.Client, coin string) []string { + k := "pool_" + coin + "_users" + users, ok := LoadStringsFromSet(client, k) + if !ok { + log.Printf("Error loading users slice from Redis for coin: %s\n", coin) + return []string{} + } + return users +} + +func StoreUsersCache(client *redis.Client, coin string, user string) bool { + k := "pool_" + coin + "_users" + ok := StoreStringToSet(client, k, user) + if !ok { + log.Printf("Error storing users slice to Redis for coin: %s\n", coin) + return false + } + return true +} +*/ +/* +func StoreCacheMinerItem(client *redis.Client, setKey string, item CacheMinerItem) bool { + data, err := json.Marshal(item) + if err != nil { + log.Printf("Error marshalling CacheMinerItem to JSON: %v\n", err) + return false + } + + err = client.SAdd(context.Background(), setKey, data).Err() + if err != nil { + log.Printf("Error adding data to Redis set: %v\n", err) + return false + } + + return true +} + +func LoadCacheMinerItems(client *redis.Client, setKey string) ([]CacheMinerItem, bool) { + data, err := client.SMembers(context.Background(), setKey).Result() + if err != nil { + log.Printf("Error retrieving data from Redis set: %v\n", err) + return nil, false + } + + var items []CacheMinerItem + for _, itemData := range data { + var item CacheMinerItem + err := json.Unmarshal([]byte(itemData), &item) + if err != nil { + log.Printf("Error unmarshalling JSON to CacheMinerItem: %v\n", err) + return nil, false + } + items = append(items, item) + } + + return items, true +} + +func RemoveCacheMinerItem(client *redis.Client, setKey string, item CacheMinerItem) bool { + + data, err := json.Marshal(item) + if err != nil { + log.Printf("Error marshalling CacheMinerItem to JSON: %v\n", err) + return false + } + + err = client.SRem(context.Background(), setKey, data).Err() + if err != nil { + log.Printf("Error removing data from Redis set: %v\n", err) + return false + } + + return true +} + +func LoadMinersCache(client *redis.Client, coin string) []CacheMinerItem { + k := "pool_" + coin + "_miners" + miners, ok := LoadCacheMinerItems(client, k) + if !ok { + log.Printf("Error loading miners set from Redis for coin: %s\n", coin) + return []CacheMinerItem{} + } + return miners +} + +func StoreMinersCache(client *redis.Client, coin string, miner CacheMinerItem) bool { + k := "pool_" + coin + "_miners" + ok := StoreCacheMinerItem(client, k, miner) + if !ok { + log.Printf("Error storing miners slice to Redis for coin: %s\n", coin) + return false + } + return true +} +*/ diff --git a/internal/db/db.go b/internal/db/db.go new file mode 100644 index 0000000..c91bceb --- /dev/null +++ b/internal/db/db.go @@ -0,0 +1,2996 @@ +// db.go +package db + +import ( + "database/sql" + "encoding/json" + "fmt" + + "log" + "strings" + + "strconv" + "time" + + "bytes" + "crypto/tls" + + "io/ioutil" + "net/http" + + "crypto/md5" + "encoding/hex" + + "pool/internal/utility" + + _ "github.com/go-sql-driver/mysql" + "go.uber.org/zap" + "gopkg.in/natefinch/lumberjack.v2" +) + +const DB_VERSION string = "v2.0a" + +var dbconnstr string +var sharesdbconnstr string + +type DbConfigInfo struct { + Ip string `json:"ip"` + Port int `json:"port"` + Username string `json:"username"` + Password string `json:"password"` + Dbname string `json:"dbname"` +} + +type DbConfig struct { + Zaplog zap.Config `json:"zap"` + Db DbConfigInfo `json:"db"` + Shares DbConfigInfo `json:"shares"` + Logrotae utility.LogRotateConfig `json:"logrotate"` +} + +type Config_db_info struct { + DbHostIp string + DbHostPort int + DbUserName string + DbPassWord string + DbName string +} + +type PoolDb struct { + *sql.DB + Logg *zap.Logger +} + +type DbContext struct { + DbExit bool + AppExit chan bool + + Db_obj *PoolDb + Shares_obj *PoolDb + + DbCfg DbConfig + Coin string + Module string + + LastMinersTime time.Time + LastMinersStatsTime time.Time + /*LastMinerTime time.Time + LastUsersTime time.Time + LastUsersStatsTime time.Time + LastUsersBlkStatsTime time.Time + LastPoolTime time.Time + LastPoolStatsTime time.Time*/ + LastPoolBlkStatsTime time.Time + LastBlockDetailHeight int64 + LastBlockNewTime time.Time + LastAddressTime time.Time + + Miners_ch chan []Miners_db_msg + MinersStats_ch chan []MinersStats_db_msg + /*Miner_ch chan Miner_db_msg + Users_ch chan Users_db_msg + UsersStats_ch chan UsersStats_db_msg + UsersBlkStats_ch chan UsersBlkStats_db_msg + Pool_ch chan Pool_db_msg + PoolStats_ch chan PoolStats_db_msg*/ + PoolBlkStats_ch chan PoolBlkStats_db_msg + BlkDetail_ch chan BlkDetail_db_msg + BlkNew_ch chan BlkNew_db_msg + Address_ch chan Address_db_msg + + LogR *lumberjack.Logger +} + +type Miners_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + Fromip string + State string + Online time.Time + Offline time.Time + Retry int + Duration float64 + Protocol string + User string + Miner string + Index string + Diff float64 + Height uint32 + Accepts float64 + Rejects float64 + Ratio float64 + Staleds float64 + Lows float64 + Duplicates float64 + Formats float64 + Others float64 + Disabled bool + Last_submit time.Time + Submits int + Blocks int + Orphans int + Orphan_ratio float64 +} + +type MinersStats_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + User string + Miner string + Index string + + Shares5m float64 + Shares15m float64 + Shares30m float64 + Shares1h float64 + Shares3h float64 + Shares6h float64 + Shares12h float64 + Shares24h float64 + Shares48h float64 + + Rejects5m float64 + Rejects15m float64 + Rejects30m float64 + Rejects1h float64 + Rejects3h float64 + Rejects6h float64 + Rejects12h float64 + Rejects24h float64 + Rejects48h float64 + + Mhs5m float64 + Mhs15m float64 + Mhs30m float64 + Mhs1h float64 + Mhs3h float64 + Mhs6h float64 + Mhs12h float64 + Mhs24h float64 + Mhs48h float64 + + Ratio5m float64 + Ratio15m float64 + Ratio30m float64 + Ratio1h float64 + Ratio3h float64 + Ratio6h float64 + Ratio12h float64 + Ratio24h float64 + Ratio48h float64 +} + +/* +type Miner_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + User string + Miner string + Index string + + Target string + Submit_target string + Height int64 + Success int + Pow string + Net_target string + Submit string + Hash string + Header string + Accepts float64 + Total_accepts float64 + Rejects float64 + Total_rejects float64 + Reward float64 + Fee float64 + Nonce string + SubIdx int64 +}*/ +/* +type Users_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + User string + Normal int64 + Abnormal int64 + + Offline int64 + MhsZero int64 + MhsLow int64 + HighRejects int64 + Unstable int64 + + Submits int64 + Blocks int64 + Orphans int64 + Orphan_ratio float64 + Reward float64 + Fee float64 +}*/ + +/*type UsersStats_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + User string + + Shares5m float64 + Shares15m float64 + Shares30m float64 + Shares1h float64 + Shares3h float64 + Shares6h float64 + Shares12h float64 + Shares24h float64 + Shares48h float64 + + Rejects5m float64 + Rejects15m float64 + Rejects30m float64 + Rejects1h float64 + Rejects3h float64 + Rejects6h float64 + Rejects12h float64 + Rejects24h float64 + Rejects48h float64 + + Mhs5m float64 + Mhs15m float64 + Mhs30m float64 + Mhs1h float64 + Mhs3h float64 + Mhs6h float64 + Mhs12h float64 + Mhs24h float64 + Mhs48h float64 + + Ratio5m float64 + Ratio15m float64 + Ratio30m float64 + Ratio1h float64 + Ratio3h float64 + Ratio6h float64 + Ratio12h float64 + Ratio24h float64 + Ratio48h float64 +}*/ + +/*type UsersBlkStats_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + User string + Miner string + Index string + + Height int64 + Hash string + Pow string + Net_target string + Submit string + Success int + Accepts float64 + Rejects float64 + Reward float64 + Fee float64 + Nonce string + SubIdx int64 +}*/ + +/*type Pool_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + Miners int64 + Normal int64 + Abnormal int64 + + Offline int64 + MhsZero int64 + MhsLow int64 + HighRejects int64 + Unstable int64 + + Net_target string + Height uint64 + Submits int64 + Blocks int64 + Orphans int64 + Orphan_ratio float64 + Reward float64 + Fee float64 +}*/ + +/*type PoolStats_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + Shares5m float64 + Shares15m float64 + Shares30m float64 + Shares1h float64 + Shares3h float64 + Shares6h float64 + Shares12h float64 + Shares24h float64 + Shares48h float64 + + Rejects5m float64 + Rejects15m float64 + Rejects30m float64 + Rejects1h float64 + Rejects3h float64 + Rejects6h float64 + Rejects12h float64 + Rejects24h float64 + Rejects48h float64 + + Mhs5m float64 + Mhs15m float64 + Mhs30m float64 + Mhs1h float64 + Mhs3h float64 + Mhs6h float64 + Mhs12h float64 + Mhs24h float64 + Mhs48h float64 + + Ratio5m float64 + Ratio15m float64 + Ratio30m float64 + Ratio1h float64 + Ratio3h float64 + Ratio6h float64 + Ratio12h float64 + Ratio24h float64 + Ratio48h float64 +}*/ + +type PoolBlkStats_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + Height int64 + Hash string + Pow string + Net_target string + Submit string + Success int + Accepts float64 + Rejects float64 + Reward float64 + Fee float64 + Nonce string + SubIdx int64 +} + +type BlkHeightDetail_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + From int64 + To int64 +} + +type BlkDetail_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + Height int64 + Hash string + User string + Miner string + Index string + Success int + Miner_diff float64 + Pool_diff float64 + Nonce string + SubIdx int64 +} + +type BlkNew_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + Height int64 + Hash string + Success int + Nonce string + SubIdx int64 +} + +type Address_db_msg struct { + Id int + Msg string + MinerType string + Date time.Time + + Addr string + Sum string + Valid bool +} + +var DbCtx DbContext + +func InitConfig(dbconfig *DbConfig) { + data, err := ioutil.ReadFile("db.conf") + if err != nil { + panic(err.Error()) + } + if err = json.Unmarshal(data, &dbconfig); err != nil { + panic(err.Error()) + } +} + +func OpenPoolDb(dbtype string, dbsql string) (*PoolDb, error) { + db, err := sql.Open(dbtype, dbsql) + if err != nil { + return nil, err + } + pooldb := &PoolDb{DB: db} + return pooldb, nil +} + +func (this *PoolDb) ClosePoolDb() error { + err := this.Close() + if err != nil { + return err + } + return err +} + +func (this *PoolDb) QueryPoolDb(query string, args ...interface{}) (*sql.Rows, error) { + result, err := this.DB.Query(query, args...) + if err != nil { + this.Logg.Error("[db]", zap.String("query db err", err.Error())) + return nil, err + } + return result, nil +} + +/* +func (this *PoolDb) InsertPoolDb2(table string, coinType string, table_name string, result interface{}) error { + //log.Println(table_name) + switch table { + case "miner": + var msg Miner_db_msg = result.(Miner_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,user,miner,`refindex`,target,submit_target,height,`success`,pow,net_target,submit,hash,header,accepts,total_accepts,rejects,total_rejects,reward,fee,nonce,subidx) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miner,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.User, msg.Miner, msg.Index, msg.Target, msg.Submit_target, msg.Height, msg.Success, msg.Pow, msg.Net_target, msg.Submit, msg.Hash, msg.Header, msg.Accepts, msg.Total_accepts, msg.Rejects, msg.Total_rejects, msg.Reward, msg.Fee, msg.Nonce, msg.SubIdx) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miner,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert miner table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + default: + this.Logg.Error("[db]", zap.String("inser table unkown table", table)) + break + } + return nil +}*/ + +func (this *PoolDb) InsertPoolDb(table string, coinType string, result interface{}) error { + var table_name string = coinType + "_" + table + switch table { + case "miners": + var msg Miners_db_msg = result.(Miners_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,fromip,state,online,offline,retry,duration,protocol,user,miner,`refindex`,diff,height,accepts,rejects,ratio,staleds,lows,duplicates,formats,others,is_disabled,last_submit,submits,blocks,orphans,orphan_ratio) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miners,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.Fromip, msg.State, msg.Online, msg.Offline, msg.Retry, msg.Duration, msg.Protocol, msg.User, msg.Miner, msg.Index, msg.Diff, msg.Height, msg.Accepts, msg.Rejects, msg.Ratio, msg.Staleds, msg.Lows, msg.Duplicates, msg.Formats, msg.Others, msg.Disabled, msg.Last_submit, msg.Submits, msg.Blocks, msg.Orphans, msg.Orphan_ratio) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miners,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert miners table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "miners_stats": + var msg MinersStats_db_msg = result.(MinersStats_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,user,miner,`refindex`,shares5m,shares15m,shares30m,shares1h,shares3h,shares6h,shares12h,shares24h,shares48h,rejects5m,rejects15m,rejects30m,rejects1h,rejects3h,rejects6h,rejects12h,rejects24h,rejects48h,mhs5m,mhs15m,mhs30m,mhs1h,mhs3h,mhs6h,mhs12h,mhs24h,mhs48h,ratio5m,ratio15m,ratio30m,ratio1h,ratio3h,ratio6h,ratio12h,ratio24h,ratio48h) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miners_stats,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.User, msg.Miner, msg.Index, msg.Shares5m, msg.Shares15m, msg.Shares30m, msg.Shares1h, msg.Shares3h, msg.Shares6h, msg.Shares12h, msg.Shares24h, msg.Shares48h, msg.Rejects5m, msg.Rejects15m, msg.Rejects30m, msg.Rejects1h, msg.Rejects3h, msg.Rejects6h, msg.Rejects12h, msg.Rejects24h, msg.Rejects48h, msg.Mhs5m, msg.Mhs15m, msg.Mhs30m, msg.Mhs1h, msg.Mhs3h, msg.Mhs6h, msg.Mhs12h, msg.Mhs24h, msg.Mhs48h, msg.Ratio5m, msg.Ratio15m, msg.Ratio30m, msg.Ratio1h, msg.Ratio3h, msg.Ratio6h, msg.Ratio12h, msg.Ratio24h, msg.Ratio48h) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miners_stats,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert miners stats table sucess,miner type", coinType), zap.String("sql", insert_sql)) + + break + /*case "miner": + var msg Miner_db_msg = result.(Miner_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,user,miner,`refindex`,target,submit_target,height,`success`,pow,net_target,submit,hash,header,accepts,total_accepts,rejects,total_rejects,reward,fee,nonce,subidx) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miner,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.User, msg.Miner, msg.Index, msg.Target, msg.Submit_target, msg.Height, msg.Success, msg.Pow, msg.Net_target, msg.Submit, msg.Hash, msg.Header, msg.Accepts, msg.Total_accepts, msg.Rejects, msg.Total_rejects, msg.Reward, msg.Fee, msg.Nonce, msg.SubIdx) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_miner,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert miner table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "users": + var msg Users_db_msg = result.(Users_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,user,normal,abnormal,offline,mhszero,mhslow,highreject,unstable,submits,blocks,orphans,orphan_ratio,reward,fee) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_users,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.User, msg.Normal, msg.Abnormal, msg.Offline, msg.MhsZero, msg.MhsLow, msg.HighRejects, msg.Unstable, msg.Submits, msg.Blocks, msg.Orphans, msg.Orphan_ratio, msg.Reward, msg.Fee) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_users,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert users table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "users_stats": + var msg UsersStats_db_msg = result.(UsersStats_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,user,shares5m,shares15m,shares30m,shares1h,shares3h,shares6h,shares12h,shares24h,shares48h,rejects5m,rejects15m,rejects30m,rejects1h,rejects3h,rejects6h,rejects12h,rejects24h,rejects48h,mhs5m,mhs15m,mhs30m,mhs1h,mhs3h,mhs6h,mhs12h,mhs24h,mhs48h,ratio5m,ratio15m,ratio30m,ratio1h,ratio3h,ratio6h,ratio12h,ratio24h,ratio48h) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_users_stats,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.User, msg.Shares5m, msg.Shares15m, msg.Shares30m, msg.Shares1h, msg.Shares3h, msg.Shares6h, msg.Shares12h, msg.Shares24h, msg.Shares48h, msg.Rejects5m, msg.Rejects15m, msg.Rejects30m, msg.Rejects1h, msg.Rejects3h, msg.Rejects6h, msg.Rejects12h, msg.Rejects24h, msg.Rejects48h, msg.Mhs5m, msg.Mhs15m, msg.Mhs30m, msg.Mhs1h, msg.Mhs3h, msg.Mhs6h, msg.Mhs12h, msg.Mhs24h, msg.Mhs48h, msg.Ratio5m, msg.Ratio15m, msg.Ratio30m, msg.Ratio1h, msg.Ratio3h, msg.Ratio6h, msg.Ratio12h, msg.Ratio24h, msg.Ratio48h) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_users_stats,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert users stats table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "users_blkstats": + var msg UsersBlkStats_db_msg = result.(UsersBlkStats_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id, `date`, `user`, miner, `refindex`, height, `hash`, pow, net_target, submit, `success`, accepts, rejects, reward, fee, nonce, subidx) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_users_blkstats,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.User, msg.Miner, msg.Index, msg.Height, msg.Hash, msg.Pow, msg.Net_target, msg.Submit, msg.Success, msg.Accepts, msg.Rejects, msg.Reward, msg.Fee, msg.Nonce, msg.SubIdx) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_users_blkstats,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert users blkstats table sucess,miner type", coinType), zap.String("sql", insert_sql)) + + break + case "pool": + var msg Pool_db_msg = result.(Pool_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,miners,normal,abnormal,offline,mhszero,mhslow,highreject,unstable,net_target,height,submits,blocks,orphans,orphan_ratio,reward,fee) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_pool,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.Miners, msg.Normal, msg.Abnormal, msg.Offline, msg.MhsZero, msg.MhsLow, msg.HighRejects, msg.Unstable, msg.Net_target, msg.Height, msg.Submits, msg.Blocks, msg.Orphans, msg.Orphan_ratio, msg.Reward, msg.Fee) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_pool,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert pool table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "pool_stats": + var msg PoolStats_db_msg = result.(PoolStats_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,shares5m,shares15m,shares30m,shares1h,shares3h,shares6h,shares12h,shares24h,shares48h,rejects5m,rejects15m,rejects30m,rejects1h,rejects3h,rejects6h,rejects12h,rejects24h,rejects48h,mhs5m,mhs15m,mhs30m,mhs1h,mhs3h,mhs6h,mhs12h,mhs24h,mhs48h,ratio5m,ratio15m,ratio30m,ratio1h,ratio3h,ratio6h,ratio12h,ratio24h,ratio48h) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_pool_stats,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.Shares5m, msg.Shares15m, msg.Shares30m, msg.Shares1h, msg.Shares3h, msg.Shares6h, msg.Shares12h, msg.Shares24h, msg.Shares48h, msg.Rejects5m, msg.Rejects15m, msg.Rejects30m, msg.Rejects1h, msg.Rejects3h, msg.Rejects6h, msg.Rejects12h, msg.Rejects24h, msg.Rejects48h, msg.Mhs5m, msg.Mhs15m, msg.Mhs30m, msg.Mhs1h, msg.Mhs3h, msg.Mhs6h, msg.Mhs12h, msg.Mhs24h, msg.Mhs48h, msg.Ratio5m, msg.Ratio15m, msg.Ratio30m, msg.Ratio1h, msg.Ratio3h, msg.Ratio6h, msg.Ratio12h, msg.Ratio24h, msg.Ratio48h) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_pool_stats,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert pool stats table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break*/ + case "pool_blkstats": + var msg PoolBlkStats_db_msg = result.(PoolBlkStats_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,height,hash,pow,net_target,submit,`success`,accepts,rejects,reward,fee,nonce,subidx) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_pool_blkstats,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.Height, msg.Hash, msg.Pow, msg.Net_target, msg.Submit, msg.Success, msg.Accepts, msg.Rejects, msg.Reward, msg.Fee, msg.Nonce, msg.SubIdx) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_pool_blkstats,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert pool blkstats table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "blk_detail": + var msg BlkDetail_db_msg = result.(BlkDetail_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,height,hash,user,miner,`refindex`,`success`,miner_diff,pool_diff,nonce,subidx) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_block_detail,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.Height, msg.Hash, msg.User, msg.Miner, msg.Index, msg.Success, msg.Miner_diff, msg.Pool_diff, msg.Nonce, msg.SubIdx) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_block_detail,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert block detail table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "blk_height_detail": + var msg BlkHeightDetail_db_msg = result.(BlkHeightDetail_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += " (id,date,`from`,`to`) VALUES (?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_block_height_detail,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.From, msg.To) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_block_height_detail,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert block height detail table sucess,miner type", coinType), zap.String("sql", insert_sql)) + break + case "blk_new": + var msg BlkNew_db_msg = result.(BlkNew_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,height,hash,`success`,nonce,subidx) VALUES (?,?,?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_block_new,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.Height, msg.Hash, msg.Success, msg.Nonce, msg.SubIdx) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_block_new,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert block new table sucess,miner type", coinType), zap.String("sql", insert_sql)) + + break + case "address": + var msg Address_db_msg = result.(Address_db_msg) + var insert_sql string = "INSERT INTO " + table_name + insert_sql += "(id,date,addr,alias,valid) VALUES (?,?,?,?,?)" + stmt, err := this.Prepare(insert_sql) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_address,Prepare err", err.Error())) + return err + } + defer stmt.Close() + res, err := stmt.Exec(msg.Id, msg.Date.Format("2006-01-02 15:04:05"), msg.Addr, msg.Sum, msg.Valid) + if err != nil { + this.Logg.Error("[db]", zap.String("db_handle_address,Exec err", err.Error()), zap.Any("db_handle_miners,res", res)) + return err + } + this.Logg.Info("[db]", zap.String("insert address table sucess,miner type", coinType), zap.String("sql", insert_sql)) + + break + default: + this.Logg.Error("[db]", zap.String("inser table unkown table", table)) + break + } + return nil +} + +func (this *PoolDb) UpdatePoolDb(sql string, args ...interface{}) (int64, error) { + + result, err := this.Exec(sql, args...) + if err != nil { + return 0, err + } + var count int64 + count, err = result.RowsAffected() + if err != nil { + return 0, err + } + return count, nil +} + +func (this *PoolDb) DeletePoolDb(sql string, args ...interface{}) (int64, error) { + + result, err := this.Exec(sql, args...) + if err != nil { + return 0, err + } + var count int64 + count, err = result.RowsAffected() + if err != nil { + return 0, err + } + return count, nil +} + +func CheckHeightRangeFromTable(DbCtx *DbContext, TableName string, height int64) (int64, int64) { + if DbCtx == nil { + return -1, -1 + } + + query := fmt.Sprintf("SELECT `from`,`to` FROM %s WHERE `from` <= ? AND `to` > ?", TableName) + rows, err := DbCtx.Shares_obj.Query(query, height, height) + + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("failed to query %s", err.Error())) + return -1, -1 + } + defer rows.Close() + + for rows.Next() { + var from int64 = -1 + var to int64 = -1 + if err := rows.Scan(&from, &to); err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("failed to scan %s", err.Error())) + } + return from, to + } + return -1, -1 +} + +/*func CheckUserFromTable(DbCtx *DbContext, TableName string, User string) bool { + if DbCtx == nil { + return false + } + + query := fmt.Sprintf("SELECT user FROM %s WHERE user = ?", TableName) + rows, err := DbCtx.Db_obj.Query(query, User) + + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("failed to query %s", err.Error())) + return false + } + defer rows.Close() + + for rows.Next() { + var user string + if err := rows.Scan(&user); err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("failed to scan %s", err.Error())) + } + return true + } + return false +}*/ + +func CheckUserMinerFromTable(DbCtx *DbContext, TableName string, User string, Miner string, Index string) bool { + if DbCtx == nil { + return false + } + + query := fmt.Sprintf("SELECT user FROM %s WHERE user = ? AND miner = ? AND `refindex` = ?", TableName) + rows, err := DbCtx.Db_obj.Query(query, User, Miner, Index) + + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("failed to query %s", err.Error())) + return false + } + defer rows.Close() + + for rows.Next() { + var user string + if err := rows.Scan(&user); err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("failed to scan %s", err.Error())) + } + return true + } + return false +} + +func CheckTableIsExist(DbCtx *DbContext, tableName string) bool { + table_exist := true + query := fmt.Sprintf("SHOW TABLES LIKE '%s'", tableName) + var result string + if strings.Contains(tableName, "blk_detail") || strings.Contains(tableName, "blk_new") || strings.Contains(tableName, "blk_height_detail") || strings.Contains(tableName, "block_detail") { + err := DbCtx.Shares_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + return table_exist + } + err := DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + return table_exist +} + +/* +func CreateTable2(DbCtx *DbContext, table string, coinType string, table_name string) error { + var table_sql string + if CheckTableIsExist(DbCtx, table_name) { + return nil + } + switch table { + case "miner": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`user` VARCHAR(128)," + table_sql += "`miner` VARCHAR(128)," + table_sql += "`refindex` VARCHAR(128)," + table_sql += "`target` VARCHAR(128)," + table_sql += "`submit_target` VARCHAR(128)," + table_sql += "`height` INT(10)," + table_sql += "`success` TINYINT(1)," + table_sql += "`pow` VARCHAR(128)," + table_sql += "`net_target` VARCHAR(128)," + table_sql += "`submit` VARCHAR(64)," + table_sql += "`hash` VARCHAR(128)," + table_sql += "`header` VARCHAR(1024)," + table_sql += "`accepts` DECIMAL(32,6)," + table_sql += "`total_accepts` DECIMAL(32,6)," + table_sql += "`rejects` DECIMAL(32,6)," + table_sql += "`total_rejects` DECIMAL(32,6)," + table_sql += "`reward` DECIMAL(32,6)," + table_sql += "`fee` DECIMAL(32,6)," + table_sql += "`nonce` VARCHAR(64)," + table_sql += "`subidx` INT(10)," + table_sql += " PRIMARY KEY (`id`))" + break + default: + log.Println("[db],create table unkown table") + DbCtx.Db_obj.Logg.Info("[db]", zap.String("create table unkown table:", table)) + break + } + //log.Println(table, table_sql, table_name) + _, err := DbCtx.Db_obj.QueryPoolDb(table_sql) + if err != nil { + //log.Println("[db],create table err: result:", err.Error()) + DbCtx.Db_obj.Logg.Info("[db]", zap.String("create table err: result:", err.Error())) + } + return err +}*/ + +func CreateTable(DbCtx *DbContext, table string, coinType string) error { + var table_sql string + var table_name string + table_name = coinType + "_" + table + + if CheckTableIsExist(DbCtx, table_name) { + return nil + } + + switch table { + case "miners": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`fromip` VARCHAR(64)," + table_sql += "`state` VARCHAR(64)," + table_sql += "`online` DATETIME," + table_sql += "`offline` DATETIME," + table_sql += "`retry` INT(10)," + table_sql += "`duration` DECIMAL(12,6)," + table_sql += "`protocol` VARCHAR(64)," + table_sql += "`user` VARCHAR(128)," + table_sql += "`miner` VARCHAR(128)," + table_sql += "`refindex` VARCHAR(128)," + table_sql += "`diff` DECIMAL(32,6)," + table_sql += "`height` INT(10)," + table_sql += "`accepts` DECIMAL(32,6)," + table_sql += "`rejects` DECIMAL(32,6)," + table_sql += "`ratio` DECIMAL(32,6)," + table_sql += "`staleds` DECIMAL(32,6)," + table_sql += "`lows` DECIMAL(32,6)," + table_sql += "`duplicates` DECIMAL(32,6)," + table_sql += "`formats` DECIMAL(32,6)," + table_sql += "`others` DECIMAL(32,6)," + table_sql += "`is_disabled` TINYINT(1)," + table_sql += "`last_submit` DATETIME," + table_sql += "`submits` INT(10)," + table_sql += "`blocks` INT(10)," + table_sql += "`orphans` INT(10)," + table_sql += "`orphan_ratio` DECIMAL(32,6)," + table_sql += " PRIMARY KEY (`id`))" + break + case "miners_stats": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`user` VARCHAR(128)," + table_sql += "`miner` VARCHAR(128)," + table_sql += "`refindex` VARCHAR(128)," + table_sql += "`shares5m` DECIMAL(32,6)," + table_sql += "`shares15m` DECIMAL(32,6)," + table_sql += "`shares30m` DECIMAL(32,6)," + table_sql += "`shares1h` DECIMAL(32,6)," + table_sql += "`shares3h` DECIMAL(32,6)," + table_sql += "`shares6h` DECIMAL(32,6)," + table_sql += "`shares12h` DECIMAL(32,6)," + table_sql += "`shares24h` DECIMAL(32,6)," + table_sql += "`shares48h` DECIMAL(32,6)," + table_sql += "`rejects5m` DECIMAL(32,6)," + table_sql += "`rejects15m` DECIMAL(32,6)," + table_sql += "`rejects30m` DECIMAL(32,6)," + table_sql += "`rejects1h` DECIMAL(32,6)," + table_sql += "`rejects3h` DECIMAL(32,6)," + table_sql += "`rejects6h` DECIMAL(32,6)," + table_sql += "`rejects12h` DECIMAL(32,6)," + table_sql += "`rejects24h` DECIMAL(32,6)," + table_sql += "`rejects48h` DECIMAL(32,6)," + table_sql += "`mhs5m` DECIMAL(32,6)," + table_sql += "`mhs15m` DECIMAL(32,6)," + table_sql += "`mhs30m` DECIMAL(32,6)," + table_sql += "`mhs1h` DECIMAL(32,6)," + table_sql += "`mhs3h` DECIMAL(32,6)," + table_sql += "`mhs6h` DECIMAL(32,6)," + table_sql += "`mhs12h` DECIMAL(32,6)," + table_sql += "`mhs24h` DECIMAL(32,6)," + table_sql += "`mhs48h` DECIMAL(32,6)," + table_sql += "`ratio5m` DECIMAL(32,6)," + table_sql += "`ratio15m` DECIMAL(32,6)," + table_sql += "`ratio30m` DECIMAL(32,6)," + table_sql += "`ratio1h` DECIMAL(32,6)," + table_sql += "`ratio3h` DECIMAL(32,6)," + table_sql += "`ratio6h` DECIMAL(32,6)," + table_sql += "`ratio12h` DECIMAL(32,6)," + table_sql += "`ratio24h` DECIMAL(32,6)," + table_sql += "`ratio48h` DECIMAL(32,6)," + table_sql += " PRIMARY KEY (`id`))" + break + /*case "miner": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`user` VARCHAR(128)," + table_sql += "`miner` VARCHAR(128)," + table_sql += "`refindex` VARCHAR(128)," + table_sql += "`target` VARCHAR(128)," + table_sql += "`submit_target` VARCHAR(128)," + table_sql += "`height` INT(10)," + table_sql += "`success` TINYINT(1)," + table_sql += "`pow` VARCHAR(128)," + table_sql += "`net_target` VARCHAR(128)," + table_sql += "`submit` VARCHAR(64)," + table_sql += "`hash` VARCHAR(128)," + table_sql += "`header` VARCHAR(1024)," + table_sql += "`accepts` DECIMAL(32,6)," + table_sql += "`total_accepts` DECIMAL(32,6)," + table_sql += "`rejects` DECIMAL(32,6)," + table_sql += "`total_rejects` DECIMAL(32,6)," + table_sql += "`reward` DECIMAL(32,6)," + table_sql += "`fee` DECIMAL(32,6)," + table_sql += "`nonce` VARCHAR(64)," + table_sql += "`subidx` INT(10)," + table_sql += " PRIMARY KEY (`id`))" + break + case "users": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`user` VARCHAR(128)," + table_sql += "`normal` INT(10)," + table_sql += "`abnormal` INT(10)," + table_sql += "`offline` INT(10)," + table_sql += "`mhszero` INT(10)," + table_sql += "`mhslow` INT(10)," + table_sql += "`highreject` INT(10)," + table_sql += "`unstable` INT(10)," + table_sql += "`submits` INT(10)," + table_sql += "`blocks` INT(10)," + table_sql += "`orphans` INT(10)," + table_sql += "`orphan_ratio` DECIMAL(32,6)," + table_sql += "`reward` DECIMAL(32,6)," + table_sql += "`fee` DECIMAL(32,6)," + table_sql += " PRIMARY KEY (`id`))" + break + case "users_stats": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`user` VARCHAR(128)," + table_sql += "`shares5m` DECIMAL(32,6)," + table_sql += "`shares15m` DECIMAL(32,6)," + table_sql += "`shares30m` DECIMAL(32,6)," + table_sql += "`shares1h` DECIMAL(32,6)," + table_sql += "`shares3h` DECIMAL(32,6)," + table_sql += "`shares6h` DECIMAL(32,6)," + table_sql += "`shares12h` DECIMAL(32,6)," + table_sql += "`shares24h` DECIMAL(32,6)," + table_sql += "`shares48h` DECIMAL(32,6)," + table_sql += "`rejects5m` DECIMAL(32,6)," + table_sql += "`rejects15m` DECIMAL(32,6)," + table_sql += "`rejects30m` DECIMAL(32,6)," + table_sql += "`rejects1h` DECIMAL(32,6)," + table_sql += "`rejects3h` DECIMAL(32,6)," + table_sql += "`rejects6h` DECIMAL(32,6)," + table_sql += "`rejects12h` DECIMAL(32,6)," + table_sql += "`rejects24h` DECIMAL(32,6)," + table_sql += "`rejects48h` DECIMAL(32,6)," + table_sql += "`mhs5m` DECIMAL(32,6)," + table_sql += "`mhs15m` DECIMAL(32,6)," + table_sql += "`mhs30m` DECIMAL(32,6)," + table_sql += "`mhs1h` DECIMAL(32,6)," + table_sql += "`mhs3h` DECIMAL(32,6)," + table_sql += "`mhs6h` DECIMAL(32,6)," + table_sql += "`mhs12h` DECIMAL(32,6)," + table_sql += "`mhs24h` DECIMAL(32,6)," + table_sql += "`mhs48h` DECIMAL(32,6)," + table_sql += "`ratio5m` DECIMAL(32,6)," + table_sql += "`ratio15m` DECIMAL(32,6)," + table_sql += "`ratio30m` DECIMAL(32,6)," + table_sql += "`ratio1h` DECIMAL(32,6)," + table_sql += "`ratio3h` DECIMAL(32,6)," + table_sql += "`ratio6h` DECIMAL(32,6)," + table_sql += "`ratio12h` DECIMAL(32,6)," + table_sql += "`ratio24h` DECIMAL(32,6)," + table_sql += "`ratio48h` DECIMAL(32,6)," + table_sql += " PRIMARY KEY (`id`))" + break + case "users_blkstats": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`height` INT(10)," + table_sql += "`user` VARCHAR(128)," + table_sql += "`miner` VARCHAR(128)," + table_sql += "`refindex` VARCHAR(128)," + table_sql += "`hash` VARCHAR(128)," + table_sql += "`pow` VARCHAR(128)," + table_sql += "`net_target` VARCHAR(128)," + table_sql += "`submit` VARCHAR(64)," + table_sql += "`success` TINYINT(1)," + table_sql += "`accepts` DECIMAL(32,6)," + table_sql += "`rejects` DECIMAL(32,6)," + table_sql += "`reward` DECIMAL(32,6)," + table_sql += "`fee` DECIMAL(32,6)," + table_sql += "`nonce` VARCHAR(64)," + table_sql += "`subidx` INT(10)," + table_sql += " PRIMARY KEY (`id`))" + break + case "pool": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`miners` INT(10)," + table_sql += "`normal` INT(10)," + table_sql += "`abnormal` INT(10)," + table_sql += "`offline` INT(10)," + table_sql += "`mhszero` INT(10)," + table_sql += "`mhslow` INT(10)," + table_sql += "`highreject` INT(10)," + table_sql += "`unstable` INT(10)," + table_sql += "`net_target` VARCHAR(128)," + table_sql += "`height` INT(10)," + table_sql += "`submits` INT(10)," + table_sql += "`blocks` INT(10)," + table_sql += "`orphans` INT(10)," + table_sql += "`orphan_ratio` DECIMAL(32,6)," + table_sql += "`reward` DECIMAL(32,6)," + table_sql += "`fee` DECIMAL(32,6)," + table_sql += " PRIMARY KEY (`id`))" + break + case "pool_stats": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`mhs5m` DECIMAL(32,6)," + table_sql += "`mhs15m` DECIMAL(32,6)," + table_sql += "`mhs30m` DECIMAL(32,6)," + table_sql += "`mhs1h` DECIMAL(32,6)," + table_sql += "`mhs3h` DECIMAL(32,6)," + table_sql += "`mhs6h` DECIMAL(32,6)," + table_sql += "`mhs12h` DECIMAL(32,6)," + table_sql += "`mhs24h` DECIMAL(32,6)," + table_sql += "`mhs48h` DECIMAL(32,6)," + table_sql += "`shares5m` DECIMAL(32,6)," + table_sql += "`shares15m` DECIMAL(32,6)," + table_sql += "`shares30m` DECIMAL(32,6)," + table_sql += "`shares1h` DECIMAL(32,6)," + table_sql += "`shares3h` DECIMAL(32,6)," + table_sql += "`shares6h` DECIMAL(32,6)," + table_sql += "`shares12h` DECIMAL(32,6)," + table_sql += "`shares24h` DECIMAL(32,6)," + table_sql += "`shares48h` DECIMAL(32,6)," + table_sql += "`rejects5m` DECIMAL(32,6)," + table_sql += "`rejects15m` DECIMAL(32,6)," + table_sql += "`rejects30m` DECIMAL(32,6)," + table_sql += "`rejects1h` DECIMAL(32,6)," + table_sql += "`rejects3h` DECIMAL(32,6)," + table_sql += "`rejects6h` DECIMAL(32,6)," + table_sql += "`rejects12h` DECIMAL(32,6)," + table_sql += "`rejects24h` DECIMAL(32,6)," + table_sql += "`rejects48h` DECIMAL(32,6)," + table_sql += "`ratio5m` DECIMAL(32,6)," + table_sql += "`ratio15m` DECIMAL(32,6)," + table_sql += "`ratio30m` DECIMAL(32,6)," + table_sql += "`ratio1h` DECIMAL(32,6)," + table_sql += "`ratio3h` DECIMAL(32,6)," + table_sql += "`ratio6h` DECIMAL(32,6)," + table_sql += "`ratio12h` DECIMAL(32,6)," + table_sql += "`ratio24h` DECIMAL(32,6)," + table_sql += "`ratio48h` DECIMAL(32,6)," + table_sql += " PRIMARY KEY (`id`))" + break*/ + case "pool_blkstats": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`height` INT(10)," + table_sql += "`hash` VARCHAR(128)," + table_sql += "`pow` VARCHAR(128)," + table_sql += "`net_target` VARCHAR(128)," + table_sql += "`submit` VARCHAR(64)," + table_sql += "`success` TINYINT(1)," + table_sql += "`accepts` DECIMAL(32,6)," + table_sql += "`rejects` DECIMAL(32,6)," + table_sql += "`reward` DECIMAL(32,6)," + table_sql += "`fee` DECIMAL(32,6)," + table_sql += "`nonce` VARCHAR(64)," + table_sql += "`subidx` INT(10)," + table_sql += " PRIMARY KEY (`id`))" + break + case "blk_height_detail": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`from` INT(10)," + table_sql += "`to` INT(10)," + table_sql += " PRIMARY KEY (`id`))" + break + case "blk_detail": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`height` INT(10)," + table_sql += "`hash` VARCHAR(128)," + table_sql += "`user` VARCHAR(128)," + table_sql += "`miner` VARCHAR(128)," + table_sql += "`refindex` VARCHAR(128)," + table_sql += "`success` TINYINT(1)," + table_sql += "`miner_diff` DECIMAL(32,6)," + table_sql += "`pool_diff` DECIMAL(32,6)," + table_sql += "`nonce` VARCHAR(64)," + table_sql += "`subidx` INT(10)," + table_sql += " PRIMARY KEY (`id`))" + break + case "blk_new": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) NOT NULL AUTO_INCREMENT," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`height` INT(10)," + table_sql += "`hash` VARCHAR(128)," + table_sql += "`success` TINYINT(1)," + table_sql += "`nonce` VARCHAR(64)," + table_sql += "`subidx` INT(10)," + table_sql += " PRIMARY KEY (`id`))" + break + case "address": + table_sql = "CREATE TABLE " + table_sql += "`" + table_name + "`" + table_sql += "(`id` INT(10) AUTO_INCREMENT UNIQUE," + table_sql += "`date` DATETIME NOT NULL," + table_sql += "`addr` VARCHAR(128)," + table_sql += "`alias` VARCHAR(128)," + table_sql += "`valid` TINYINT(1)," + table_sql += " PRIMARY KEY (`addr`))" + break + default: + log.Println("[db],create table unkown table") + DbCtx.Db_obj.Logg.Info("[db]", zap.String("create table unkown table:", table)) + break + } + //log.Println(table, table_sql) + if strings.Contains(table, "blk_detail") || strings.Contains(table, "blk_new") || strings.Contains(table, "blk_height_detail") || strings.Contains(table, "block_detail") { + _, err := DbCtx.Shares_obj.QueryPoolDb(table_sql) + if err != nil { + log.Println("[db],create table err: result:", err.Error()) + DbCtx.Shares_obj.Logg.Info("[db]", zap.String("create table err: result:", err.Error())) + } + return err + } + _, err := DbCtx.Db_obj.QueryPoolDb(table_sql) + if err != nil { + log.Println("[db],create table err: result:", err.Error()) + DbCtx.Db_obj.Logg.Info("[db]", zap.String("create table err: result:", err.Error())) + } + return err +} + +func createdb(DbCtx *DbContext) (int, error) { + var result int = 0 + var db_sql string = DbCtx.DbCfg.Db.Username + ":" + DbCtx.DbCfg.Db.Password + "@tcp(" + DbCtx.DbCfg.Db.Ip + ":" + strconv.Itoa(DbCtx.DbCfg.Db.Port) + ")/" + DbCtx.DbCfg.Db.Dbname + "?charset=utf8" + //log.Println("[db],create db sql:", db_sql) + dbconnstr = db_sql + db_obj, err := OpenPoolDb("mysql", db_sql) + if err != nil { + log.Println("[db],open db err:", err.Error()) + //DbCtx.Db_obj.Logg.Info("[db]", zap.String("open db err:", err.Error())) + result = -1 + } + DbCtx.Db_obj = db_obj + + var sharesdb_sql string = DbCtx.DbCfg.Shares.Username + ":" + DbCtx.DbCfg.Shares.Password + "@tcp(" + DbCtx.DbCfg.Shares.Ip + ":" + strconv.Itoa(DbCtx.DbCfg.Shares.Port) + ")/" + DbCtx.DbCfg.Shares.Dbname + "?charset=utf8" + //log.Println("[db],create db sql:", db_sql) + sharesdbconnstr = sharesdb_sql + sharesdb_obj, err := OpenPoolDb("mysql", sharesdb_sql) + if err != nil { + log.Println("[db],open db err:", err.Error()) + //DbCtx.Shares_obj.Logg.Info("[db]", zap.String("open db err:", err.Error())) + result = -1 + } + DbCtx.Shares_obj = sharesdb_obj + log.Println("open db!") + return result, err +} + +func do_handle_miners(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msgs := <-DbCtx.Miners_ch + if len(msgs) == 0 { + continue + } + + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + for _, msg := range msgs { + switch msg.Msg { + case "miners": + curTableName := msg.MinerType + "_" + msg.Msg + if DbCtx.Module == "server" { + if msg.Date.Sub(DbCtx.LastMinersTime) >= 300*time.Second { + prev := DbCtx.LastMinersTime + DbCtx.LastMinersTime = msg.Date + table_exist := true + tableName := msg.MinerType + "_" + msg.Msg + "_" + prev.Format("20060102") + query := fmt.Sprintf("SHOW TABLES LIKE '%s'", tableName) + var result string + err := DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + if !table_exist { + createTableSQL := fmt.Sprintf("CREATE TABLE %s LIKE %s", tableName, curTableName) + _, err = DbCtx.Db_obj.Exec(createTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("create miners table err", err.Error())) + //continue + } + alterTableSQL := fmt.Sprintf("ALTER TABLE %s ADD COLUMN save_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP", tableName) + _, err = DbCtx.Db_obj.Exec(alterTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners column table err", err.Error())) + //continue + } + } + copyDataSQL := fmt.Sprintf("INSERT INTO %s (date, fromip, state, online, offline, retry, duration, protocol, user, miner, `refindex`, diff, height, accepts, rejects, ratio, staleds, lows, duplicates, formats, others, is_disabled, last_submit, submits, blocks, orphans, orphan_ratio, save_ts) SELECT date, fromip, state, online, offline, retry, duration, protocol, user, miner, `refindex`, diff, height, accepts, rejects, ratio, staleds, lows, duplicates, formats, others, is_disabled, last_submit, submits, blocks, orphans, orphan_ratio, '%s' FROM %s", tableName, prev.Format("2006-01-02 15:04:05"), curTableName) + _, err = DbCtx.Db_obj.Exec(copyDataSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners column table err", err.Error())) + //continue + } + } + found := CheckUserMinerFromTable(DbCtx, msg.MinerType+"_"+msg.Msg, msg.User, msg.Miner, msg.Index) + if found { + updateSQL := fmt.Sprintf("UPDATE %s SET date = ?, fromip = ?, state = ?, online = ?, offline = ?, retry = ?, duration = ?, protocol = ?, diff = ?, height = ?, accepts = ?, rejects = ?, ratio = ?, staleds = ?, lows = ?, duplicates = ?, formats = ?, others = ?, is_disabled = ?, last_submit = ?, submits = ?, blocks = ?, orphans = ?, orphan_ratio = ? WHERE user = ? AND miner = ? AND `refindex` = ?", curTableName) + count, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Date.Format("2006-01-02 15:04:05"), msg.Fromip, msg.State, msg.Online, msg.Offline, msg.Retry, msg.Duration, msg.Protocol, msg.Diff, msg.Height, msg.Accepts, msg.Rejects, msg.Ratio, msg.Staleds, msg.Lows, msg.Duplicates, msg.Formats, msg.Others, msg.Disabled, msg.Last_submit, msg.Submits, msg.Blocks, msg.Orphans, msg.Orphan_ratio, msg.User, msg.Miner, msg.Index) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update miners table err", err.Error())) + //continue + } + DbCtx.Db_obj.Logg.Info("[db]", zap.Int64("update miners table count", count), zap.String("update miners table MinerType", msg.MinerType), zap.String("sql", updateSQL)) + } else { + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert miners table err", err.Error())) + } + } + } else if DbCtx.Module == "gbt" { + /*curTableName := msg.MinerType + "_" + msg.Msg + last_blocks := GetLastBlocksFromTable(DbCtx, curTableName, msg.User, msg.Miner, msg.Index) + if last_blocks >= 0 { + last_blocks += 1 + UpdateBlocksToTable(DbCtx, curTableName, msg.User, msg.Miner, msg.Index, last_blocks) + }*/ + + } else if DbCtx.Module == "block" { + } + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_miners", "unkown msg "+msg.Msg)) + break + } + } + } +} + +func do_handle_miners_old(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msgs := <-DbCtx.Miners_ch + for _, msg := range msgs { + switch msg.Msg { + case "miners": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + curTableName := msg.MinerType + "_" + msg.Msg + if DbCtx.Module == "server" { + if msg.Date.Sub(DbCtx.LastMinersTime) >= 300*time.Second { + prev := DbCtx.LastMinersTime + DbCtx.LastMinersTime = msg.Date + table_exist := true + tableName := msg.MinerType + "_" + msg.Msg + "_" + prev.Format("20060102") + query := fmt.Sprintf("SHOW TABLES LIKE '%s'", tableName) + var result string + err := DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + if !table_exist { + createTableSQL := fmt.Sprintf("CREATE TABLE %s LIKE %s", tableName, curTableName) + _, err = DbCtx.Db_obj.Exec(createTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("create miners table err", err.Error())) + //continue + } + alterTableSQL := fmt.Sprintf("ALTER TABLE %s ADD COLUMN save_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP", tableName) + _, err = DbCtx.Db_obj.Exec(alterTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners column table err", err.Error())) + //continue + } + } + copyDataSQL := fmt.Sprintf("INSERT INTO %s (date, fromip, state, online, offline, retry, duration, protocol, user, miner, `refindex`, diff, height, accepts, rejects, ratio, staleds, lows, duplicates, formats, others, is_disabled, last_submit, submits, blocks, orphans, orphan_ratio, save_ts) SELECT date, fromip, state, online, offline, retry, duration, protocol, user, miner, `refindex`, diff, height, accepts, rejects, ratio, staleds, lows, duplicates, formats, others, is_disabled, last_submit, submits, blocks, orphans, orphan_ratio, '%s' FROM %s", tableName, prev.Format("2006-01-02 15:04:05"), curTableName) + _, err = DbCtx.Db_obj.Exec(copyDataSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners column table err", err.Error())) + //continue + } + } + found := CheckUserMinerFromTable(DbCtx, msg.MinerType+"_"+msg.Msg, msg.User, msg.Miner, msg.Index) + if found { + updateSQL := fmt.Sprintf("UPDATE %s SET date = ?, fromip = ?, state = ?, online = ?, offline = ?, retry = ?, duration = ?, protocol = ?, diff = ?, height = ?, accepts = ?, rejects = ?, ratio = ?, staleds = ?, lows = ?, duplicates = ?, formats = ?, others = ?, is_disabled = ?, last_submit = ?, submits = ?, blocks = ?, orphans = ?, orphan_ratio = ? WHERE user = ? AND miner = ? AND `refindex` = ?", curTableName) + count, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Date.Format("2006-01-02 15:04:05"), msg.Fromip, msg.State, msg.Online, msg.Offline, msg.Retry, msg.Duration, msg.Protocol, msg.Diff, msg.Height, msg.Accepts, msg.Rejects, msg.Ratio, msg.Staleds, msg.Lows, msg.Duplicates, msg.Formats, msg.Others, msg.Disabled, msg.Last_submit, msg.Submits, msg.Blocks, msg.Orphans, msg.Orphan_ratio, msg.User, msg.Miner, msg.Index) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update miners table err", err.Error())) + //continue + } + DbCtx.Db_obj.Logg.Info("[db]", zap.Int64("update miners table count", count), zap.String("update miners table MinerType", msg.MinerType), zap.String("sql", updateSQL)) + } else { + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert miners table err", err.Error())) + } + } + } else if DbCtx.Module == "gbt" { + /*curTableName := msg.MinerType + "_" + msg.Msg + last_blocks := GetLastBlocksFromTable(DbCtx, curTableName, msg.User, msg.Miner, msg.Index) + if last_blocks >= 0 { + last_blocks += 1 + UpdateBlocksToTable(DbCtx, curTableName, msg.User, msg.Miner, msg.Index, last_blocks) + }*/ + + } else if DbCtx.Module == "block" { + } + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_miners", "unkown msg "+msg.Msg)) + break + } + } + } +} + +func do_handle_miners_stats(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + + msgs := <-DbCtx.MinersStats_ch + if len(msgs) == 0 { + continue + } + + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + + for _, msg := range msgs { + switch msg.Msg { + case "miners_stats": + curTableName := msg.MinerType + "_" + msg.Msg + if DbCtx.Module == "server" { + if msg.Date.Sub(DbCtx.LastMinersStatsTime) >= 300*time.Second { + prev := DbCtx.LastMinersStatsTime + DbCtx.LastMinersStatsTime = msg.Date + table_exist := true + tableName := msg.MinerType + "_" + msg.Msg + "_" + prev.Format("20060102") + query := fmt.Sprintf("SHOW TABLES LIKE '%s'", tableName) + var result string + err := DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + if !table_exist { + createTableSQL := fmt.Sprintf("CREATE TABLE %s LIKE %s", tableName, curTableName) + _, err = DbCtx.Db_obj.Exec(createTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("create miners_stats table err", err.Error())) + //continue + } + alterTableSQL := fmt.Sprintf("ALTER TABLE %s ADD COLUMN save_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP", tableName) + _, err = DbCtx.Db_obj.Exec(alterTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners_stats column table err", err.Error())) + //continue + } + } + copyDataSQL := fmt.Sprintf("INSERT INTO %s (date, user, miner, `refindex`, shares5m, shares15m, shares30m, shares1h, shares3h, shares6h, shares12h, shares24h, shares48h, rejects5m, rejects15m, rejects30m, rejects1h, rejects3h, rejects6h, rejects12h, rejects24h, rejects48h, mhs5m, mhs15m, mhs30m, mhs1h, mhs3h, mhs6h, mhs12h, mhs24h, mhs48h, ratio5m, ratio15m, ratio30m, ratio1h, ratio3h, ratio6h, ratio12h, ratio24h, ratio48h, save_ts) SELECT date, user, miner, `refindex`, shares5m, shares15m, shares30m, shares1h, shares3h, shares6h, shares12h, shares24h, shares48h, rejects5m, rejects15m, rejects30m, rejects1h, rejects3h, rejects6h, rejects12h, rejects24h, rejects48h, mhs5m, mhs15m, mhs30m, mhs1h, mhs3h, mhs6h, mhs12h, mhs24h, mhs48h, ratio5m, ratio15m, ratio30m, ratio1h, ratio3h, ratio6h, ratio12h, ratio24h, ratio48h, '%s' FROM %s", tableName, prev.Format("2006-01-02 15:04:05"), curTableName) + _, err = DbCtx.Db_obj.Exec(copyDataSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners_stats column table err", err.Error())) + //continue + } + } + found := CheckUserMinerFromTable(DbCtx, msg.MinerType+"_"+msg.Msg, msg.User, msg.Miner, msg.Index) + if found { + updateSQL := fmt.Sprintf("UPDATE %s SET date = ?, shares5m = ?, shares15m = ?, shares30m = ?, shares1h = ?, shares3h = ?, shares6h = ?, shares12h = ?, shares24h = ?, shares48h = ?, rejects5m = ?, rejects15m = ?, rejects30m = ?, rejects1h = ?, rejects3h = ?, rejects6h = ?, rejects12h = ?, rejects24h = ?, rejects48h = ?, mhs5m = ?, mhs15m = ?, mhs30m = ?, mhs1h = ?, mhs3h = ?, mhs6h = ?, mhs12h = ?, mhs24h = ?, mhs48h = ?, ratio5m = ?, ratio15m = ?, ratio30m = ?, ratio1h = ?, ratio3h = ?, ratio6h = ?, ratio12h = ?, ratio24h = ?, ratio48h = ? WHERE user = ? AND miner = ? AND `refindex` = ?", curTableName) + count, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Date.Format("2006-01-02 15:04:05"), msg.Shares5m, msg.Shares15m, msg.Shares30m, msg.Shares1h, msg.Shares3h, msg.Shares6h, msg.Shares12h, msg.Shares24h, msg.Shares48h, msg.Rejects5m, msg.Rejects15m, msg.Rejects30m, msg.Rejects1h, msg.Rejects3h, msg.Rejects6h, msg.Rejects12h, msg.Rejects24h, msg.Rejects48h, msg.Mhs5m, msg.Mhs15m, msg.Mhs30m, msg.Mhs1h, msg.Mhs3h, msg.Mhs6h, msg.Mhs12h, msg.Mhs24h, msg.Mhs48h, msg.Ratio5m, msg.Ratio15m, msg.Ratio30m, msg.Ratio1h, msg.Ratio3h, msg.Ratio6h, msg.Ratio12h, msg.Ratio24h, msg.Ratio48h, msg.User, msg.Miner, msg.Index) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update miners_stats table err", err.Error())) + //continue + } + DbCtx.Db_obj.Logg.Info("[db]", zap.Int64("update miners_stats table count", count), zap.String("update miners table MinerType", msg.MinerType), zap.String("sql", updateSQL)) + } else { + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert miners_stats table err", err.Error())) + } + } + } else if DbCtx.Module == "gbt" { + + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_miners_stats", "unkown msg "+msg.Msg)) + break + } + } + } +} + +func do_handle_miners_stats_old(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msgs := <-DbCtx.MinersStats_ch + for _, msg := range msgs { + switch msg.Msg { + case "miners_stats": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + curTableName := msg.MinerType + "_" + msg.Msg + if DbCtx.Module == "server" { + if msg.Date.Sub(DbCtx.LastMinersStatsTime) >= 300*time.Second { + prev := DbCtx.LastMinersStatsTime + DbCtx.LastMinersStatsTime = msg.Date + table_exist := true + tableName := msg.MinerType + "_" + msg.Msg + "_" + prev.Format("20060102") + query := fmt.Sprintf("SHOW TABLES LIKE '%s'", tableName) + var result string + err := DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + if !table_exist { + createTableSQL := fmt.Sprintf("CREATE TABLE %s LIKE %s", tableName, curTableName) + _, err = DbCtx.Db_obj.Exec(createTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("create miners_stats table err", err.Error())) + //continue + } + alterTableSQL := fmt.Sprintf("ALTER TABLE %s ADD COLUMN save_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP", tableName) + _, err = DbCtx.Db_obj.Exec(alterTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners_stats column table err", err.Error())) + //continue + } + } + copyDataSQL := fmt.Sprintf("INSERT INTO %s (date, user, miner, `refindex`, shares5m, shares15m, shares30m, shares1h, shares3h, shares6h, shares12h, shares24h, shares48h, rejects5m, rejects15m, rejects30m, rejects1h, rejects3h, rejects6h, rejects12h, rejects24h, rejects48h, mhs5m, mhs15m, mhs30m, mhs1h, mhs3h, mhs6h, mhs12h, mhs24h, mhs48h, ratio5m, ratio15m, ratio30m, ratio1h, ratio3h, ratio6h, ratio12h, ratio24h, ratio48h, save_ts) SELECT date, user, miner, `refindex`, shares5m, shares15m, shares30m, shares1h, shares3h, shares6h, shares12h, shares24h, shares48h, rejects5m, rejects15m, rejects30m, rejects1h, rejects3h, rejects6h, rejects12h, rejects24h, rejects48h, mhs5m, mhs15m, mhs30m, mhs1h, mhs3h, mhs6h, mhs12h, mhs24h, mhs48h, ratio5m, ratio15m, ratio30m, ratio1h, ratio3h, ratio6h, ratio12h, ratio24h, ratio48h, '%s' FROM %s", tableName, prev.Format("2006-01-02 15:04:05"), curTableName) + _, err = DbCtx.Db_obj.Exec(copyDataSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add miners_stats column table err", err.Error())) + //continue + } + } + found := CheckUserMinerFromTable(DbCtx, msg.MinerType+"_"+msg.Msg, msg.User, msg.Miner, msg.Index) + if found { + updateSQL := fmt.Sprintf("UPDATE %s SET date = ?, shares5m = ?, shares15m = ?, shares30m = ?, shares1h = ?, shares3h = ?, shares6h = ?, shares12h = ?, shares24h = ?, shares48h = ?, rejects5m = ?, rejects15m = ?, rejects30m = ?, rejects1h = ?, rejects3h = ?, rejects6h = ?, rejects12h = ?, rejects24h = ?, rejects48h = ?, mhs5m = ?, mhs15m = ?, mhs30m = ?, mhs1h = ?, mhs3h = ?, mhs6h = ?, mhs12h = ?, mhs24h = ?, mhs48h = ?, ratio5m = ?, ratio15m = ?, ratio30m = ?, ratio1h = ?, ratio3h = ?, ratio6h = ?, ratio12h = ?, ratio24h = ?, ratio48h = ? WHERE user = ? AND miner = ? AND `refindex` = ?", curTableName) + count, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Date.Format("2006-01-02 15:04:05"), msg.Shares5m, msg.Shares15m, msg.Shares30m, msg.Shares1h, msg.Shares3h, msg.Shares6h, msg.Shares12h, msg.Shares24h, msg.Shares48h, msg.Rejects5m, msg.Rejects15m, msg.Rejects30m, msg.Rejects1h, msg.Rejects3h, msg.Rejects6h, msg.Rejects12h, msg.Rejects24h, msg.Rejects48h, msg.Mhs5m, msg.Mhs15m, msg.Mhs30m, msg.Mhs1h, msg.Mhs3h, msg.Mhs6h, msg.Mhs12h, msg.Mhs24h, msg.Mhs48h, msg.Ratio5m, msg.Ratio15m, msg.Ratio30m, msg.Ratio1h, msg.Ratio3h, msg.Ratio6h, msg.Ratio12h, msg.Ratio24h, msg.Ratio48h, msg.User, msg.Miner, msg.Index) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update miners_stats table err", err.Error())) + //continue + } + DbCtx.Db_obj.Logg.Info("[db]", zap.Int64("update miners_stats table count", count), zap.String("update miners table MinerType", msg.MinerType), zap.String("sql", updateSQL)) + } else { + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert miners_stats table err", err.Error())) + } + } + } else if DbCtx.Module == "gbt" { + + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_miners_stats", "unkown msg "+msg.Msg)) + break + } + } + } +} + +/*func do_handle_miner(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.Miner_ch + switch msg.Msg { + case "miner": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + minerTableName := msg.MinerType + "_" + msg.Msg + "_" + msg.User + "_" + msg.Miner + "_" + msg.Index + table_exist := true + query := fmt.Sprintf("SHOW TABLES LIKE '%s'", minerTableName) + var result string + err := DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + if !table_exist { + CreateTable2(DbCtx, msg.Msg, msg.MinerType, minerTableName) + } + DbCtx.LastMinerTime = GetLastTimeFromTable(DbCtx, minerTableName) + + newTableName := minerTableName + "_" + DbCtx.LastMinerTime.Format("20060102") + //fmt.Printf("do_handle_miner %v,%v,%v", DbCtx.LastMinerTime, DbCtx.LastMinerTime.Format("20060102"), newTableName) + if msg.Date.Format("2006-01-02") != DbCtx.LastMinerTime.Format("2006-01-02") { + //DbCtx.LastMinerTime = msg.Date + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", minerTableName, newTableName) + _, err := DbCtx.Db_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("miner rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable2(DbCtx, msg.Msg, msg.MinerType, minerTableName) + } + err = DbCtx.Db_obj.InsertPoolDb2(msg.Msg, msg.MinerType, minerTableName, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert miner table err", err.Error())) + } + + } else if DbCtx.Module == "gbt" { + minerTableName := msg.MinerType + "_" + msg.Msg + "_" + msg.User + "_" + msg.Miner + "_" + msg.Index + updateSQL := fmt.Sprintf("UPDATE %s SET `success` = ?, reward = ?, fee = ? WHERE height = ? AND nonce = ?", minerTableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Success, msg.Reward, msg.Fee, msg.Height, msg.Nonce) + if err != nil { + log.Printf("[db] update miner table err %s %s", minerTableName, err.Error()) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update miner table err", err.Error())) + //continue + } + //log.Printf("[db] update %s %d %s %d\n", minerTableName, msg.Height, msg.Nonce, msg.Success) + now := time.Now() + yesterday := now.AddDate(0, 0, -1) + yesterdayTableName := minerTableName + "_" + yesterday.Format("20060102") + if CheckTableIsExist(DbCtx, yesterdayTableName) { + updateYesterdaySQL := fmt.Sprintf("UPDATE %s SET `success` = ?, reward = ?, fee = ? WHERE height = ? AND nonce = ?", yesterdayTableName) + _, err = DbCtx.Db_obj.UpdatePoolDb(updateYesterdaySQL, msg.Success, msg.Reward, msg.Fee, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + } + } else if DbCtx.Module == "block" { + } + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_miner", "unkown msg "+msg.Msg)) + break + } + } +}*/ + +/*func do_handle_users(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.Users_ch + switch msg.Msg { + case "users": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + curTableName := msg.MinerType + "_" + msg.Msg + if DbCtx.Module == "server" { + if msg.Date.Sub(DbCtx.LastUsersTime) >= 300*time.Second { + + msg.Normal = 0 + msg.Abnormal = 0 + + msg.Offline = 0 + msg.MhsZero = 0 + msg.MhsLow = 0 + msg.HighRejects = 0 + msg.Unstable = 0 + + startTime := time.Now().Add(-48 * time.Hour).Unix() + minersTable := msg.MinerType + "_" + "miners" + minersMhsTable := msg.MinerType + "_" + "miners_stats" + + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE UNIX_TIMESTAMP(date) >= %d AND user = '%s'", minersTable, startTime, msg.User) + var total_count int64 = 0 + err := DbCtx.Db_obj.QueryRow(query).Scan(&total_count) + if err != nil { + log.Printf("Error querying database total_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database total_count:", curTableName+" "+err.Error())) + } + //log.Printf("[db] users total_count %d %s\n", total_count, query) + + //query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND mhs5m >= 10 AND UNIX_TIMESTAMP(date) >= %d AND user = %s", minersTable, startTime, msg.User) + query = fmt.Sprintf("SELECT COUNT(*) FROM %s po JOIN %s pm ON po.user = pm.user AND po.miner = pm.miner AND po.refindex = pm.refindex WHERE po.`state` = 'online' AND pm.mhs5m >= 10.0 AND UNIX_TIMESTAMP(po.`date`) >= %d AND po.user = '%s'", minersTable, minersMhsTable, startTime, msg.User) + var normal_count int64 = 0 + err = DbCtx.Db_obj.QueryRow(query).Scan(&normal_count) + if err != nil { + log.Printf("Error querying database normal_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database normal_count:", curTableName+" "+err.Error())) + } + msg.Normal = normal_count + msg.Abnormal = total_count - normal_count + //log.Printf("[db] users normal_count %d %s\n", normal_count, query) + + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'offline' AND UNIX_TIMESTAMP(date) >= %d AND user = '%s'", minersTable, startTime, msg.User) + var offline_count int64 = 0 + err = DbCtx.Db_obj.QueryRow(query).Scan(&offline_count) + if err != nil { + log.Printf("Error querying database offline_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database offline_count:", curTableName+" "+err.Error())) + } + msg.Offline = offline_count + //log.Printf("[db] users offline_count %d %s\n", offline_count, query) + + //query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND mhs5m <= 0 AND duration > 300 AND UNIX_TIMESTAMP(date) >= %d AND user = %s", minersTable, startTime, msg.User) + query = fmt.Sprintf("SELECT COUNT(*) FROM %s po JOIN %s pm ON po.user = pm.user AND po.miner = pm.miner AND po.refindex = pm.refindex WHERE po.`state` = 'online' AND pm.mhs5m <= 0.0 AND po.duration > 300.0 AND UNIX_TIMESTAMP(po.`date`) >= %d AND po.user = '%s'", minersTable, minersMhsTable, startTime, msg.User) + var mhszero_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&mhszero_count) + if err != nil { + log.Printf("Error querying database mhszero_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database mhszero_count:", curTableName+" "+err.Error())) + } + msg.MhsZero = mhszero_count + //log.Printf("[db] users mhszero_count %d %s\n", mhszero_count, query) + + //query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND mhs5m < 10 AND duration > 300 AND UNIX_TIMESTAMP(date) >= %d AND user = '%s'", minersTable, startTime, msg.User) + query = fmt.Sprintf("SELECT COUNT(*) FROM %s po JOIN %s pm ON po.user = pm.user AND po.miner = pm.miner AND po.refindex = pm.refindex WHERE po.`state` = 'online' AND pm.mhs5m < 10.0 AND po.duration > 300.0 AND UNIX_TIMESTAMP(po.date) >= %d AND po.user = '%s'", minersTable, minersMhsTable, startTime, msg.User) + var mhslow_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&mhslow_count) + if err != nil { + log.Printf("Error querying database mhslow_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database mhslow_count:", curTableName+" "+err.Error())) + } + msg.MhsLow = mhslow_count + //log.Printf("[db] users mhslow_count %d %s\n", mhslow_count, query) + + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND ratio > 0.01 AND UNIX_TIMESTAMP(date) >= %d AND user = '%s'", minersTable, startTime, msg.User) + var highreject_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&highreject_count) + if err != nil { + log.Printf("Error querying database highreject_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database highreject_count:", curTableName+" "+err.Error())) + } + msg.HighRejects = highreject_count + //log.Printf("[db] users highreject_count %d %s\n", highreject_count, query) + + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND retry > 10 AND UNIX_TIMESTAMP(date) >= %d AND user = '%s'", minersTable, startTime, msg.User) + var unstable_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&unstable_count) + if err != nil { + log.Printf("Error querying database unstable_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database unstable_count:", curTableName+" "+err.Error())) + } + msg.Unstable = unstable_count + //log.Printf("[db] users unstable_count %d %s\n", unstable_count, query) + + prev := DbCtx.LastUsersTime + DbCtx.LastUsersTime = msg.Date + table_exist := true + tableName := msg.MinerType + "_" + msg.Msg + "_" + prev.Format("20060102") + query = fmt.Sprintf("SHOW TABLES LIKE '%s'", tableName) + var result string + err = DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + if !table_exist { + createTableSQL := fmt.Sprintf("CREATE TABLE %s LIKE %s", tableName, curTableName) + _, err = DbCtx.Db_obj.Exec(createTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("create users table err", err.Error())) + //continue + } + alterTableSQL := fmt.Sprintf("ALTER TABLE %s ADD COLUMN save_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP", tableName) + _, err = DbCtx.Db_obj.Exec(alterTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add users column table err", err.Error())) + //continue + } + } + copyDataSQL := fmt.Sprintf("INSERT INTO %s (date,user,normal,abnormal,offline,mhszero,mhslow,highreject,unstable,submits,blocks,orphans,orphan_ratio,reward,fee, save_ts) SELECT date,user,normal,abnormal,offline,mhszero,mhslow,highreject,unstable,submits,blocks,orphans,orphan_ratio,reward,fee, '%s' FROM %s", tableName, prev.Format("2006-01-02 15:04:05"), curTableName) + _, err = DbCtx.Db_obj.Exec(copyDataSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add users column table err", err.Error())) + //return + } + } + found := CheckUserFromTable(DbCtx, msg.MinerType+"_"+msg.Msg, msg.User) + if found { + updateSQL := fmt.Sprintf("UPDATE %s SET date = ?, normal = ?, abnormal = ?, offline = ?, mhszero = ?, mhslow = ?, highreject = ?, unstable = ?, submits = ?, blocks = ?, orphans = ?, orphan_ratio = ?, reward = ?, fee = ? WHERE user = ?", curTableName) + count, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Date.Format("2006-01-02 15:04:05"), msg.Normal, msg.Abnormal, msg.Offline, msg.MhsZero, msg.MhsLow, msg.HighRejects, msg.Unstable, msg.Submits, msg.Blocks, msg.Orphans, msg.Orphan_ratio, msg.Reward, msg.Fee, msg.User) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + DbCtx.Db_obj.Logg.Info("[db]", zap.Int64("update users table count", count), zap.String("update miners table MinerType", msg.MinerType), zap.String("sql", updateSQL)) + } else { + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert users table err", err.Error())) + } + } + } else if DbCtx.Module == "gbt" { + curTableName := msg.MinerType + "_" + msg.Msg + last_blocks := GetLastBlocksFromTable(DbCtx, curTableName, msg.User, "", "") + if last_blocks >= 0 { + last_blocks += 1 + UpdateBlocksToTable(DbCtx, curTableName, msg.User, "", "", last_blocks) + } + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_users", "unkown msg "+msg.Msg)) + break + } + } +}*/ + +/*func do_handle_users_stats(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.UsersStats_ch + switch msg.Msg { + case "users_stats": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + curTableName := msg.MinerType + "_" + msg.Msg + if DbCtx.Module == "server" { + if msg.Date.Sub(DbCtx.LastUsersStatsTime) >= 300*time.Second { + prev := DbCtx.LastUsersStatsTime + DbCtx.LastUsersStatsTime = msg.Date + table_exist := true + tableName := msg.MinerType + "_" + msg.Msg + "_" + prev.Format("20060102") + query := fmt.Sprintf("SHOW TABLES LIKE '%s'", tableName) + var result string + err := DbCtx.Db_obj.QueryRow(query).Scan(&result) + if err != nil { + if err == sql.ErrNoRows { + table_exist = false + } + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("check table existence failed:", tableName), zap.String("err", err.Error())) + table_exist = false + } + if !table_exist { + createTableSQL := fmt.Sprintf("CREATE TABLE %s LIKE %s", tableName, curTableName) + _, err = DbCtx.Db_obj.Exec(createTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("create users_stats table err", err.Error())) + //continue + } + alterTableSQL := fmt.Sprintf("ALTER TABLE %s ADD COLUMN save_ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP", tableName) + _, err = DbCtx.Db_obj.Exec(alterTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add users_stats column table err", err.Error())) + //continue + } + } + copyDataSQL := fmt.Sprintf("INSERT INTO %s (date,user,shares5m,shares15m,shares30m,shares1h,shares3h,shares6h,shares12h,shares24h,shares48h,rejects5m,rejects15m,rejects30m,rejects1h,rejects3h,rejects6h,rejects12h,rejects24h,rejects48h,mhs5m,mhs15m,mhs30m,mhs1h,mhs3h,mhs6h,mhs12h,mhs24h,mhs48h,ratio5m,ratio15m,ratio30m,ratio1h,ratio3h,ratio6h,ratio12h,ratio24h,ratio48h,save_ts) SELECT date,user,shares5m,shares15m,shares30m,shares1h,shares3h,shares6h,shares12h,shares24h,shares48h,rejects5m,rejects15m,rejects30m,rejects1h,rejects3h,rejects6h,rejects12h,rejects24h,rejects48h,mhs5m,mhs15m,mhs30m,mhs1h,mhs3h,mhs6h,mhs12h,mhs24h,mhs48h,ratio5m,ratio15m,ratio30m,ratio1h,ratio3h,ratio6h,ratio12h,ratio24h,ratio48h,'%s' FROM %s", tableName, prev.Format("2006-01-02 15:04:05"), curTableName) + + _, err = DbCtx.Db_obj.Exec(copyDataSQL) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("add users_stats column table err", err.Error())) + //continue + } + } + found := CheckUserFromTable(DbCtx, msg.MinerType+"_"+msg.Msg, msg.User) + if found { + updateSQL := fmt.Sprintf("UPDATE %s SET date = ?, shares5m = ?, shares15m = ?, shares30m = ?, shares1h = ?, shares3h = ?, shares6h = ?, shares12h = ?, shares24h = ?, shares48h = ?, rejects5m = ?, rejects15m = ?, rejects30m = ?, rejects1h = ?, rejects3h = ?, rejects6h = ?, rejects12h = ?, rejects24h = ?, rejects48h = ?, mhs5m = ?, mhs15m = ?, mhs30m = ?, mhs1h = ?, mhs3h = ?, mhs6h = ?, mhs12h = ?, mhs24h = ?, mhs48h = ?, ratio5m = ?, ratio15m = ?, ratio30m = ?, ratio1h = ?, ratio3h = ?, ratio6h = ?, ratio12h = ?, ratio24h = ?, ratio48h = ? WHERE user = ?", curTableName) + count, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Date.Format("2006-01-02 15:04:05"), msg.Shares5m, msg.Shares15m, msg.Shares30m, msg.Shares1h, msg.Shares3h, msg.Shares6h, msg.Shares12h, msg.Shares24h, msg.Shares48h, msg.Rejects5m, msg.Rejects15m, msg.Rejects30m, msg.Rejects1h, msg.Rejects3h, msg.Rejects6h, msg.Rejects12h, msg.Rejects24h, msg.Rejects48h, msg.Mhs5m, msg.Mhs15m, msg.Mhs30m, msg.Mhs1h, msg.Mhs3h, msg.Mhs6h, msg.Mhs12h, msg.Mhs24h, msg.Mhs48h, msg.Ratio5m, msg.Ratio15m, msg.Ratio30m, msg.Ratio1h, msg.Ratio3h, msg.Ratio6h, msg.Ratio12h, msg.Ratio24h, msg.Ratio48h, msg.User) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update users_stats table err", err.Error())) + //continue + } + DbCtx.Db_obj.Logg.Info("[db]", zap.Int64("update users_stats table count", count), zap.String("update miners table MinerType", msg.MinerType), zap.String("sql", updateSQL)) + } else { + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert users_stats table err", err.Error())) + } + } + } else if DbCtx.Module == "gbt" { + + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_users", "unkown msg "+msg.Msg)) + break + } + } +}*/ + +/*func do_handle_users_blkstats(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.UsersBlkStats_ch + switch msg.Msg { + case "users_blkstats": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + tableName := msg.MinerType + "_" + msg.Msg + newTableName := msg.MinerType + "_" + msg.Msg + "_" + DbCtx.LastUsersBlkStatsTime.Format("20060102") + + if msg.Date.Format("2006-01-02") != DbCtx.LastUsersBlkStatsTime.Format("2006-01-02") { + DbCtx.LastUsersBlkStatsTime = msg.Date + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Db_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("users_blkstats rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + } + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert users_blkstats table err", err.Error())) + } + } else if DbCtx.Module == "gbt" { + curTableName := msg.MinerType + "_" + msg.Msg + updateSQL := fmt.Sprintf("UPDATE %s SET `success` = ?, reward = ?, fee = ? WHERE height = ? AND nonce = ?", curTableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Success, msg.Reward, msg.Fee, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + now := time.Now() + yesterday := now.AddDate(0, 0, -1) + yesterdayTableName := curTableName + "_" + yesterday.Format("20060102") + if CheckTableIsExist(DbCtx, yesterdayTableName) { + updateYesterdaySQL := fmt.Sprintf("UPDATE %s SET `success` = ?, reward = ?, fee = ? WHERE height = ? AND nonce = ?", yesterdayTableName) + _, err = DbCtx.Db_obj.UpdatePoolDb(updateYesterdaySQL, msg.Success, msg.Reward, msg.Fee, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + } + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_users_blkstats", "unkown msg "+msg.Msg)) + break + } + } +}*/ + +/*func do_handle_pool(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.Pool_ch + switch msg.Msg { + case "pool": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + tableName := msg.MinerType + "_" + msg.Msg + + msg.Miners = 0 + msg.Normal = 0 + msg.Abnormal = 0 + + msg.Offline = 0 + msg.MhsZero = 0 + msg.MhsLow = 0 + msg.HighRejects = 0 + msg.Unstable = 0 + + startTime := time.Now().Add(-48 * time.Hour).Unix() + minersTable := msg.MinerType + "_" + "miners" + minersMhsTable := msg.MinerType + "_" + "miners_stats" + + query := fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE UNIX_TIMESTAMP(date) >= %d", minersTable, startTime) + var total_count int64 = 0 + err := DbCtx.Db_obj.QueryRow(query).Scan(&total_count) + if err != nil { + log.Printf("Error querying database total_count: %s %v %s", tableName, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database total_count:", tableName+" "+err.Error())) + } + msg.Miners = total_count + //log.Printf("[db] pool total_count %d %s\n", total_count, query) + + //query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND mhs5m >= 10 AND UNIX_TIMESTAMP(date) >= %d", minersTable, startTime) + query = fmt.Sprintf("SELECT COUNT(*) FROM %s po JOIN %s pm ON po.user = pm.user AND po.miner = pm.miner AND po.refindex = pm.refindex WHERE po.`state` = 'online' AND pm.mhs5m >= 10.0 AND UNIX_TIMESTAMP(po.date) >= %d", minersTable, minersMhsTable, startTime) + var normal_count int64 = 0 + err = DbCtx.Db_obj.QueryRow(query).Scan(&normal_count) + if err != nil { + log.Printf("Error querying database normal_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database normal_count:", tableName+" "+err.Error())) + } + msg.Normal = normal_count + msg.Abnormal = msg.Miners - normal_count + + //log.Printf("[db] pool normal_count %d %s\n", normal_count, query) + + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'offline' AND UNIX_TIMESTAMP(date) >= %d", minersTable, startTime) + var offline_count int64 = 0 + err = DbCtx.Db_obj.QueryRow(query).Scan(&offline_count) + if err != nil { + log.Printf("Error querying database offline_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database offline_count:", tableName+" "+err.Error())) + } + msg.Offline = offline_count + //log.Printf("[db] pool offline_count %d %s\n", offline_count, query) + + //query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND mhs5m <= 0 AND duration > 300 AND UNIX_TIMESTAMP(date) >= %d", minersTable, startTime) + query = fmt.Sprintf("SELECT COUNT(*) FROM %s po JOIN %s pm ON po.user = pm.user AND po.miner = pm.miner AND po.refindex = pm.refindex WHERE po.`state` = 'online' AND pm.mhs5m <= 0.0 AND po.duration > 300.0 AND UNIX_TIMESTAMP(po.date) >= %d", minersTable, minersMhsTable, startTime) + var mhszero_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&mhszero_count) + if err != nil { + log.Printf("Error querying database mhszero_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database mhszero_count:", tableName+" "+err.Error())) + } + msg.MhsZero = mhszero_count + //log.Printf("[db] pool mhszero_count %d %s\n", mhszero_count, query) + + query = fmt.Sprintf("SELECT COUNT(*) FROM %s po JOIN %s pm ON po.user = pm.user AND po.miner = pm.miner AND po.refindex = pm.refindex WHERE po.`state` = 'online' AND pm.mhs5m < 10.0 AND po.duration > 300.0 AND UNIX_TIMESTAMP(po.`date`) >= %d", minersTable, minersMhsTable, startTime) + var mhslow_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&mhslow_count) + if err != nil { + log.Printf("Error querying database mhslow_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database mhslow_count:", tableName+" "+err.Error())) + } + msg.MhsLow = mhslow_count + //log.Printf("[db] pool mhslow_count %d %s\n", mhslow_count, query) + + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND ratio > 0.01 AND UNIX_TIMESTAMP(date) >= %d", minersTable, startTime) + var highreject_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&highreject_count) + if err != nil { + log.Printf("Error querying database highreject_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database highreject_count:", tableName+" "+err.Error())) + } + msg.HighRejects = highreject_count + //log.Printf("[db] pool highreject_count %d %s\n", highreject_count, query) + + query = fmt.Sprintf("SELECT COUNT(*) FROM %s WHERE `state` = 'online' AND retry > 10 AND UNIX_TIMESTAMP(date) >= %d", minersTable, startTime) + var unstable_count int64 + err = DbCtx.Db_obj.QueryRow(query).Scan(&unstable_count) + if err != nil { + log.Printf("Error querying database unstable_count: %s %v %s", minersTable, err, query) + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Error querying database unstable_count:", tableName+" "+err.Error())) + } + msg.Unstable = unstable_count + //log.Printf("[db] pool unstable_count %d %s\n", unstable_count, query) + + newTableName := msg.MinerType + "_" + msg.Msg + "_" + DbCtx.LastPoolTime.Format("20060102") + + if msg.Date.Format("2006-01-02") != DbCtx.LastPoolTime.Format("2006-01-02") { + DbCtx.LastPoolTime = msg.Date + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Db_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("pool rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + } + err = DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert pool table err", err.Error())) + } + + } else if DbCtx.Module == "gbt" { + curTableName := msg.MinerType + "_" + msg.Msg + last_blocks := GetLastBlocksFromTable(DbCtx, curTableName, "", "", "") + if last_blocks >= 0 { + last_blocks += 1 + UpdateBlocksToTable(DbCtx, curTableName, "", "", "", last_blocks) + } + last_reward, last_fee := GetLastRewardFromTable(DbCtx, curTableName, "", "", "") + if last_reward >= 0 { + last_reward += msg.Reward + last_fee += msg.Fee + UpdateRewardToTable(DbCtx, curTableName, last_reward, last_fee) + } + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_pool", "unkown msg "+msg.Msg)) + break + } + } +}*/ + +/*func do_handle_pool_stats(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.PoolStats_ch + switch msg.Msg { + case "pool_stats": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + tableName := msg.MinerType + "_" + msg.Msg + newTableName := msg.MinerType + "_" + msg.Msg + "_" + DbCtx.LastPoolStatsTime.Format("20060102") + + if msg.Date.Format("2006-01-02") != DbCtx.LastPoolStatsTime.Format("2006-01-02") { + DbCtx.LastPoolStatsTime = msg.Date + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Db_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("pool_stats rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + } + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert pool_stats table err", err.Error())) + } + + } else if DbCtx.Module == "gbt" { + } else if DbCtx.Module == "block" { + } + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_pool_stats", "unkown msg "+msg.Msg)) + break + } + } +}*/ + +func do_handle_pool_blkstats(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.PoolBlkStats_ch + switch msg.Msg { + case "pool_blkstats": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + tableName := msg.MinerType + "_" + msg.Msg + newTableName := msg.MinerType + "_" + msg.Msg + "_" + DbCtx.LastPoolBlkStatsTime.Format("20060102") + + if msg.Date.Format("2006-01-02") != DbCtx.LastPoolBlkStatsTime.Format("2006-01-02") { + DbCtx.LastPoolBlkStatsTime = msg.Date + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Db_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("pool_blkstats rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + } + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert pool_blkstats table err", err.Error())) + } + + } else if DbCtx.Module == "gbt" { + curTableName := msg.MinerType + "_" + msg.Msg + + if msg.Submit == "" { + updateSQL := fmt.Sprintf("UPDATE %s SET `success` = ?, reward = ?, fee = ? WHERE height = ? AND nonce = ?", curTableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Success, msg.Reward, msg.Fee, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update pool_blkstats table err", err.Error())) + //continue + } + } else { + updateSQL := fmt.Sprintf("UPDATE %s SET `submit` = ? WHERE height = ? AND nonce = ?", curTableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, msg.Submit, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update pool_blkstats table err", err.Error())) + //continue + } + } + + now := time.Now() + yesterday := now.AddDate(0, 0, -1) + yesterdayTableName := curTableName + "_" + yesterday.Format("20060102") + if CheckTableIsExist(DbCtx, yesterdayTableName) { + if msg.Submit == "" { + updateYesterdaySQL := fmt.Sprintf("UPDATE %s SET `success` = ?, reward = ?, fee = ? WHERE height = ? AND nonce = ?", yesterdayTableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateYesterdaySQL, msg.Success, msg.Reward, msg.Fee, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update pool_blkstats table err", err.Error())) + //continue + } + } else { + updateYesterdaySQL := fmt.Sprintf("UPDATE %s SET `submit` = ? WHERE height = ? AND nonce = ?", yesterdayTableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateYesterdaySQL, msg.Submit, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update pool_blkstats table err", err.Error())) + //continue + } + } + } + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_pool_blkstats", "unkown msg "+msg.Msg)) + break + } + } +} + +func do_handle_blk_detail(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.BlkDetail_ch + //msgs := <-DbCtx.BlkDetail_ch + //for _, msg := range msgs { + switch msg.Msg { + case "blk_detail": + ret := CheckSharesDbAlive(DbCtx) + if ret != 0 { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + tableName := msg.MinerType + "_" + msg.Msg + newTableName := msg.MinerType + "_block_detail" + "_" + fmt.Sprint(DbCtx.LastBlockDetailHeight) + "_" + fmt.Sprint(msg.Height-1) + + if DbCtx.LastBlockDetailHeight > 0 { + + if msg.Height-DbCtx.LastBlockDetailHeight > 100 { + var heightMsg BlkHeightDetail_db_msg + heightMsg.From = DbCtx.LastBlockDetailHeight + + DbCtx.LastBlockDetailHeight = msg.Height + log.Println("do_handle_blk_detail", tableName, newTableName) + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Shares_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("pool_detail rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + + heightMsg.Id = 0 + heightMsg.To = msg.Height + heightMsg.MinerType = msg.MinerType + heightMsg.Date = msg.Date + heightMsg.Msg = "blk_height_detail" + err = DbCtx.Shares_obj.InsertPoolDb(heightMsg.Msg, heightMsg.MinerType, heightMsg) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("insert pool_height_detail table err", err.Error())) + } + } + } + err := DbCtx.Shares_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("insert pool_detail table err", err.Error())) + } + } else if DbCtx.Module == "gbt" { + curTableName := msg.MinerType + "_" + msg.Msg + updateSQL := fmt.Sprintf("UPDATE %s SET `success` = ? WHERE height = ? AND nonce = ?", curTableName) + _, err := DbCtx.Shares_obj.UpdatePoolDb(updateSQL, msg.Success, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + from, to := CheckHeightRangeFromTable(DbCtx, msg.MinerType+"_"+"blk_height_detail", msg.Height) + if (from > 0) && (to > 0) { + oldTableName := curTableName + "_" + fmt.Sprint(from) + "_" + fmt.Sprint(to) + if CheckTableIsExist(DbCtx, oldTableName) { + updateOldSQL := fmt.Sprintf("UPDATE %s SET `success` = ? WHERE height = ? AND nonce = ?", oldTableName) + _, err := DbCtx.Shares_obj.UpdatePoolDb(updateOldSQL, msg.Success, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + } + } + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("do_handle_blk_detail", "unkown msg "+msg.Msg)) + break + } + //} + } +} + +func Save_blk_detail(DbCtx *DbContext, msg *BlkDetail_db_msg) { + switch msg.Msg { + case "blk_detail": + ret := CheckSharesDbAlive(DbCtx) + if ret != 0 { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + //continue + break + } + if DbCtx.Module == "server" { + tableName := msg.MinerType + "_" + msg.Msg + newTableName := msg.MinerType + "_block_detail" + "_" + fmt.Sprint(DbCtx.LastBlockDetailHeight) + "_" + fmt.Sprint(msg.Height-1) + + if DbCtx.LastBlockDetailHeight > 0 { + + if msg.Height-DbCtx.LastBlockDetailHeight > 100 { + var heightMsg BlkHeightDetail_db_msg + heightMsg.From = DbCtx.LastBlockDetailHeight + + DbCtx.LastBlockDetailHeight = msg.Height + log.Println("do_handle_blk_detail", tableName, newTableName) + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Shares_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("pool_detail rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + + heightMsg.Id = 0 + heightMsg.To = msg.Height + heightMsg.MinerType = msg.MinerType + heightMsg.Date = msg.Date + heightMsg.Msg = "blk_height_detail" + err = DbCtx.Shares_obj.InsertPoolDb(heightMsg.Msg, heightMsg.MinerType, heightMsg) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("insert pool_height_detail table err", err.Error())) + } + } + } + err := DbCtx.Shares_obj.InsertPoolDb(msg.Msg, msg.MinerType, *msg) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("insert pool_detail table err", err.Error())) + } + } else if DbCtx.Module == "gbt" { + curTableName := msg.MinerType + "_" + msg.Msg + updateSQL := fmt.Sprintf("UPDATE %s SET `success` = ? WHERE height = ? AND nonce = ?", curTableName) + _, err := DbCtx.Shares_obj.UpdatePoolDb(updateSQL, msg.Success, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + from, to := CheckHeightRangeFromTable(DbCtx, msg.MinerType+"_"+"blk_height_detail", msg.Height) + if (from > 0) && (to > 0) { + oldTableName := curTableName + "_" + fmt.Sprint(from) + "_" + fmt.Sprint(to) + if CheckTableIsExist(DbCtx, oldTableName) { + updateOldSQL := fmt.Sprintf("UPDATE %s SET `success` = ? WHERE height = ? AND nonce = ?", oldTableName) + _, err := DbCtx.Shares_obj.UpdatePoolDb(updateOldSQL, msg.Success, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + } + } + } else if DbCtx.Module == "block" { + } + + break + default: + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("save_blk_detail", "unkown msg "+msg.Msg)) + break + } +} + +func do_handle_blk_new(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.BlkNew_ch + switch msg.Msg { + case "blk_new": + ret := CheckSharesDbAlive(DbCtx) + if ret != 0 { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + /*tableName := msg.MinerType + "_" + msg.Msg + newTableName := msg.MinerType + "_" + msg.Msg + "_" + DbCtx.LastBlockNewTime.Format("20060102") + + if msg.Date.Format("2006-01-02") != DbCtx.LastBlockNewTime.Format("2006-01-02") { + DbCtx.LastBlockNewTime = msg.Date + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Shares_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("block_new rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + }*/ + /*err := DbCtx.Shares_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("insert pool_blknew table err", err.Error())) + }*/ + } else if DbCtx.Module == "gbt" { + /*tableName := msg.MinerType + "_" + msg.Msg + newTableName := msg.MinerType + "_" + msg.Msg + "_" + DbCtx.LastBlockNewTime.Format("20060102") + + if msg.Date.Format("2006-01-02") != DbCtx.LastBlockNewTime.Format("2006-01-02") { + DbCtx.LastBlockNewTime = msg.Date + renameTableSQL := fmt.Sprintf("RENAME TABLE %s TO %s", tableName, newTableName) + _, err := DbCtx.Shares_obj.Exec(renameTableSQL) + if err != nil { + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("block_new rename ", "failed"), zap.String("err ", err.Error())) + //continue + } + + CreateTable(DbCtx, msg.Msg, msg.MinerType) + }*/ + err := DbCtx.Shares_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("insert pool_blknew table err", err.Error())) + } + /*curTableName := msg.MinerType + "_" + msg.Msg + updateSQL := fmt.Sprintf("UPDATE %s SET `success` = ? WHERE height = ? AND nonce = ?", curTableName) + _, err := DbCtx.Shares_obj.UpdatePoolDb(updateSQL, msg.Success, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + } + + now := time.Now() + yesterday := now.AddDate(0, 0, -1) + yesterdayTableName := curTableName + "_" + yesterday.Format("20060102") + updateYesterdaySQL := fmt.Sprintf("UPDATE %s SET `success` = ? WHERE height = ? AND nonce = ?", yesterdayTableName) + _, err = DbCtx.Shares_obj.UpdatePoolDb(updateYesterdaySQL, msg.Success, msg.Height, msg.Nonce) + if err != nil { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("update users table err", err.Error())) + //continue + }*/ + } else if DbCtx.Module == "block" { + } else { + } + break + default: + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("do_handle_blk_new", "unkown msg "+msg.Msg)) + break + } + } +} + +func do_handle_address(DbCtx *DbContext) { + for { + if DbCtx.DbExit { + return + } + msg := <-DbCtx.Address_ch + switch msg.Msg { + case "address": + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + continue + } + if DbCtx.Module == "server" { + err := DbCtx.Db_obj.InsertPoolDb(msg.Msg, msg.MinerType, msg) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("insert address table err", err.Error())) + } + } else if DbCtx.Module == "gbt" { + + } else if DbCtx.Module == "block" { + } + break + default: + DbCtx.Db_obj.Logg.Error("[db]", zap.String("do_handle_address", "unkown msg "+msg.Msg)) + break + } + } +} + +func GetAddressFromTable(DbCtx *DbContext) []string { + var addresses []string + + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + return addresses + } + query := "SELECT addr, alias, valid FROM " + DbCtx.Coin + "_address" + rows, err := DbCtx.Db_obj.Query(query) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("query address from Pool db ", err.Error())) + return addresses + } + defer rows.Close() + + for rows.Next() { + var addr string + var alias string + var valid int = 0 + // 将每一行的字段值扫描到结构体中 + err := rows.Scan(&addr, &alias, &valid) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("scan address from Pool db ", err.Error())) + continue + } + + hash := md5.Sum([]byte(addr + "m2pool_alias")) + hashString := hex.EncodeToString(hash[:]) + if hashString == alias { + addresses = append(addresses, addr) + } + } + return addresses +} + +/*func UpdateBlocksToTable(DbCtx *DbContext, tableName string, user string, miner string, minerid string, update_blocks int64) { + if len(miner) > 0 { + updateSQL := fmt.Sprintf("UPDATE %s SET `blocks` = ? WHERE user = ? AND miner = ? AND refindex = ?", tableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, update_blocks, user, miner, minerid) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update table err", tableName+" "+err.Error())) + //continue + } + } else if len(user) > 0 { + updateSQL := fmt.Sprintf("UPDATE %s SET `blocks` = ? WHERE user = ?", tableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, update_blocks, user) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update table err", tableName+" "+err.Error())) + //continue + } + } else { + updateSQL := fmt.Sprintf("UPDATE %s SET `blocks` = ?", tableName) + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, update_blocks) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update table err", tableName+" "+err.Error())) + //continue + } + } +}*/ + +/*func GetLastBlocksFromTable(DbCtx *DbContext, tableName string, user string, miner string, minerid string) int64 { + var last_blocks int64 = -1 + query := fmt.Sprintf("SELECT blocks FROM %s", tableName) + if len(miner) > 0 { + query = fmt.Sprintf("SELECT blocks FROM %s WHERE user = '%s' AND miner = '%s' AND refindex = '%s'", tableName, user, miner, minerid) + } else if len(user) > 0 { + query = fmt.Sprintf("SELECT blocks FROM %s WHERE user = '%s'", tableName, user) + } else { + } + err := DbCtx.Db_obj.QueryRow(query).Scan(&last_blocks) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("get blocks failed:", tableName), zap.String("err", err.Error())) + } + + return last_blocks +}*/ +/* +func UpdateRewardToTable(DbCtx *DbContext, tableName string, reward float64, fee float64) { + updateSQL := fmt.Sprintf("UPDATE %s SET `reward` = ?, `fee` = ?", tableName) + + _, err := DbCtx.Db_obj.UpdatePoolDb(updateSQL, reward, fee) + if err != nil { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("update table err", tableName+" "+err.Error())) + } +}*/ +/* +func GetLastRewardFromTable(DbCtx *DbContext, tableName string, user string, miner string, minerid string) (float64, float64) { + var last_reward float64 = -1 + var last_fee float64 = -1 + query := fmt.Sprintf("SELECT reward,fee FROM %s", tableName) + err := DbCtx.Db_obj.QueryRow(query).Scan(&last_reward, &last_fee) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("get blocks failed:", tableName), zap.String("err", err.Error())) + } + + return last_reward, last_fee +}*/ + +func GetLastTimeFromTable(DbCtx *DbContext, tableName string) time.Time { + var last_time time.Time + + if !CheckTableIsExist(DbCtx, tableName) { + last_time = time.Now() + return last_time + } + + var last_time_str sql.NullString + + query := fmt.Sprintf("SELECT DATE_FORMAT(date, '%%Y-%%m-%%d %%H:%%i:%%S') AS last_time FROM %s ORDER BY id DESC LIMIT 1", tableName) + + var err error + if strings.Contains(tableName, "blk_new") || strings.Contains(tableName, "blk_detail") || strings.Contains(tableName, "blk_height_detail") || strings.Contains(tableName, "block_detail") { + err = DbCtx.Shares_obj.QueryRow(query).Scan(&last_time_str) + if err != nil { + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("get failed:", tableName), zap.String("err", err.Error())) + last_time = time.Now() + } + } else { + err = DbCtx.Db_obj.QueryRow(query).Scan(&last_time_str) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("get failed:", tableName), zap.String("err", err.Error())) + last_time = time.Now() + } + } + + if last_time_str.Valid { + last_time, err = time.Parse("2006-01-02 15:04:05", last_time_str.String) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("parse datetime error", err.Error())) + last_time = time.Now() + } + } + + return last_time +} + +/*func GetLastTimeFromTable(DbCtx *DbContext, tableName string) time.Time { + var last_time time.Time + var last_time_str sql.NullString + read_ok := false + query := fmt.Sprintf("SELECT DATE_FORMAT(date, '%Y-%m-%d %H:%i:%s') FROM %s ORDER BY id DESC LIMIT 1", tableName) + if strings.Contains(tableName, "blk_new") || strings.Contains(tableName, "blk_detail") { + err := DbCtx.Shares_obj.QueryRow(query).Scan(&last_time_str) + if err != nil { + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("get failed:", tableName), zap.String("err ", err.Error())) + last_time = time.Now() + } + } else { + err := DbCtx.Db_obj.QueryRow(query).Scan(&last_time_str) + if err != nil { + DbCtx.Db_obj.Logg.Warn("[db]", zap.String("get failed:", tableName), zap.String("err ", err.Error())) + last_time = time.Now() + } + } + if read_ok { + mysqlDateTimeFormat := "2006-01-02 15:04:05" + last_time, _ = time.Parse(mysqlDateTimeFormat, datetimeStr) + + } + return last_time +}*/ + +func GetLastHeightFromTable(DbCtx *DbContext, tableName string) int64 { + var last_height int64 + query := fmt.Sprintf("SELECT height FROM %s ORDER BY id DESC LIMIT 1", tableName) + err := DbCtx.Shares_obj.QueryRow(query).Scan(&last_height) + if err != nil { + DbCtx.Shares_obj.Logg.Warn("[db]", zap.String("get failed:", tableName), zap.String("err ", err.Error())) + last_height = -1 + } + return last_height +} + +func InitDbData(DbCtx *DbContext, Module string) { + ret := CheckPoolDbAlive(DbCtx) + if ret != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + } + ret = CheckSharesDbAlive(DbCtx) + if ret != 0 { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("Pool db ", "disconnected")) + } + if Module == "server" { + DbCtx.LastMinersTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"miners") + DbCtx.LastMinersStatsTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"miners_stats") + //DbCtx.LastMinerTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"miner") + /*DbCtx.LastUsersTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"users") + DbCtx.LastUsersStatsTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"users_stats") + DbCtx.LastUsersBlkStatsTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"users_blkstats") + DbCtx.LastPoolTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"pool") + DbCtx.LastPoolStatsTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"pool_stats")*/ + DbCtx.LastPoolBlkStatsTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"pool_blkstats") + DbCtx.LastBlockDetailHeight = GetLastHeightFromTable(DbCtx, DbCtx.Coin+"_"+"blk_detail") + DbCtx.LastBlockNewTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"blk_new") + DbCtx.LastAddressTime = GetLastTimeFromTable(DbCtx, DbCtx.Coin+"_"+"address") + } +} + +func InitDb(Coin string, Module string) *DbContext { + DbCtx.AppExit = make(chan bool, 256) + + DbCtx.Miners_ch = make(chan []Miners_db_msg, 32768) + DbCtx.MinersStats_ch = make(chan []MinersStats_db_msg, 32768) + /*DbCtx.Miner_ch = make(chan Miner_db_msg, 32768) + + DbCtx.Users_ch = make(chan Users_db_msg, 32768) + DbCtx.UsersStats_ch = make(chan UsersStats_db_msg, 32768) + DbCtx.UsersBlkStats_ch = make(chan UsersBlkStats_db_msg, 32768) + + DbCtx.Pool_ch = make(chan Pool_db_msg, 32768) + DbCtx.PoolStats_ch = make(chan PoolStats_db_msg, 32768)*/ + DbCtx.PoolBlkStats_ch = make(chan PoolBlkStats_db_msg, 32768) + + DbCtx.BlkDetail_ch = make(chan BlkDetail_db_msg, 32768) + DbCtx.BlkNew_ch = make(chan BlkNew_db_msg, 32768) + + DbCtx.Address_ch = make(chan Address_db_msg, 16) + + DbCtx.Module = Module + DbCtx.Coin = Coin + + InitConfig(&(DbCtx.DbCfg)) + l, r, e := utility.InitLogg(&(DbCtx.DbCfg.Zaplog), &(DbCtx.DbCfg.Logrotae), Coin, "db") + if e != nil { + log.Fatalln("[db]", e) + return nil + } + DbCtx.LogR = r + + var result int = 0 + result, err := createdb(&DbCtx) + if result != 0 || err != nil { + DbCtx.Db_obj.Logg.Info("[db]", zap.String("create db failed: ", err.Error())) + return nil + } + + DbCtx.Db_obj.Logg = l + DbCtx.Shares_obj.Logg = l + + InitDbData(&DbCtx, Module) + + go do_handle_miners(&DbCtx) + go do_handle_miners_stats(&DbCtx) + /*go do_handle_miner(&DbCtx) + go do_handle_users(&DbCtx) + go do_handle_users_stats(&DbCtx) + go do_handle_users_blkstats(&DbCtx) + go do_handle_pool(&DbCtx) + go do_handle_pool_stats(&DbCtx)*/ + go do_handle_pool_blkstats(&DbCtx) + go do_handle_blk_detail(&DbCtx) + go do_handle_blk_new(&DbCtx) + go do_handle_address(&DbCtx) + + if Module == "server" { + } else if Module == "block" { + } else if Module == "gbt" { + } else if Module == "job" { + } else { + } + + return &DbCtx +} + +func StopDb(coin string, App string) { + DbCtx.DbExit = true + defer close(DbCtx.Miners_ch) + /*defer close(DbCtx.MinersStats_ch) + defer close(DbCtx.Miner_ch) + defer close(DbCtx.Users_ch) + defer close(DbCtx.UsersStats_ch) + defer close(DbCtx.UsersBlkStats_ch) + defer close(DbCtx.Pool_ch) + defer close(DbCtx.PoolStats_ch)*/ + defer close(DbCtx.PoolBlkStats_ch) + defer close(DbCtx.BlkDetail_ch) + defer close(DbCtx.BlkNew_ch) + defer close(DbCtx.Address_ch) + defer DbCtx.Db_obj.Logg.Sync() + DbCtx.Db_obj.ClosePoolDb() + DbCtx.Shares_obj.ClosePoolDb() +} + +func (this *PoolDb) PingPoolDb(DbCtx *DbContext) int { + for i := 0; i < 3; i++ { + err := this.Ping() + if err != nil { + if DbCtx.DbExit { + return -1 + } + time.Sleep(200 * time.Millisecond) + continue + } + return 0 + } + return -1 +} + +func CheckPoolDbAlive(DbCtx *DbContext) int { + //ping + ret := DbCtx.Db_obj.PingPoolDb(DbCtx) + if ret != 0 { + backup_l := DbCtx.Db_obj.Logg + DbCtx.Db_obj.ClosePoolDb() + //reconnect + db_obj, err := OpenPoolDb("mysql", dbconnstr) + if err != nil { + backup_l.Info("[db]", zap.String("reconnect db err", err.Error())) + //log.Println("[db]reconnect db err", err.Error()) + return -1 + } + DbCtx.Db_obj = db_obj + DbCtx.Db_obj.Logg = backup_l + + //ping + if DbCtx.Db_obj.PingPoolDb(DbCtx) != 0 { + DbCtx.Db_obj.Logg.Error("[db]", zap.String("reconnect ping db", "failed")) + DbCtx.Db_obj.ClosePoolDb() + return -1 + } + DbCtx.Db_obj.Logg.Info("[db]", zap.String("reconnect db sucess", dbconnstr)) + } + return 0 +} + +func CheckSharesDbAlive(DbCtx *DbContext) int { + //ping + ret := DbCtx.Shares_obj.PingPoolDb(DbCtx) + if ret != 0 { + backup_l := DbCtx.Shares_obj.Logg + DbCtx.Shares_obj.ClosePoolDb() + //reconnect + db_obj, err := OpenPoolDb("mysql", sharesdbconnstr) + if err != nil { + backup_l.Info("[db]", zap.String("reconnect db err", err.Error())) + //log.Println("[db]reconnect db err", err.Error()) + return -1 + } + DbCtx.Shares_obj = db_obj + DbCtx.Shares_obj.Logg = backup_l + + //ping + if DbCtx.Shares_obj.PingPoolDb(DbCtx) != 0 { + DbCtx.Shares_obj.Logg.Error("[db]", zap.String("reconnect ping db", "failed")) + DbCtx.Shares_obj.ClosePoolDb() + return -1 + } + DbCtx.Shares_obj.Logg.Info("[db]", zap.String("reconnect db sucess", sharesdbconnstr)) + } + return 0 +} + +func CheckUserIsPermitted(User string, Coin string) bool { + //DbCtx.Db_obj.Logg.Info("[db]", zap.Any("CheckUserIsPermitted", User)) + //return true + + //url := "https://test.m2pool.com/api/pool/checkAccount" + url := "https://m2pool.com/api/pool/checkAccount" + data := map[string]string{ + "coin": Coin, + "ma": User, + } + //log.Println("CheckUserIsPermitted user =", User, data) + jsonData, err := json.Marshal(data) + if err != nil { + log.Println("Error marshalling JSON:", err) + return false + } + + tr := &http.Transport{ + TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, + } + client := &http.Client{Transport: tr} + + resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + log.Println("Error making POST request:", err) + return false + } + + defer resp.Body.Close() + + if resp.StatusCode == http.StatusOK { + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + log.Println("Error reading response body:", err) + return false + } + log.Println("CheckUserIsPermitted", string(body)) + if string(body) == "true" { + return true + } + } + + return false +} diff --git a/internal/gbt/coin/coin.go b/internal/gbt/coin/coin.go new file mode 100644 index 0000000..5d09557 --- /dev/null +++ b/internal/gbt/coin/coin.go @@ -0,0 +1,85 @@ +// coin.go +package coin + +import ( + "pool/internal/db" + monero_rpc "pool/internal/gbt/monero/rpc" + "pool/internal/gbt/tari" + "pool/internal/utility" + + "github.com/btcsuite/btcd/rpcclient" + "github.com/redis/go-redis/v9" + "github.com/zeromq/goczmq" + "go.uber.org/zap" + "gopkg.in/natefinch/lumberjack.v2" +) + +type RpcConfig struct { + Host string `json:"host"` + Testnet string `json:"testnet"` + Type string `json:"type"` + User string `json:"user"` + Pass string `json:"pass"` + ZmqSub string `json:"zmqsub"` + Timeout int `json:"timeout"` +} + +type ZmqConfig struct { + Pub string `json:"pub"` + Sub string `json:"sub"` +} + +type ProfitConfig struct { + Push string `json:"push"` +} + +type GbtConfig struct { + Rpc RpcConfig `json:"rpc"` + Zmq ZmqConfig `json:"zmq"` + Redis utility.RedisConfig `json:"redis"` + Profit ProfitConfig `json:"profit"` + Zaplog zap.Config `json:"zap"` + Logrotae utility.LogRotateConfig `json:"logrotate"` +} + +type GbtContext struct { + DbCtx *db.DbContext + + NodeSubCh *goczmq.Sock + + PubCh *goczmq.Sock + SubCh *goczmq.Sock + MoneroNewBlockPubCh *goczmq.Sock // monero gbt有新块产生时发送消息队列 + MoneroNewBlockSubCh *goczmq.Sock // 模仿自带zmq通知的币 + PushCh *goczmq.Sock + + Started bool + Config GbtConfig + Client *rpcclient.Client + MoneroClinet *monero_rpc.HttpClient + TariClient *tari.BaseNodeClient + MoneroAddr string // monero报块地址 + TariAddr string // tari报块地址 + ExitNotifyChan chan bool + ExitGbtChan chan bool + ExitBlockChan chan bool + + //AlivingChan chan bool + FlagAliving int32 + FlagAlivingExit int32 + + Log *zap.Logger + LogR *lumberjack.Logger + + RedisClient *redis.Client + + Coin string + + MinerAddrs []string + MinerAddrIndex int + + /*Blocks int64 + + Reward float64 + Fee float64*/ +} diff --git a/internal/gbt/dbif/dbif.go b/internal/gbt/dbif/dbif.go new file mode 100644 index 0000000..d8f58d3 --- /dev/null +++ b/internal/gbt/dbif/dbif.go @@ -0,0 +1,198 @@ +// dbif.go +package dbif + +import ( + "pool/internal/db" + "pool/internal/gbt/coin" + "time" +) + +func NotifyBlkDetailSuccess(gbt *coin.GbtContext, height int64, hash string, nonce string, subidx int64) { + var msg db.BlkDetail_db_msg + msg.Id = 0 + msg.Msg = "blk_detail" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.Height = height + msg.Hash = hash + msg.Success = 1 + msg.Nonce = nonce + msg.SubIdx = subidx + + //gbt.DbCtx.BlkDetail_ch <- msg + db.Save_blk_detail(gbt.DbCtx, &msg) +} + +/*func NotifyMinerSuccess(gbt *coin.GbtContext, user string, miner string, minerid string, height int64, hash string, nonce string, subidx int64, reward float64, fee float64) { + var msg db.Miner_db_msg + msg.Id = 0 + msg.Msg = "miner" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.User = user + msg.Miner = miner + msg.Index = minerid + + msg.Height = height + msg.Hash = hash + msg.Success = 1 + msg.Nonce = nonce + msg.SubIdx = subidx + + msg.Reward = reward + msg.Fee = fee + + gbt.DbCtx.Miner_ch <- msg +}*/ + +/*func NotifyUsersBlkStatsSuccess(gbt *coin.GbtContext, user string, height int64, hash string, nonce string, subidx int64, reward float64, fee float64) { + var msg db.UsersBlkStats_db_msg + msg.Id = 0 + msg.Msg = "users_blkstats" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.User = user + + msg.Height = height + msg.Hash = hash + msg.Success = 1 + msg.Nonce = nonce + msg.SubIdx = subidx + + msg.Reward = reward + msg.Fee = fee + + gbt.DbCtx.UsersBlkStats_ch <- msg +}*/ + +func NotifyPoolBlkStatsSuccess(gbt *coin.GbtContext, height int64, hash string, nonce string, subidx int64, reward float64, fee float64) { + var msg db.PoolBlkStats_db_msg + msg.Id = 0 + msg.Msg = "pool_blkstats" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.Height = height + msg.Hash = hash + msg.Success = 1 + msg.Nonce = nonce + msg.SubIdx = subidx + msg.Submit = "" + + msg.Reward = reward + msg.Fee = fee + + gbt.DbCtx.PoolBlkStats_ch <- msg +} + +/*func NotifyMinerSubmitResult(gbt *coin.GbtContext, user string, miner string, minerid string, height int64, hash string, result string, nonce string, subidx int64) { + var msg db.Miner_db_msg + msg.Id = 0 + msg.Msg = "miner" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.User = user + msg.Miner = miner + msg.Index = minerid + + msg.Height = height + msg.Hash = hash + msg.Submit = result + msg.Nonce = nonce + msg.SubIdx = subidx + + gbt.DbCtx.Miner_ch <- msg +}*/ + +/*func NotifyUsersBlkStatsSubmitResult(gbt *coin.GbtContext, user string, height int64, hash string, result string, nonce string, subidx int64) { + var msg db.UsersBlkStats_db_msg + msg.Id = 0 + msg.Msg = "users_blkstats" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.User = user + + msg.Height = height + msg.Hash = hash + msg.Submit = result + msg.Nonce = nonce + msg.SubIdx = subidx + + gbt.DbCtx.UsersBlkStats_ch <- msg +}*/ + +func NotifyPoolBlkStatsSubmitResult(gbt *coin.GbtContext, height int64, hash string, result string, nonce string, subidx int64) { + var msg db.PoolBlkStats_db_msg + msg.Id = 0 + msg.Msg = "pool_blkstats" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.Height = height + msg.Hash = hash + msg.Submit = result + msg.Nonce = nonce + msg.SubIdx = subidx + + gbt.DbCtx.PoolBlkStats_ch <- msg +} + +func NotifyBlkNewDb(gbt *coin.GbtContext, height int64, hash string, success bool, nonce string, subidx int64) { + var msg db.BlkNew_db_msg + msg.Id = 0 + msg.Msg = "blk_new" + msg.Date = time.Now() + msg.MinerType = gbt.Coin + + msg.Height = height + msg.Hash = hash + if success { + msg.Success = 1 + } else { + msg.Success = 0 + } + msg.Nonce = nonce + msg.SubIdx = subidx + + gbt.DbCtx.BlkNew_ch <- msg +} + +/*func NotifyBlockStat(gbt *coin.GbtContext, user string, miner string, minerid string, reward float64, fee float64) { + var miners_msg db.Miners_db_msg + miners_msg.Id = 0 + miners_msg.Msg = "miners" + miners_msg.Date = time.Now() + miners_msg.MinerType = gbt.Coin + + miners_msg.User = user + miners_msg.Miner = miner + miners_msg.Index = minerid + + gbt.DbCtx.Miners_ch <- miners_msg + + var users_msg db.Users_db_msg + users_msg.Id = 0 + users_msg.Msg = "users" + users_msg.Date = time.Now() + users_msg.MinerType = gbt.Coin + + users_msg.User = user + + gbt.DbCtx.Users_ch <- users_msg + + var pool_msg db.Pool_db_msg + pool_msg.Id = 0 + pool_msg.Msg = "pool" + pool_msg.Date = time.Now() + pool_msg.MinerType = gbt.Coin + + pool_msg.Reward = reward + pool_msg.Fee = fee + + gbt.DbCtx.Pool_ch <- pool_msg +}*/ diff --git a/internal/gbt/gbt.go b/internal/gbt/gbt.go new file mode 100644 index 0000000..2932e69 --- /dev/null +++ b/internal/gbt/gbt.go @@ -0,0 +1,300 @@ +// gbt.go +package gbt + +import ( + "encoding/json" + "fmt" + "log" + + "io/ioutil" + "pool/internal/db" + "sync/atomic" + + //"pool/internal/cache" + "pool/internal/gbt/coin" + monero_rpc "pool/internal/gbt/monero/rpc" + "pool/internal/gbt/tari" + "pool/internal/gbt/tari/sha3x" + "pool/internal/utility" + + "os" + "os/signal" + "syscall" + + "time" + + "github.com/btcsuite/btcd/rpcclient" + "github.com/redis/go-redis/v9" + "go.uber.org/zap" +) + +var logg *zap.Logger +var GbtCtx coin.GbtContext + +func InitConfig(config *coin.GbtConfig) { + data, err := ioutil.ReadFile("gbt.conf") + if err != nil { + panic(err.Error()) + } + if err = json.Unmarshal(data, &config); err != nil { + panic(err.Error()) + } +} + +func InitClient(gbt *coin.GbtContext) error { + fmt.Println(gbt.Coin) + switch gbt.Coin { + case "monero": + url := "http://" + gbt.Config.Rpc.Host + 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" { + config.Host = gbt.Config.Rpc.Testnet + } else { + config.Host = gbt.Config.Rpc.Host + } + config.User = gbt.Config.Rpc.User + config.Pass = gbt.Config.Rpc.Pass + config.HTTPPostMode = true + config.DisableTLS = true + client, err := rpcclient.New(&config, nil) + if err != nil { + logg.Info("[gbt]", zap.String("rpcclient new ", err.Error())) + return err + } + gbt.Client = client + blockCount, err := client.GetBlockCount() + if err != nil { + logg.Info("[gbt]", zap.String("GetBlockCount ", err.Error())) + return err + } + logg.Info("[gbt]", zap.Int64("Block count ", blockCount)) + + } + return nil +} + +/*func GbtLivingHandler(gbt *coin.GbtContext) { + timer := time.NewTimer(time.Duration(600) * time.Second) + for { + select { + case aliving := <-gbt.AlivingChan: + if !aliving { + timer.Stop() + //log.Println("gbt aliving", aliving) + return + } else { + timer.Reset(time.Duration(600) * time.Second) + } + case <-time.After(time.Duration(600) * time.Second): + gbt.ExitGbtChan <- true + + return + } + } +}*/ + +func GbtLivingHandler(gbt *coin.GbtContext) { + var to_cnt int = 0 + for { + flagAliving := atomic.LoadInt32(&(gbt.FlagAliving)) + flagExit := atomic.LoadInt32(&(gbt.FlagAlivingExit)) + + if flagExit == 1 { + logg.Error("[server]", zap.String("GbtLivingHandler exited", "exit")) + break + } + + if flagAliving == 0 { + //if to_cnt > 240 { + if to_cnt > gbt.Config.Rpc.Timeout*3/1000 { + logg.Error("[server]", zap.String("GbtLivingHandler exited", "timer expired")) + cmd := "killall gbt_" + gbt.Coin + " &" + utility.ExecShellCmd(cmd) + gbt.ExitGbtChan <- true + break + } + to_cnt++ + } else { + to_cnt = 0 + atomic.StoreInt32(&(gbt.FlagAliving), 0) + } + + time.Sleep(time.Second) + } +} + +type coinobj struct { + Coin string + Init func(GbtCtx *coin.GbtContext, DbCtx *db.DbContext) + Start func() + Stop func() +} + +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}, +} + +func register_signal(dbctx *db.DbContext) { + signal_ch := make(chan os.Signal, 1) + signal.Notify(signal_ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) + go signal_handle(signal_ch, dbctx) +} + +func signal_handle(signal_ch chan os.Signal, dbctx *db.DbContext) { + for s := range signal_ch { + switch s { + case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT: + log.Println("stop!") + dbctx.AppExit <- true + default: + //fmt.Println("other signal", s) + } + } +} + +/*func LoadCache(gbt *coin.GbtContext) { + val := cache.LoadPoolCache(gbt.RedisClient, gbt.Coin, "blocks") + if val != nil { + if intVal, ok := val.(int64); ok { + gbt.Blocks = intVal + } + } + + val_f := cache.LoadPoolCache(gbt.RedisClient, gbt.Coin, "rewards") + if val_f != nil { + if fVal, ok := val_f.(float64); ok { + gbt.Reward = fVal + } + } + + val_f = cache.LoadPoolCache(gbt.RedisClient, gbt.Coin, "fee") + if val_f != nil { + if fVal, ok := val_f.(float64); ok { + gbt.Fee = fVal + } + } +}*/ + +func Start(Coin string, DbCtx *db.DbContext) { + GbtCtx.DbCtx = DbCtx + + GbtCtx.Coin = Coin + + atomic.StoreInt32(&(GbtCtx.FlagAliving), 0) + atomic.StoreInt32(&(GbtCtx.FlagAlivingExit), 0) + + InitConfig(&GbtCtx.Config) + l, lr, err := utility.InitLogg(&(GbtCtx.Config.Zaplog), &(GbtCtx.Config.Logrotae), Coin, "gbt") + logg = l + + //defer logg.Sync() + + GbtCtx.Log = l + GbtCtx.LogR = lr + + GbtCtx.RedisClient = redis.NewClient(&redis.Options{ + Addr: GbtCtx.Config.Redis.Addr, + Password: GbtCtx.Config.Redis.Password, + DB: GbtCtx.Config.Redis.DB, + }) + + register_signal(DbCtx) + + GbtCtx.PubCh = utility.InitZmqPub(GbtCtx.Config.Zmq.Pub) + + GbtCtx.SubCh = utility.InitZmqSub(GbtCtx.Config.Zmq.Sub, "blk"+Coin) + + GbtCtx.MoneroNewBlockPubCh = utility.InitZmqPub(GbtCtx.Config.Rpc.ZmqSub) + GbtCtx.MoneroNewBlockSubCh = utility.InitZmqSub(GbtCtx.Config.Rpc.ZmqSub, "hashblock") + //GbtCtx.PushCh = utility.InitZmqPush(GbtCtx.Config.Profit.Push) + + for { + err = InitClient(&GbtCtx) + if err != nil { + logg.Error("[gbt]", zap.String("InitClient", err.Error())) + time.Sleep(time.Duration(5) * time.Second) + continue + } + break + } + + if len(GbtCtx.Config.Rpc.ZmqSub) > 0 { + GbtCtx.NodeSubCh = utility.InitZmqSub(GbtCtx.Config.Rpc.ZmqSub, utility.BITCOIND_ZMQ_HASHBLOCK) + } + + GbtCtx.Started = true + + GbtCtx.ExitGbtChan = make(chan bool, 256) + + //GbtCtx.AlivingChan = make(chan bool, 256) + + GbtCtx.MinerAddrs = db.GetAddressFromTable(DbCtx) + GbtCtx.MinerAddrIndex = 0 + + //LoadCache(&GbtCtx) + + for _, coinobj := range coinobjs { + if coinobj.Coin == Coin { + coinobj.Init(&GbtCtx, DbCtx) + go coinobj.Start() + break + } + } + + go GbtLivingHandler(&GbtCtx) + + <-DbCtx.AppExit +} + +func Stop(Coin string) { + + GbtCtx.Started = false + + GbtCtx.ExitGbtChan <- true + + //GbtCtx.AlivingChan <- false + atomic.StoreInt32(&(GbtCtx.FlagAlivingExit), 1) + + for _, coinobj := range coinobjs { + if coinobj.Coin == Coin { + coinobj.Stop() + break + } + } + + //time.Sleep(1 * time.Second) + + defer close(GbtCtx.ExitGbtChan) + + //defer close(GbtCtx.AlivingChan) + + if GbtCtx.NodeSubCh != nil { + defer GbtCtx.NodeSubCh.Destroy() + } + if GbtCtx.PubCh != nil { + defer GbtCtx.PubCh.Destroy() + } + if GbtCtx.SubCh != nil { + defer GbtCtx.SubCh.Destroy() + } + /*if GbtCtx.PushCh != nil { + defer GbtCtx.PushCh.Destroy() + }*/ + defer GbtCtx.RedisClient.Close() + defer logg.Sync() +} diff --git a/internal/gbt/monero/monore.go b/internal/gbt/monero/monore.go new file mode 100644 index 0000000..478390b --- /dev/null +++ b/internal/gbt/monero/monore.go @@ -0,0 +1,495 @@ +package monero + +import ( + "crypto/rand" + "database/sql" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "math" + "pool/internal/db" + "pool/internal/gbt/coin" + "pool/internal/gbt/dbif" + "pool/internal/msg" + "pool/internal/utility" + "sync/atomic" + "time" + + "go.uber.org/zap" +) + +const GBT_MONERO_VERSION string = "monero v1.0" + +type MoneroAddrConfig struct { + Addr string `json:"addr"` +} + +type MoneroConfig struct { + Monero MoneroAddrConfig `json:"nexa"` +} + +type GetBlockTemplateResponse struct { + ID string `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result msg.MoneroStratumJob `json:"result"` + Error *RpcError `json:"error,omitempty"` +} + +type RpcError struct { + Code int `json:"code"` + Message string `json:"message"` +} + +// RPCError 用于描述 RPC 返回的错误 +type RPCError struct { + Code int `json:"code"` + Message string `json:"message"` +} + +// 通用 RPC 响应结构 +type MoneroRPCResponse[T any] struct { + ID string `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result *T `json:"result,omitempty"` // 成功时使用 + Error *RPCError `json:"error,omitempty"` // 失败时使用 +} +type SubmitSuccess struct { + BlockId string `json:"block_id"` + Status string `json:"status"` + Untrusted bool `json:"untrusted"` +} +type GbtMoneroContext struct { + Config MoneroConfig + GbtCtx *coin.GbtContext + + last_time time.Time + last_gbt msg.MoneroStratumJob + last_blockhash string + + last_height uint32 + + Submits float64 + + addressIndex int + + Target []byte + Header []byte + last_body string + + new_block_chan chan int + new_block_index int +} + +var logg *zap.Logger +var GbtMoneroCtx GbtMoneroContext + +func configInit(config *MoneroConfig) { + 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) { + GbtMoneroCtx.GbtCtx = GbtCtx + + GbtMoneroCtx.last_height = 0 + + configInit(&GbtMoneroCtx.Config) + + GbtMoneroCtx.Target = make([]byte, 32) + GbtMoneroCtx.Header = make([]byte, 49) + GbtMoneroCtx.last_time = time.Now() + logg = GbtCtx.Log + GbtMoneroCtx.new_block_chan = make(chan int, 256) + GbtMoneroCtx.new_block_index = 0 + logg.Info("[gbt]", zap.String("gbt_monero_version", GBT_MONERO_VERSION)) + +} + +func Start() { + go gbt_running(&GbtMoneroCtx) + go gbt_notify_running(&GbtMoneroCtx) + go submit_block_running(&GbtMoneroCtx) +} + +func Stop() { + defer close(GbtMoneroCtx.new_block_chan) +} + +type BlockCheckData struct { + Height int + Nonce string + User string + Miner string + MinerId string + Hash string + SubIdx int +} +type GetBlockHeaderResp struct { + Id string `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Error any `json:"error"` + Result GetBlockHeaderMsg `json:"result"` +} + +type GetBlockHeaderMsg struct { + Result struct { + BlockHeader struct { + Nonce uint64 `json:"nonce"` + PowHash string `json:"pow_hash"` + Reward uint64 `json:"reward"` + } `json:"block_header"` + Status string `json:"status"` + Untrusted bool `json:"untrusted"` + } `json:"result"` +} + +func update_block_confirm(gbt *GbtMoneroContext) { + db, err := sql.Open("sqlite3", "./blocks.db") + if err != nil { + //log.Printf("Error opening database: %v", err) + logg.Error("[gbt]", zap.String("Error opening database", err.Error())) + return + } + defer db.Close() + + query := "SELECT user,miner,minerid,height,nonce,hash,subidx FROM blocks WHERE checked=0 AND created_at >= datetime('now', '-30 minutes') order by id desc limit 2" + rows, err := db.Query(query) + if err != nil { + //log.Printf("Error executing query from blocks: %v", err) + logg.Error("[gbt]", zap.String("Error executing query from blocks:", err.Error())) + return + } + defer rows.Close() + + var blocks []BlockCheckData + for rows.Next() { + var height int + var nonce string + var user string + var miner string + var minerid string + var hash string + var subidx int + if err := rows.Scan(&user, &miner, &minerid, &height, &nonce, &hash, &subidx); err != nil { + //log.Printf("Error scanning row in blocks: %v", err) + logg.Error("[gbt]", zap.String("Error scanning row in blocks:", err.Error())) + return + } + var blockdata BlockCheckData + blockdata.Height = height + blockdata.Nonce = nonce + blockdata.User = user + blockdata.Miner = miner + blockdata.MinerId = minerid + blockdata.Hash = hash + blockdata.SubIdx = subidx + + blocks = append(blocks, blockdata) + //fmt.Printf("blocks - Height: %d, Nonce: %d\n", height, nonce) + //log.Printf("update block height %d nonce %s, subidx %d, user %s", height, nonce, subidx, user+"."+miner+"_"+minerid) + } + for _, block := range blocks { + var blockHeaderResp GetBlockHeaderResp + resp, err := gbt.GbtCtx.MoneroClinet.GetBlockByHash(block.Hash) + err = json.Unmarshal(resp, &blockHeaderResp) + if err != nil { + logg.Error("[gbt]", zap.String("getblockheader Unmarshal ", fmt.Sprint(block.Height)+" "+err.Error())) + continue + } + if blockHeaderResp.Error != nil { + fmt.Println("[check block]:", blockHeaderResp.Error) + update_sql := `UPDATE blocks SET checked = 2 WHERE height = ? AND nonce = ? AND checked = 0` + _, err = db.Exec(update_sql, block.Height, block.Nonce) + if err != nil { + //log.Printf("Error updating blk_new: %v", err) + logg.Error("[gbt]", zap.String("Error updating blk_new:", err.Error())) + } + return + } + blockHeader := blockHeaderResp.Result + + block_height := int64(block.Height) + // nonceHex := fmt.Sprintf("%x", block.Nonce) + dbif.NotifyPoolBlkStatsSuccess(gbt.GbtCtx, block_height, "", block.Nonce, int64(block.SubIdx), float64(blockHeader.Result.BlockHeader.Reward)/math.Pow(10, 12), 0) + dbif.NotifyBlkDetailSuccess(gbt.GbtCtx, block_height, "", block.Nonce, int64(block.SubIdx)) + dbif.NotifyBlkNewDb(gbt.GbtCtx, block_height, block.Hash, true, block.Nonce, int64(block.SubIdx)) + + updateSQL := `UPDATE blocks SET checked = 1 WHERE height = ? AND nonce = ? AND checked = 0` + _, err = db.Exec(updateSQL, block.Height, block.Nonce) + if err != nil { + //log.Printf("Error updating blk_new: %v", err) + logg.Error("[gbt]", zap.String("Error updating blk_new:", err.Error())) + continue + } + logg.Warn("[gbt]", zap.String("update block success:", fmt.Sprint(block.Height)+" "+block.Nonce)) + } +} + +func randomxJobId() string { + // 生成4个字节 + bytes := make([]byte, 4) + _, err := rand.Read(bytes) + if err != nil { + panic(err) + } + + // 转成 hex 字符串 + hexStr := hex.EncodeToString(bytes) + return hexStr +} + +var start_count int = 0 +var start_height uint64 = 0 + +func gbt_running(gbt *GbtMoneroContext) { + ticker := time.NewTicker(1000 * time.Millisecond) + defer ticker.Stop() + + for gbt.GbtCtx.Started { + select { + case <-ticker.C: + resp, err := gbt.GbtCtx.MoneroClinet.GetBlockTemplate(gbt.GbtCtx.MoneroAddr, 0) + if err != nil { + fmt.Println("调用失败:", err) + continue + } + if resp != nil { + if gbt.GbtCtx.PubCh == nil { + gbt.GbtCtx.PubCh = utility.InitZmqPub(gbt.GbtCtx.Config.Zmq.Pub) + } + + if gbt.GbtCtx.PubCh != nil { + var responseJson GetBlockTemplateResponse + err = json.Unmarshal(resp, &responseJson) + if err != nil { + fmt.Println("[gbt]:get block template response to json error\n", err) + return + } + sendJobMonero := func(job msg.MoneroStratumJob) { + for trycnt := 0; trycnt < 3; trycnt++ { + job.JobId = randomxJobId() + bt, err := json.Marshal(job) + if err != nil { + fmt.Println(err) + return + } + err = gbt.GbtCtx.PubCh.SendMessage([][]byte{[]byte("jobmonero"), bt}) + if err != nil { + if !gbt.GbtCtx.Started { + return + } + logg.Warn("[gbt]", zap.String("job", err.Error())) + } else { + logg.Warn("[gbt]", zap.String("job", "sent")) + start_height = job.Height + start_count = 0 + break + } + } + atomic.StoreInt32(&(gbt.GbtCtx.FlagAliving), 1) + } + + if responseJson.Result.Height != start_height { + // 高度变化,先发 hashblock + if start_height != 0 { + topic := []byte("hashblock") + _msg := []byte("") + _ = gbt.GbtCtx.MoneroNewBlockPubCh.SendMessage([][]byte{topic, _msg}) + } + + // 再发 jobmonero + sendJobMonero(responseJson.Result) + } else if start_count >= 30 { + // 高度未变,但计数达到阈值,只发 jobmonero + sendJobMonero(responseJson.Result) + } else { + start_count += 1 + } + } else { + logg.Warn("[gbt]", zap.String("job ", "sent failed! PubCh nil")) + } + } else { + atomic.StoreInt32(&(gbt.GbtCtx.FlagAliving), 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 gbt_notify_running(gbt *GbtMoneroContext) { + 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 { + // fmt.Println("gbt_notify_running 开始接收消息") + 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" { + GbtMoneroCtx.new_block_index = GbtMoneroCtx.new_block_index + 1 + //log.Println("gbt_notify_running", hex.EncodeToString(cmsg_sub[1]), GbtNexaCtx.new_block_index) + gbt.new_block_chan <- GbtMoneroCtx.new_block_index + + } + } + } else { + logg.Error("[gbt]", zap.String("notify", "NodeSubCh fail!")) + time.Sleep(time.Duration(1) * time.Second) + } + } +} + +func submit_block_running(block *GbtMoneroContext) { + 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]) == "blkmonero" { + cmsg := cmsg_sub[1] + //block data + msgb := make([]byte, len(cmsg)-16) + copy(msgb, cmsg) + var moneroblock msg.BlockMoneroMsg + if err := json.Unmarshal(msgb, &moneroblock); err != nil { + //block.Consumer.MarkOffset(cmsg, "") + logg.Error("[block]", zap.String("failed to Unmarshal job", err.Error())) + continue + } + + // heightb, err := hex.DecodeString(string(cmsg[len(msgb) : len(msgb)+8])) + // if err != nil { + // //block.Consumer.MarkOffset(cmsg, "") + // logg.Error("[block]", zap.String("failed to decode height", err.Error())) + // continue + // } + var height uint32 = uint32(moneroblock.Height) + logg.Warn("[block]", zap.Uint32("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))) + + result, _ := block.GbtCtx.MoneroClinet.SubmitBlock(moneroblock.Header) + var submitResp MoneroRPCResponse[SubmitSuccess] + if err2 := json.Unmarshal(result, &submitResp); err2 != nil { + logg.Error("[submit block]", zap.String("unmarshal error", err2.Error())) + return + } + + if submitResp.Error != nil { + logg.Error("[submit block]", zap.String("submit failed reason", submitResp.Error.Message)) + return + } + + if submitResp.Result != nil { + logg.Info("[submit block]", zap.String("submit status", submitResp.Result.Status)) + } + logg.Info("[block]", zap.String("result", string(result))) + //} + blockHash, success_msg := submitResp.Result.BlockId, submitResp.Result.Status + // nonceHex := fmt.Sprintf("%x", moneroblock.Nonce) + dbif.NotifyPoolBlkStatsSubmitResult(block.GbtCtx, int64(height), blockHash, success_msg, moneroblock.Nonce, moneroblock.SubIdx) + + block.Submits += 1 + //log.Printf("[block] height %d subidx %d nonce %s\n", height, nexablock.SubIdx, nexablock.Nonce) + logg.Warn("[block]", zap.Float64("total submits", block.Submits), zap.Int64("SubIdx", moneroblock.SubIdx)) + // nonce, err := strconv.ParseUint(moneroblock.Nonce, 16, 32) + // if err != nil { + // return + // } + new_block_into_db(block, moneroblock.User, moneroblock.Miner, moneroblock.Index, int64(height), moneroblock.Nonce, blockHash, moneroblock.SubIdx) + } + } + } else { + logg.Error("[block]", zap.String("block", "SubCh failed! retry")) + time.Sleep(time.Duration(1) * time.Second) + } + } +} + +func new_block_into_db(block *GbtMoneroContext, 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/monero/rpc/rpc.go b/internal/gbt/monero/rpc/rpc.go new file mode 100644 index 0000000..1cb869a --- /dev/null +++ b/internal/gbt/monero/rpc/rpc.go @@ -0,0 +1,179 @@ +package monero_rpc + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" + "time" +) + +// HttpClient 封装 +type HttpClient struct { + Client *http.Client + Url string +} + +func NewHttpClient(url string, timeout time.Duration) *HttpClient { + return &HttpClient{ + Client: &http.Client{ + Timeout: timeout, + }, + Url: url, + } +} + +// GET 请求,params 可为 nil +func (hc *HttpClient) Get(api string, params map[string]interface{}, headers map[string]string) ([]byte, error) { + rawURL := hc.Url + "/json_rpc" + api + // 处理 URL 参数 + if params != nil { + u, err := url.Parse(rawURL) + if err != nil { + return nil, err + } + q := u.Query() + for k, v := range params { + q.Set(k, fmt.Sprintf("%v", v)) + } + u.RawQuery = q.Encode() + rawURL = u.String() + } + + // 创建请求 + req, err := http.NewRequest("GET", rawURL, nil) + if err != nil { + return nil, err + } + // 设置头 + for k, v := range headers { + req.Header.Set(k, v) + } + + // 发送请求 + resp, err := hc.Client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + return io.ReadAll(resp.Body) +} + +// POST 请求,params 可为 nil +func (hc *HttpClient) Post(api string, params interface{}, headers map[string]string) ([]byte, error) { + rawURL := hc.Url + "/json_rpc" + api + var body io.Reader + if params != nil { + jsonBytes, err := json.Marshal(params) + if err != nil { + return nil, err + } + body = bytes.NewBuffer(jsonBytes) + } + + req, err := http.NewRequest("POST", rawURL, body) + if err != nil { + return nil, err + } + + // 设置默认 Content-Type + if _, ok := headers["Content-Type"]; !ok { + req.Header.Set("Content-Type", "application/json") + } + + // 设置额外头 + for k, v := range headers { + req.Header.Set(k, v) + } + + resp, err := hc.Client.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + return io.ReadAll(resp.Body) +} + +type RPCRequest struct { + JsonRPC string `json:"jsonrpc"` + ID string `json:"id"` + Method string `json:"method"` + Params interface{} `json:"params"` +} + +func (hc *HttpClient) GetBlockTemplate(address string, size int) ([]byte, error) { + params := map[string]any{ + "wallet_address": address, + "reserve_size": size, + } + req := RPCRequest{ + JsonRPC: "2.0", + ID: "0", + Method: "get_block_template", + Params: params, + } + resp, err := hc.Post("", req, nil) + if err != nil { + fmt.Println("[gbt]: getblocktemplate error:", err) + return nil, err + } + + return resp, nil +} + +func (hc *HttpClient) GetBlockHeader(height uint64) ([]byte, error) { + params := map[string]any{ + "height": height, + "fill_pow_hash": true, + } + req := RPCRequest{ + JsonRPC: "2.0", + ID: "0", + Method: "get_block_header_by_height", + Params: params, + } + resp, err := hc.Post("", req, nil) + if err != nil { + fmt.Println("[gbt]: getblockheader error:", err) + return nil, err + } + return resp, nil +} + +func (hc *HttpClient) GetBlockByHash(hash string) ([]byte, error) { + params := map[string]any{ + "hash": hash, + } + req := RPCRequest{ + JsonRPC: "2.0", + ID: "0", + Method: "get_block_header_by_hash", + Params: params, + } + resp, err := hc.Post("", req, nil) + if err != nil { + fmt.Println("[gbt]: getblockheader error:", err) + return nil, err + } + return resp, nil +} + +func (hc *HttpClient) SubmitBlock(blob string) ([]byte, error) { + params := []string{blob} + req := RPCRequest{ + JsonRPC: "2.0", + ID: "0", + Method: "submit_block", + Params: params, + } + resp, err := hc.Post("", req, nil) + if err != nil { + fmt.Println("[gbt]: getblockheader error:", err) + return nil, err + } + return resp, nil +} diff --git a/internal/gbt/nexa/nexa.go b/internal/gbt/nexa/nexa.go new file mode 100644 index 0000000..07a4839 --- /dev/null +++ b/internal/gbt/nexa/nexa.go @@ -0,0 +1,627 @@ +// nexa.go +package nexa + +import ( + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "io/ioutil" + "log" + "sync/atomic" + + //"pool/internal/cache" + "pool/internal/db" + "pool/internal/gbt/coin" + "pool/internal/gbt/dbif" + "pool/internal/msg" + "pool/internal/utility" + "time" + + "database/sql" + + //"github.com/btcsuite/btcd/rpcclient" + _ "github.com/mattn/go-sqlite3" + + "go.uber.org/zap" +) + +const GBT_NEXA_VERSION string = "nexa v2.0m" + +type NexaAddrConfig struct { + Addr string `json:"addr"` +} + +type NexaConfig struct { + Nexa NexaAddrConfig `json:"nexa"` +} + +type GbtNexaContext struct { + Config NexaConfig + GbtCtx *coin.GbtContext + + last_time time.Time + last_gbt GbtNexaMsg + last_blockhash string + + last_height uint32 + + Submits float64 + + addressIndex int + + Target []byte + Header []byte + last_body string + + new_block_chan chan int + new_block_index int +} + +var logg *zap.Logger +var GbtNexaCtx GbtNexaContext + +type GbtNexaMsg struct { + Id uint64 `json:"id"` + HeaderCommitment string `json:"headerCommitment"` + NBits string `json:"nBits"` +} + +type GetBlockHeaderMsg struct { + Height int `json:"height"` + Nonce string `json:"nonce"` + Confirmations int `json:"confirmations"` +} + +type GetBlockStatsMsg struct { + Height int `json:"height"` + Subsidy float64 `json:"subsidy"` + Totalfee float64 `json:"totalfee"` +} + +type BlockCheckData struct { + Height int + Nonce string + User string + Miner string + MinerId string + Hash string + SubIdx int +} + +/*type NewBlockMsg struct { + Height int `json:"height"` + Nonce int `json:"nonce"` +}*/ + +type PushBlkNewMsg struct { + Coin string `json:"coin"` + Height int `json:"height"` + Nonce string `json:"nonce"` +} + +func update_block_confirm(gbt *GbtNexaContext) { + db, err := sql.Open("sqlite3", "./blocks.db") + if err != nil { + //log.Printf("Error opening database: %v", err) + logg.Error("[gbt]", zap.String("Error opening database", err.Error())) + return + } + defer db.Close() + + query := "SELECT user,miner,minerid,height,nonce,hash,subidx FROM blocks WHERE checked=0 AND created_at >= datetime('now', '-30 minutes') order by id desc limit 2" + rows, err := db.Query(query) + if err != nil { + //log.Printf("Error executing query from blocks: %v", err) + logg.Error("[gbt]", zap.String("Error executing query from blocks:", err.Error())) + return + } + defer rows.Close() + + var blocks []BlockCheckData + for rows.Next() { + var height int + var nonce string + var user string + var miner string + var minerid string + var hash string + var subidx int + if err := rows.Scan(&user, &miner, &minerid, &height, &nonce, &hash, &subidx); err != nil { + //log.Printf("Error scanning row in blocks: %v", err) + logg.Error("[gbt]", zap.String("Error scanning row in blocks:", err.Error())) + return + } + var blockdata BlockCheckData + blockdata.Height = height + blockdata.Nonce = nonce + blockdata.User = user + blockdata.Miner = miner + blockdata.MinerId = minerid + blockdata.Hash = hash + blockdata.SubIdx = subidx + + blocks = append(blocks, blockdata) + //fmt.Printf("blocks - Height: %d, Nonce: %d\n", height, nonce) + //log.Printf("update block height %d nonce %s, subidx %d, user %s", height, nonce, subidx, user+"."+miner+"_"+minerid) + } + for _, block := range blocks { + block_hash, err := gbt.GbtCtx.Client.GetBlockHash(int64(block.Height)) + if err != nil { + logg.Info("[gbt]", zap.String("GetBlockHash ", err.Error())) + continue + } + rawmsgs := make([]json.RawMessage, 1) + param_str := `"` + block_hash.String() + `"` + rawmsgs[0] = json.RawMessage(param_str) + result, err := gbt.GbtCtx.Client.RawRequest("getblockheader", rawmsgs) + if err != nil { + //log.Printf("getblockheader %s", err.Error()) + logg.Error("[gbt]", zap.String("getblockheader", err.Error())) + continue + } + //log.Printf("getblockheader %d %s:%v", block.Height, block_hash, result) + var blockHeader GetBlockHeaderMsg + err = json.Unmarshal(result, &blockHeader) + if err != nil { + //log.Printf("getblockheader Unmarshal %s", err.Error()) + logg.Error("[gbt]", zap.String("getblockheader Unmarshal ", fmt.Sprint(block.Height)+" "+err.Error())) + continue + } + + rawmsgs_stats := make([]json.RawMessage, 1) + rawmsgs_stats[0] = json.RawMessage(param_str) + result_stats, err := gbt.GbtCtx.Client.RawRequest("getblockstats", rawmsgs_stats) + if err != nil { + //log.Printf("getblockstats %s", err.Error()) + logg.Error("[gbt]", zap.String("getblockstats", err.Error())) + continue + } + //log.Printf("getblockheader %d %s:%v", block.Height, block_hash, result) + var blockStats GetBlockStatsMsg + err = json.Unmarshal(result_stats, &blockStats) + if err != nil { + //log.Printf("getblockstats Unmarshal %s", err.Error()) + logg.Error("[gbt]", zap.String("getblockstats Unmarshal ", fmt.Sprint(block.Height)+" "+err.Error())) + continue + } + + if blockHeader.Confirmations > 3 { + //log.Printf("cmp block: %d %s vs %s %s", block.Height, block.Nonce, string(result), blockHeader.Nonce) + //log.Printf("cmp block: %d %s %s_%s_%s vs %s\n", block.Height, block.Nonce, block.User, block.Miner, block.MinerId, blockHeader.Nonce) + if blockHeader.Nonce == block.Nonce { + + block_height := int64(block.Height) + /*dbif.NotifyMinerSuccess(gbt.GbtCtx, block.User, block.Miner, block.MinerId, block_height, "", block.Nonce, int64(block.SubIdx), blockStats.Subsidy, blockStats.Totalfee) + dbif.NotifyUsersBlkStatsSuccess(gbt.GbtCtx, block.User, block_height, "", block.Nonce, int64(block.SubIdx), blockStats.Subsidy, blockStats.Totalfee)*/ + dbif.NotifyPoolBlkStatsSuccess(gbt.GbtCtx, block_height, "", block.Nonce, int64(block.SubIdx), blockStats.Subsidy, blockStats.Totalfee) + dbif.NotifyBlkDetailSuccess(gbt.GbtCtx, block_height, "", block.Nonce, int64(block.SubIdx)) + /*dbif.NotifyBlockStat(gbt.GbtCtx, block.User, block.Miner, block.MinerId, blockStats.Subsidy, blockStats.Totalfee)*/ + //dbif.NotifyBlkNewSuccess(gbt.GbtCtx, block_height, "", block.Nonce, -1) + dbif.NotifyBlkNewDb(gbt.GbtCtx, block_height, block.Hash, true, block.Nonce, int64(block.SubIdx)) + + //gbt.GbtCtx.Blocks += 1 + //cache.StorePoolCache(gbt.GbtCtx.RedisClient, gbt.GbtCtx.Coin, "blocks", gbt.GbtCtx.Blocks) + + //gbt.GbtCtx.Reward += blockStats.Subsidy + //cache.StorePoolCache(gbt.GbtCtx.RedisClient, gbt.GbtCtx.Coin, "reward", gbt.GbtCtx.Reward) + + //gbt.GbtCtx.Fee += blockStats.Totalfee + //cache.StorePoolCache(gbt.GbtCtx.RedisClient, gbt.GbtCtx.Coin, "fee", gbt.GbtCtx.Fee) + + /*var pushmsg PushBlkNewMsg + pushmsg.Coin = gbt.GbtCtx.Coin + pushmsg.Height = block.Height + pushmsg.Nonce = block.Nonce + + jsonData, err := json.Marshal(pushmsg) + if err != nil { + //log.Printf("Failed to marshal JSON: %v", err) + logg.Error("[gbt]", zap.String("Failed to marshal JSON:", err.Error())) + continue + } + if gbt.GbtCtx.PushCh == nil { + gbt.GbtCtx.PushCh = utility.InitZmqPush(gbt.GbtCtx.Config.Profit.Push) + } + if gbt.GbtCtx.PushCh != nil { + err = gbt.GbtCtx.PushCh.SendMessage([][]byte{[]byte("blk_new"), jsonData}) + if err != nil { + //log.Printf("Failed to send data: %v", err) + logg.Error("[gbt]", zap.String("Failed to SendMessage:", err.Error())) + continue + } + }*/ + + updateSQL := `UPDATE blocks SET checked = 1 WHERE height = ? AND nonce = ? AND checked = 0` + _, err = db.Exec(updateSQL, block.Height, block.Nonce) + if err != nil { + //log.Printf("Error updating blk_new: %v", err) + logg.Error("[gbt]", zap.String("Error updating blk_new:", err.Error())) + continue + } + //log.Printf("update block success: %d %s", block.Height, block.Nonce) + logg.Warn("[gbt]", zap.String("update block success:", fmt.Sprint(block.Height)+" "+block.Nonce)) + } + } + } +} + +func get_gbt_msg(gbt *GbtNexaContext) []byte { + height, err := gbt.GbtCtx.Client.GetBlockCount() + if err != nil { + logg.Info("[gbt]", zap.String("GetBlockCount ", err.Error())) + return nil + } + height = height + 1 + rawmsgs := make([]json.RawMessage, 3) + param_str1 := `"` + "1000" + `"` + param_str2 := `"` + gbt.Config.Nexa.Addr + `"` + if len(gbt.GbtCtx.MinerAddrs) > 0 { + param_str2 = `"` + gbt.GbtCtx.MinerAddrs[gbt.GbtCtx.MinerAddrIndex] + `"` + gbt.GbtCtx.MinerAddrIndex = gbt.GbtCtx.MinerAddrIndex + 1 + if gbt.GbtCtx.MinerAddrIndex >= len(gbt.GbtCtx.MinerAddrs) { + gbt.GbtCtx.MinerAddrIndex = 0 + } + } + param_str3 := `"` + " / m2pool.com / " + `"` + //logg.Debug("[gbt]", zap.String("option", param_str)) + rawmsgs[0] = json.RawMessage(param_str1) + rawmsgs[1] = json.RawMessage(param_str2) + rawmsgs[2] = json.RawMessage(param_str3) + result, err := gbt.GbtCtx.Client.RawRequest("getminingcandidate", rawmsgs) + //log.Printf("[gbt] getminingcandidate %v %s\n", err, result) + if err != nil { + logg.Error("[gbt]", zap.String("getminingcandidate", err.Error())) + return nil + } + + var rxmsg GbtNexaMsg + err = json.Unmarshal(result, &rxmsg) + if err != nil { + logg.Error("[gbt]", zap.String("getminingcandidate", err.Error())) + return nil + } + + gbtstr := fmt.Sprintf("[gbt] height %d, id %d, header %s, nBits %s", height, rxmsg.Id, rxmsg.HeaderCommitment, rxmsg.NBits) + //logg.Debug("[gbt]", zap.String(" ", gbtstr)) + + if rxmsg.Id == gbt.last_gbt.Id { + return nil + } + + gbt.last_gbt = rxmsg + + gbt.last_time = time.Now() + + nbits_b, _ := hex.DecodeString(rxmsg.NBits) + var nbits_i uint32 = binary.BigEndian.Uint32(nbits_b) + bigdiff := utility.CompactToBig(nbits_i) + targetdiff := fmt.Sprintf("%064x", bigdiff.Bytes()) + //logg.Debug("[gbt]", zap.String("target", targetdiff)) + logg.Debug("[gbt]", zap.String(" ", gbtstr), zap.String("target", targetdiff)) + + var job msg.NexaStratumJob + job.Id = rxmsg.Id + job.Header = utility.Reverse_string(rxmsg.HeaderCommitment) + job.NBits = rxmsg.NBits + job.CurTime = uint64(time.Now().Unix()) + job.Height = uint32(height) + job.Nonce = "" + job.Target = targetdiff + job.Extranonce1 = "" + job.Extranonce2_size = 8 + job.Extranonce2 = "" + body, err := json.Marshal(job) + if err != nil { + logg.Error("[gbt]", zap.String("failed to Marshal jobmsg", err.Error())) + return nil + } + return body +} + +func gbt_notify_running(gbt *GbtNexaContext) { + for { + if !gbt.GbtCtx.Started { + break + } + if gbt.GbtCtx.NodeSubCh == nil { + gbt.GbtCtx.NodeSubCh = utility.InitZmqSub(gbt.GbtCtx.Config.Rpc.ZmqSub, utility.BITCOIND_ZMQ_HASHBLOCK) + } + if gbt.GbtCtx.NodeSubCh != nil { + cmsg_sub, err := gbt.GbtCtx.NodeSubCh.RecvMessage() + if err != nil { + if !gbt.GbtCtx.Started { + break + } + gbt.GbtCtx.NodeSubCh.SetSubscribe(utility.BITCOIND_ZMQ_HASHBLOCK) + gbt.GbtCtx.NodeSubCh.Connect(gbt.GbtCtx.Config.Rpc.ZmqSub) + continue + } + if len(cmsg_sub) >= 2 { + if string(cmsg_sub[0]) == "hashblock" { + GbtNexaCtx.new_block_index = GbtNexaCtx.new_block_index + 1 + //log.Println("gbt_notify_running", hex.EncodeToString(cmsg_sub[1]), GbtNexaCtx.new_block_index) + gbt.new_block_chan <- GbtNexaCtx.new_block_index + + } + } + } else { + logg.Error("[gbt]", zap.String("notify", "NodeSubCh fail!")) + time.Sleep(time.Duration(1) * time.Second) + } + } +} + +func gbt_running(gbt *GbtNexaContext) { + gbtmsg := get_gbt_msg(gbt) + if gbtmsg != nil { + if gbt.GbtCtx.PubCh == nil { + gbt.GbtCtx.PubCh = utility.InitZmqPub(gbt.GbtCtx.Config.Zmq.Pub) + } + if gbt.GbtCtx.PubCh != nil { + for trycnt := 0; trycnt < 3; trycnt++ { + err := gbt.GbtCtx.PubCh.SendMessage([][]byte{[]byte("jobnexa"), gbtmsg}) + if err != nil { + if !gbt.GbtCtx.Started { + return + } + //gbt.GbtCtx.PubCh.Bind(gbt.GbtCtx.Config.Zmq.Pub) + logg.Warn("[gbt]", zap.String("job ", err.Error())) + } else { + //gbt.GbtCtx.PubCh.SendChan <- [][]byte{[]byte("jobnexa"), gbtmsg} + logg.Warn("[gbt]", zap.String("job ", "sent")) + break + } + } + //gbt.GbtCtx.AlivingChan <- true + atomic.StoreInt32(&(gbt.GbtCtx.FlagAliving), 1) + } else { + logg.Warn("[gbt]", zap.String("job ", "sent failed! PubCh nil")) + } + } else { + atomic.StoreInt32(&(gbt.GbtCtx.FlagAliving), 1) + } + + timer := time.NewTimer(time.Duration(gbt.GbtCtx.Config.Rpc.Timeout) * time.Millisecond) + defer timer.Stop() + + for { + if !gbt.GbtCtx.Started { + break + } + + new_block_notify := false + + select { + case blk_idx := <-gbt.new_block_chan: + log.Println("new block chan", blk_idx) + new_block_notify = true + if !timer.Stop() { + <-timer.C + } + timer.Reset(time.Duration(gbt.GbtCtx.Config.Rpc.Timeout) * time.Millisecond) + case <-gbt.GbtCtx.ExitGbtChan: + logg.Error("[gbt]", zap.String("gbt", "exit")) + return + case <-time.After(time.Duration(gbt.GbtCtx.Config.Rpc.Timeout) * time.Millisecond): + log.Println("poll gbt timeout") + timer.Reset(time.Duration(gbt.GbtCtx.Config.Rpc.Timeout) * time.Millisecond) + } + /*if check_bestblockhash(gbt) {*/ + gbtmsg := get_gbt_msg(gbt) + if gbtmsg != nil { + //check_preblock(gbt, DbCtx) + if gbt.GbtCtx.PubCh == nil { + gbt.GbtCtx.PubCh = utility.InitZmqPub(gbt.GbtCtx.Config.Zmq.Pub) + } + if gbt.GbtCtx.PubCh != nil { + for trycnt := 0; trycnt < 3; trycnt++ { + err := gbt.GbtCtx.PubCh.SendMessage([][]byte{[]byte("jobnexa"), gbtmsg}) + if err != nil { + logg.Warn("[gbt]", zap.String("job ", err.Error())) + continue + } else { + //gbt.GbtCtx.PubCh.SendChan <- [][]byte{[]byte("jobnexa"), gbtmsg} + logg.Warn("[gbt]", zap.String("job ", "sent")) + break + } + } + //gbt.GbtCtx.AlivingChan <- true + atomic.StoreInt32(&(gbt.GbtCtx.FlagAliving), 1) + } else { + logg.Warn("[gbt]", zap.String("job ", "sent failed! PubCh nil")) + } + } else { + atomic.StoreInt32(&(gbt.GbtCtx.FlagAliving), 1) + } + + if new_block_notify { + update_block_confirm(gbt) + } + } + +} + +func nexaInit(config *NexaConfig) { + 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) { + GbtNexaCtx.GbtCtx = GbtCtx + + GbtNexaCtx.last_height = 0 + + nexaInit(&GbtNexaCtx.Config) + + GbtNexaCtx.Target = make([]byte, 32) + GbtNexaCtx.Header = make([]byte, 49) + GbtNexaCtx.last_time = time.Now() + logg = GbtCtx.Log + GbtNexaCtx.new_block_chan = make(chan int, 256) + GbtNexaCtx.new_block_index = 0 + logg.Info("[gbt]", zap.String("gbt_nexa_version", GBT_NEXA_VERSION)) + + rawmsgs := make([]json.RawMessage, 1) + pool_tag := " / m2pool.com / " + param_str := `"` + pool_tag + `"` + rawmsgs[0] = json.RawMessage(param_str) + _, err := GbtNexaCtx.GbtCtx.Client.RawRequest("setminercomment", rawmsgs) + if err != nil { + //log.Printf("setminercomment %s", err.Error()) + logg.Error("[gbt]", zap.String("setminercomment", err.Error())) + } +} + +func Start() { + go gbt_running(&GbtNexaCtx) + go gbt_notify_running(&GbtNexaCtx) + go submit_block_running(&GbtNexaCtx) +} + +func Stop() { + defer close(GbtNexaCtx.new_block_chan) +} + +func new_block_into_db(block *GbtNexaContext, 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 +} + +func submit_block_running(block *GbtNexaContext) { + 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.Destroy() + block.GbtCtx.SubCh = nil*/ + block.GbtCtx.SubCh.SetSubscribe("blk" + block.GbtCtx.Coin) + block.GbtCtx.SubCh.Connect(block.GbtCtx.Config.Zmq.Sub) + //block.GbtCtx.SubCh.Destroy() + //block.GbtCtx.SubCh = utility.InitZmqSub(block.GbtCtx.Config.Zmq.Sub, "blk"+block.GbtCtx.Coin) + continue + } + + //log.Println(cmsg_sub, len(cmsg_sub), block.GbtCtx.SubCh) + if len(cmsg_sub) >= 2 { + if string(cmsg_sub[0]) == "blknexa" { + cmsg := cmsg_sub[1] + //block data + msgb := make([]byte, len(cmsg)-16) + copy(msgb, cmsg) + + //height + //heightb := make([]byte, 4) + heightb, err := hex.DecodeString(string(cmsg[len(msgb) : len(msgb)+8])) + if err != nil { + //block.Consumer.MarkOffset(cmsg, "") + logg.Error("[block]", zap.String("failed to decode height", err.Error())) + continue + } + var height uint32 = utility.ByteToUint32(heightb) + logg.Warn("[block]", zap.Uint32("height", height)) + + if height <= block.last_height { + continue + } + block.last_height = height + + //index + //indexb := make([]byte, 4) + indexb, err1 := hex.DecodeString(string(cmsg[len(msgb)+8:])) + if err1 != nil { + //block.Consumer.MarkOffset(cmsg, "") + logg.Error("[block]", zap.String("failed to decode index", err1.Error())) + continue + } + //copy(indexb, cmsg.Value[len(msgb)+4:]) + 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))) + var nexablock msg.BlockNexaMsg + if err := json.Unmarshal(msgb, &nexablock); err != nil { + //block.Consumer.MarkOffset(cmsg, "") + logg.Error("[block]", zap.String("failed to Unmarshal job", err.Error())) + continue + } + + blk := fmt.Sprintf(`{"id":%d,"nonce":"%s"}`, nexablock.Id, nexablock.Nonce) + rawmsgs := make([]json.RawMessage, 1) + logg.Info("[block]", zap.String("blk", blk)) + rawmsgs[0] = json.RawMessage(blk) + //var last_result json.RawMessage + //for i := 0; i < len(block.Client); i++ { + result, err := block.GbtCtx.Client.RawRequest("submitminingsolution", rawmsgs) + if err != nil { + logg.Error("[block]", zap.String("submitminingsolution", err.Error())) + } else { + //last_result = result + } + logg.Info("[block]", zap.String("result", string(result))) + //} + + /*dbif.NotifyMinerSubmitResult(block.GbtCtx, nexablock.User, nexablock.Miner, nexablock.Index, int64(height), nexablock.Pow, string(result), nexablock.Nonce, nexablock.SubIdx) + dbif.NotifyUsersBlkStatsSubmitResult(block.GbtCtx, nexablock.User, int64(height), nexablock.Pow, string(result), nexablock.Nonce, nexablock.SubIdx)*/ + dbif.NotifyPoolBlkStatsSubmitResult(block.GbtCtx, int64(height), nexablock.Pow, string(result), nexablock.Nonce, nexablock.SubIdx) + + block.Submits += 1 + //log.Printf("[block] height %d subidx %d nonce %s\n", height, nexablock.SubIdx, nexablock.Nonce) + logg.Warn("[block]", zap.Float64("total submits", block.Submits), zap.Int64("SubIdx", nexablock.SubIdx)) + + new_block_into_db(block, nexablock.User, nexablock.Miner, nexablock.Index, int64(height), nexablock.Nonce, nexablock.Pow, nexablock.SubIdx) + } + } + } else { + logg.Error("[block]", zap.String("block", "SubCh failed! retry")) + time.Sleep(time.Duration(1) * time.Second) + } + } +} diff --git a/internal/gbt/tari/proto/base_node.pb.go b/internal/gbt/tari/proto/base_node.pb.go new file mode 100644 index 0000000..74fb539 --- /dev/null +++ b/internal/gbt/tari/proto/base_node.pb.go @@ -0,0 +1,4609 @@ +// 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 new file mode 100644 index 0000000..26ea595 --- /dev/null +++ b/internal/gbt/tari/proto/base_node.proto @@ -0,0 +1,600 @@ +// 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 new file mode 100644 index 0000000..126b243 --- /dev/null +++ b/internal/gbt/tari/proto/base_node_grpc.pb.go @@ -0,0 +1,1666 @@ +// 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 new file mode 100644 index 0000000..9a4971c --- /dev/null +++ b/internal/gbt/tari/proto/block.proto @@ -0,0 +1,142 @@ +// 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 new file mode 100644 index 0000000..428b15b --- /dev/null +++ b/internal/gbt/tari/proto/block/block.pb.go @@ -0,0 +1,783 @@ +// 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 new file mode 100644 index 0000000..fae006c --- /dev/null +++ b/internal/gbt/tari/proto/net_work/network.pb.go @@ -0,0 +1,790 @@ +// 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 new file mode 100644 index 0000000..fba0614 --- /dev/null +++ b/internal/gbt/tari/proto/network.proto @@ -0,0 +1,97 @@ +// 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 new file mode 100644 index 0000000..bb5fd37 --- /dev/null +++ b/internal/gbt/tari/proto/p2pool.proto @@ -0,0 +1,61 @@ +// 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 new file mode 100644 index 0000000..184a321 --- /dev/null +++ b/internal/gbt/tari/proto/sidechain_types.proto @@ -0,0 +1,77 @@ +// 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 new file mode 100644 index 0000000..c6eb653 --- /dev/null +++ b/internal/gbt/tari/proto/sidechain_types/sidechain_types.pb.go @@ -0,0 +1,727 @@ +// 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 new file mode 100644 index 0000000..0e8ab2c --- /dev/null +++ b/internal/gbt/tari/proto/transaction.proto @@ -0,0 +1,188 @@ +// 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 new file mode 100644 index 0000000..f9b355a --- /dev/null +++ b/internal/gbt/tari/proto/transaction/transaction.pb.go @@ -0,0 +1,1012 @@ +// 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 new file mode 100644 index 0000000..d25b5ad --- /dev/null +++ b/internal/gbt/tari/proto/types.proto @@ -0,0 +1,147 @@ +// 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 new file mode 100644 index 0000000..bbba83f --- /dev/null +++ b/internal/gbt/tari/proto/types/types.pb.go @@ -0,0 +1,1239 @@ +// 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 new file mode 100644 index 0000000..9b8d73e --- /dev/null +++ b/internal/gbt/tari/proto/validator_node.proto @@ -0,0 +1,132 @@ +// 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 new file mode 100644 index 0000000..5ec6d35 --- /dev/null +++ b/internal/gbt/tari/proto/wallet.proto @@ -0,0 +1,1582 @@ +// 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 new file mode 100644 index 0000000..836ed08 --- /dev/null +++ b/internal/gbt/tari/sha3x/sha3x.go @@ -0,0 +1,385 @@ +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 new file mode 100644 index 0000000..dfb3206 --- /dev/null +++ b/internal/gbt/tari/tari.go @@ -0,0 +1,120 @@ +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 new file mode 100644 index 0000000..119ba09 --- /dev/null +++ b/internal/msg/msg.go @@ -0,0 +1,165 @@ +// msg.go +package msg + +import ( + "time" + + "github.com/decred/dcrd/chaincfg/chainhash" +) + +type StratumJob struct { + Job_id string `json:"job_id, omitemtpy"` + Version int32 `json:"version, omitemtpy"` + Prevblock chainhash.Hash `json:"prevblock, omitemtpy"` + Coinbase1 string `json:"coinbase1, omitemtpy"` + Coinbase2 string `json:"coinbase2, omitemtpy"` + Bits uint32 `json:"bits, omitemtpy"` + Timestamp time.Time `json:"ts, omitemtpy"` + Extranonce1 string `json:"extranonce1, omitemtpy"` + Extranonce2_size uint64 `json:"extranonce2_size, omitemtpy"` + Extranonce2 string `json:"extranonce2, omitemtpy"` + Nonce string `json:"nonce, omitemtpy` + Target string `json:"target, omitemtpy"` + Difficulty float64 `json:"difficulty, omitemtpy"` + PrevblockS string `json:"prevblocks,omitempty"` + PrevblockBig string `json:"prevblockbig,omitempty"` + Transactions *[]string `json:"transactions,omitempty"` + BitsS string `json:"bitss,omitempty"` + Height uint32 `json:"height,omitempty"` + TransData *[]string `json:"data,omitempty"` + Payloadstart string `json:"payloadstart,omitempty"` + TimestampS string `json:"timestamps, omitempty"` + Segwit string `json:"default_witness_commitment, omitempty"` + IsClean bool `json:"isclean, omitempty"` + Mintime uint32 `json:"mintime, omitempty"` + JobDifficulty float64 `json:"diff, omitempty"` +} + +type NexaStratumJob struct { + Header string `json:"header, omitempty"` + NBits string `json:"nBits, omitempty"` + Id uint64 `json:"id, omitempty"` + CurTime uint64 `json:"timestamp, omitempty"` + Target string `json:"target, omitempty"` + Height uint32 `json:"height, omitempty"` + Nonce string `json:"nonce, omitempty"` + Extranonce1 string `json:"extranonce1, omitempty"` + Extranonce2_size uint64 `json:"extranonce2_size, omitempty"` + Extranonce2 string `json:"extranonce2, omitempty"` + JobDifficulty float64 `json:"diff, omitempty"` +} + +type BlockNexaMsg struct { + Id uint64 `json:"id"` + User string `json:"user"` + Miner string `json:"miner"` + Index string `json:"index"` + Header string `json:"header"` + Nonce string `json:"nonce"` + Pow string `json:"pow"` + SubIdx int64 `json:"subidx"` +} + +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"` + Nonce string `json:"nonce, omitempty"` + Extranonce1 string `json:"extranonce1, omitempty"` + Extranonce2_size uint64 `json:"extranonce2_size, omitempty"` + Extranonce2 string `json:"extranonce2, omitempty"` + JobDifficulty float64 `json:"diff, omitempty"` + U64target uint64 `json:"u64target, omitempty"` +} + +type BlockSha3xMsg struct { + Id uint64 `json:"id"` + User string `json:"user"` + Miner string `json:"miner"` + Index string `json:"index"` + Header string `json:"header"` + Nonce uint64 `json:"nonce"` + Pow string `json:"pow"` + SubIdx int64 `json:"subidx"` + Height uint64 `json:"height"` + 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"` + Difficulty uint64 `json:"difficulty"` + DiffcultyTop64 uint64 `json:"difficulty_top64"` + ExpectedReward uint64 `json:"expected_reward"` + Height uint64 `json:"height"` + NextSeedHash string `json:"next_seed_hash"` + PrevHash string `json:"prev_hash"` + ReservedOffset uint64 `json:"reserved_offset"` + SeedHash string `json:"seed_hash"` + SeedHeight uint64 `json:"seed_height"` + Status string `json:"status"` + Untrusted bool `json:"untrusted"` + WideDifficulty string `json:"wide_difficulty"` +} + +type MoneroStratumJob struct { + Id uint64 `json:"id"` + JobId string `json:"job_id"` + BlockhashingBlob string `json:"blockhashing_blob"` + BlocktemplateBlob string `json:"blocktemplate_blob"` + Difficulty uint64 `json:"difficulty"` + DiffcultyTop64 uint64 `json:"difficulty_top64"` + ExpectedReward uint64 `json:"expected_reward"` + Height uint64 `json:"height"` + NextSeedHash string `json:"next_seed_hash"` + PrevHash string `json:"prev_hash"` + ReservedOffset uint64 `json:"reserved_offset"` + SeedHash string `json:"seed_hash"` + SeedHeight uint64 `json:"seed_height"` + Status string `json:"status"` + Untrusted bool `json:"untrusted"` + WideDifficulty string `json:"wide_difficulty"` + Target string `json:"target"` + Nonce string `json:"nonce"` + CompleteHeader []byte `json:"completeHeader"` +} + +type BlockMoneroMsg struct { + Id uint64 `json:"id"` + User string `json:"user"` + Miner string `json:"miner"` + Index string `json:"index"` + Header string `json:"header"` + Nonce string `json:"nonce"` + Pow string `json:"pow"` + SubIdx int64 `json:"subidx"` + Height uint64 `json:"height"` + SubmitIdx uint64 `json:"submitidx"` +} diff --git a/internal/server/coin/coin.go b/internal/server/coin/coin.go new file mode 100644 index 0000000..0879f2f --- /dev/null +++ b/internal/server/coin/coin.go @@ -0,0 +1,681 @@ +// coin.go +package coin + +import ( + "container/list" + "crypto/md5" + "crypto/rand" + "encoding/base64" + + "database/sql" + "encoding/hex" + + "io" + "log" + "math" + "math/big" + "net" + + "fmt" + "pool/internal/db" + "pool/internal/msg" + "pool/internal/server/diff" + "pool/internal/utility" + "sync" + "time" + + "github.com/rs/zerolog" + + "github.com/redis/go-redis/v9" + "github.com/zeromq/goczmq" + "go.uber.org/zap" + "gopkg.in/natefinch/lumberjack.v2" + + _ "github.com/mattn/go-sqlite3" +) + +const JOB_EXPIRED_TIME uint32 = 3600 //job expired time (second) +const LOCAL_JOBS_EXPIRED_TIME uint32 = 3600 //300 //local jobs expired time (second) +const LOCAL_JOBS_TOTAL_SIZE uint32 = 100 //300 //total local jobs +const CONN_EXPIRED_TIME uint32 = 600 //connection expired time + +// miner status +// const MINER_STATUS_OFFLINE string = "offline" +const MINER_STATUS_CONNECTED string = "connected" +const MINER_STATUS_SUBSCRIBED string = "subscribed" +const MINER_STATUS_AUTHORIZED string = "authorized" +const MINER_STATUS_RUNNING string = "online" +const MINER_STATUS_DISCONNECTED string = "offline" +const MINER_STATUS_DISABLED string = "disabled" + +const MINER_DURATION_TIME time.Duration = 1 +const MINER_DIFFICULTY_ADJUST_DURATION time.Duration = 5 + +// vardiff +const UP_DIFF int = 0 +const DOWN_DIFF int = 1 +const UPDATE_DIFF int = 2 +const DIFFICULTY_WAIT_TIMES int = 6 + +const ( + Low = 0 + Mid = 1 + Hign = 2 +) + +type BindConfig struct { + Listen string `json:"listen"` + Auth bool `json:"auth"` +} + +type DiffConfig struct { + StartDifficulty float64 `json:"start_diff"` + DiffMin float64 `json:"diff_min"` + DiffMax float64 `json:"diff_max"` + DiffAdjustInterval float64 `json:"diff_adjust_interval"` + DiffAdjustPercentage float64 `json:"diff_adjust_percentage"` + DiffAdjustTime float64 `json:"diff_adjust_time"` + Filter string `json:"filter"` + Dbg bool `json:"dbg"` +} + +type ServerConfig struct { + Coin string `json:"coin"` + Host BindConfig `json:"host"` + Diff DiffConfig `json:"diff"` + Zmq utility.ZmqConfig `json:"zmq"` + Redis utility.RedisConfig `json:"redis"` + Zaplog zap.Config `json:"zap"` + Logrotae utility.LogRotateConfig `json:"logrotate"` +} + +type CoinObj struct { + Coin string + Init func(server *ServerContext) + Start func() + Stop func() + InitMiner func(miner *MinerObj) + HandleMinerSubscribe func(miner *MinerObj, id float64, extranonce1 string, msg string) + HandleMinerAuth func(miner *MinerObj) + HandleMinerSubmit func(miner *MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) + SetDifficulty func(miner *MinerObj) + Notify func(miner *MinerObj) + HandleJobMsg func(server *ServerContext, Msg []byte) + IsMhsLow func(miner *MinerObj) bool + GetBlockInterval func() int +} + +type PoolBlkMsg struct { + Height int64 + Hash string + Pow string + Net_target string + Submit string + Success bool + Accepts float64 + Rejects float64 + Reward float64 + Fee float64 + Nonce string + SubIdx int64 +} + +type ServerContext struct { + CoinCtx CoinObj + DbCtx *db.DbContext + + Config *ServerConfig + + PubCh *goczmq.Sock + SubCh *goczmq.Sock + + Listener net.Listener + + MinerType string + + Extranonce1 uint64 + + Difficulty float64 + + RefDifficulty float64 + + Accepts float64 + Rejects float64 + AverageHashrate float64 + + Miners sync.Map + + MMhs sync.Map + + Started bool + + SLock sync.Mutex + ExitFlag bool + + //AlivingChan chan bool + //LiveingExpired bool + FlagAliving int32 + FlagAlivingExit int32 + + ExitPingChan chan bool + ExitJobChan chan bool + + Logg *zap.Logger + LogR *lumberjack.Logger + + SJob msg.StratumJob + + //UpdateMap sync.Map + + SyncJobChan chan bool + Synced bool + + ExitDbMiners chan bool + ExitDbMinersStats chan bool + + ExitDbUser chan bool + ExitDbUserStats chan bool + + ExitDbPoolStats chan bool + + NexaJob msg.NexaStratumJob + Sha3xJob msg.Sha3xStratumJob + MoneroJob msg.MoneroStratumJob + Tari_Sha3xJob msg.GbtSendMsg + ExitDiffVar chan bool + + RedisClient *redis.Client + + Accepts5M float64 + Accepts15M float64 + Accepts30M float64 + Accepts1h float64 + Accepts3h float64 + Accepts6h float64 + Accepts12h float64 + Accepts24h float64 + Accepts48h float64 + + Rejects5M float64 + Rejects15M float64 + Rejects30M float64 + Rejects1h float64 + Rejects3h float64 + Rejects6h float64 + Rejects12h float64 + Rejects24h float64 + Rejects48h float64 + + Mhs5M float64 + Mhs15M float64 + Mhs30M float64 + Mhs1h float64 + Mhs3h float64 + Mhs6h float64 + Mhs12h float64 + Mhs24h float64 + Mhs48h float64 + + RejectRatio5M float64 + RejectRatio15M float64 + RejectRatio30M float64 + RejectRatio1h float64 + RejectRatio3h float64 + RejectRatio6h float64 + RejectRatio12h float64 + RejectRatio24h float64 + RejectRatio48h float64 + + TotalMiners int64 + Normal int64 + Abnormal int64 + Offline int64 + MhsZero int64 + MhsLow int64 + HighRejects int64 + Unstable int64 + + NetTarget string + NetHight uint64 + + Submits int64 + Blocks int64 + Orphans int64 + + Reward float64 + Fee float64 + + /*Users sync.Map + UsersSLock sync.Mutex*/ + + /*PoolSLock sync.Mutex*/ + + SubIdx int64 + + MinerIndex int64 + + //NotifyBlkDetailIdx int32 + + CacheUsers sync.Map + CacheUsersCnt int32 + + CurrentConns int32 + IpCounts map[string]int + IpMutex sync.Mutex +} + +type JobListEntry struct { + Job_id string + Ts time.Time +} + +type MhsItem struct { + Tt time.Time + Diff float64 +} + +type MhsObj struct { + MinerId string + Name string + Accepts []MhsItem + Rejects []MhsItem + StartSubmitTime time.Time + + StartDayTime time.Time + + User string + Miner string + Index string + Status string + Algo int + Release bool + + LockForMhs sync.Mutex +} + +type VarDiffOptions struct { + VariancePercent float64 + AdjustTime float64 + AdjustInterval float64 + MinDiff float64 + MaxDiff float64 + MinShares float64 + MaxShares float64 + TargetShares float64 + SubmitShares float64 + SilenceCount float64 + LastCalcTime time.Time + Uptimes int + Downtimes int + Level int + LastSubmitTime time.Time +} + +type BlockMsg struct { + Target string + Submit_target string + Height int64 + Success bool + Pow string + Net_target string + Submit string + Hash string + Header string + Accepts float64 + Total_accepts float64 + Rejects float64 + Total_rejects float64 + Reward float64 + Fee float64 + Nonce string + SubIdx int64 +} + +type MinerObj struct { + Server *ServerContext + Conn net.Conn + Authorized bool + + MinerId string + JobId uint32 + Name string + + Jobs sync.Map + LockForJobs sync.Mutex + JobList *list.List + + Target *big.Int + Difficulty float64 + DifficultyNext float64 + ServerDifficulty float64 + ServerTarget *big.Int + ServerTargetS string + Accepts float64 + Rejects float64 + StartSubmitTime time.Time + LastSubmitime time.Time + SubmitIndex uint32 + AverageHashrate float64 + M5Accepts float64 + M5Hashrate float64 + M5SubmitTime time.Time + LastJobId string + LastNonce string + CurHeight uint32 + CurHeight64 uint64 + Reconnect bool + + LastHeader string + + VarDiffOpt VarDiffOptions + + Version int32 + Job msg.StratumJob + + User string + PassWord string + Miner string + Session string + Duration float64 + + Status string + ConnSetupTime time.Time + TxLock sync.Mutex + + KeepliveCnt float64 + RecvedLiveAck bool + PongFailCnt int + PingCnt int + + NexaJob msg.NexaStratumJob + Sha3xJob msg.Sha3xStratumJob + MoneroJob msg.MoneroStratumJob + Tari_Sha3xJob msg.GbtSendMsg + + FromIP string + + OnlineTime time.Time + OfflineTime time.Time + Retry int64 + DurationTime float64 + MinerIndex int64 + + Protocol string + + ErrStaleds int64 + ErrLowDiffs int64 + ErrDuplicates int64 + ErrFormats int64 + ErrOthers int64 + + IsDisabled bool + + Submits int64 + Blocks int64 + Orphans int64 + + Accepts5M float64 + Accepts15M float64 + Accepts30M float64 + Accepts1h float64 + Accepts3h float64 + Accepts6h float64 + Accepts12h float64 + Accepts24h float64 + Accepts48h float64 + + Rejects5M float64 + Rejects15M float64 + Rejects30M float64 + Rejects1h float64 + Rejects3h float64 + Rejects6h float64 + Rejects12h float64 + Rejects24h float64 + Rejects48h float64 + + Mhs5M float64 + Mhs15M float64 + Mhs30M float64 + Mhs1h float64 + Mhs3h float64 + Mhs6h float64 + Mhs12h float64 + Mhs24h float64 + Mhs48h float64 + + RejectRatio5M float64 + RejectRatio15M float64 + RejectRatio30M float64 + RejectRatio1h float64 + RejectRatio3h float64 + RejectRatio6h float64 + RejectRatio12h float64 + RejectRatio24h float64 + RejectRatio48h float64 + + Reward float64 + Fee float64 + + Zlog zerolog.Logger + LogR *lumberjack.Logger + ZlogInit bool + + //EndCh chan bool + + DiffHandler diff.KalmanVarDiff + + NeedExit int32 + + PingEnabled bool +} + +/*type UserBlockMsg struct { + User string + Miner string + Index string + Height int64 + Hash string + Pow string + Net_target string + Submit string + Success bool + Accepts float64 + Rejects float64 + Reward float64 + Fee float64 + Nonce string + SubIdx int64 +}*/ +/* +type UserMinerContainer struct { + Data map[string]string +}*/ + +/* +type UserObj struct { + Server *ServerContext + User string + Name string + + Normal int64 + Abnormal int64 + + Offline int64 + MhsZero int64 + MhsLow int64 + HighRejects int64 + Unstable int64 + + Submits int64 + Blocks int64 + Orphans int64 + + Reward float64 + Fee float64 + + Accepts5M float64 + Accepts15M float64 + Accepts30M float64 + Accepts1h float64 + Accepts3h float64 + Accepts6h float64 + Accepts12h float64 + Accepts24h float64 + Accepts48h float64 + + Rejects5M float64 + Rejects15M float64 + Rejects30M float64 + Rejects1h float64 + Rejects3h float64 + Rejects6h float64 + Rejects12h float64 + Rejects24h float64 + Rejects48h float64 + + Mhs5M float64 + Mhs15M float64 + Mhs30M float64 + Mhs1h float64 + Mhs3h float64 + Mhs6h float64 + Mhs12h float64 + Mhs24h float64 + Mhs48h float64 + + RejectRatio5M float64 + RejectRatio15M float64 + RejectRatio30M float64 + RejectRatio1h float64 + RejectRatio3h float64 + RejectRatio6h float64 + RejectRatio12h float64 + RejectRatio24h float64 + RejectRatio48h float64 +}*/ + +func md5md5(v string) string { + md5Obj := md5.New() + md5Obj.Write([]byte(v)) + char := md5Obj.Sum(nil) + return hex.EncodeToString(char) +} + +func Guid() string { + c := make([]byte, 32) + if _, err := io.ReadFull(rand.Reader, c); err != nil { + return "" + } + return md5md5(base64.URLEncoding.EncodeToString(c)) +} + +func VarAdjustDifficulty(miner *MinerObj, adjust int) { + if adjust != UP_DIFF && adjust != DOWN_DIFF && adjust != UPDATE_DIFF { + miner.Server.Logg.Error("[server]", zap.Int("Not support adjust ", adjust)) + return + } + if adjust == UP_DIFF { + miner.DifficultyNext = miner.Difficulty + if miner.VarDiffOpt.Level == Mid { + miner.DifficultyNext *= math.Pow(2, 1) + miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000 + } else if miner.VarDiffOpt.Level == Hign { + miner.DifficultyNext *= math.Pow(2, 2) + miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000 + } + } else if adjust == DOWN_DIFF { + miner.DifficultyNext = miner.Difficulty + if miner.VarDiffOpt.Level == Mid { + miner.DifficultyNext /= math.Pow(2, 1) + miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000 + } else if miner.VarDiffOpt.Level == Hign { + miner.DifficultyNext /= math.Pow(2, 2) + miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000 + } + } else if adjust == UPDATE_DIFF { + if miner.VarDiffOpt.SubmitShares > 0 { + // re-target if outside bounds + if miner.VarDiffOpt.SubmitShares < miner.VarDiffOpt.MinShares || miner.VarDiffOpt.SubmitShares > miner.VarDiffOpt.MaxShares { + var change float64 = miner.VarDiffOpt.SubmitShares / miner.VarDiffOpt.TargetShares + miner.DifficultyNext = miner.Difficulty + miner.DifficultyNext *= change + miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000 + } + miner.VarDiffOpt.SilenceCount = 0 + } else { + // radical measures if there were no shares submitted + miner.VarDiffOpt.SilenceCount++ + miner.DifficultyNext = miner.Difficulty / math.Pow(2, miner.VarDiffOpt.SilenceCount) + miner.DifficultyNext = math.Round(miner.DifficultyNext*1000) / 1000 + } + } + + if miner.DifficultyNext < miner.VarDiffOpt.MinDiff { + miner.DifficultyNext = miner.VarDiffOpt.MinDiff + } else if miner.DifficultyNext > miner.VarDiffOpt.MaxDiff { + miner.DifficultyNext = miner.VarDiffOpt.MaxDiff + } + miner.VarDiffOpt.TargetShares = miner.VarDiffOpt.AdjustTime / miner.VarDiffOpt.AdjustInterval * miner.DifficultyNext + miner.VarDiffOpt.MinShares = miner.VarDiffOpt.AdjustTime / miner.VarDiffOpt.AdjustInterval * miner.DifficultyNext * (1 - miner.VarDiffOpt.VariancePercent) + miner.VarDiffOpt.MaxShares = miner.VarDiffOpt.AdjustTime / miner.VarDiffOpt.AdjustInterval * miner.DifficultyNext * (1 + miner.VarDiffOpt.VariancePercent) + miner.VarDiffOpt.SubmitShares = 0 + miner.VarDiffOpt.Uptimes = 0 + miner.VarDiffOpt.Downtimes = 0 + miner.Server.Logg.Info("[server]", zap.Float64("DifficultyNext", miner.DifficultyNext)) + miner.Server.Logg.Info("[server]", zap.Float64("TargetShares", miner.VarDiffOpt.TargetShares), zap.Float64("MinShares", miner.VarDiffOpt.MinShares), zap.Float64("MaxShares", miner.VarDiffOpt.MaxShares)) + + now := time.Now() + share_interval := now.Sub(miner.LastSubmitime).Seconds() + New_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, miner.DifficultyNext, miner.VarDiffOpt.SubmitShares, share_interval, miner.VarDiffOpt.MinShares, miner.VarDiffOpt.MaxShares) +} + +var gdiff_db *sql.DB + +func Init_diff_db() { + db, err := sql.Open("sqlite3", "./diffs.db") + if err != nil { + log.Printf("Error opening database: %v", err) + return + } + //defer db.Close() + + gdiff_db = db + + createTableSQL := ` + CREATE TABLE IF NOT EXISTS diffs ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + ts TEXT NOT NULL, + user TEXT NOT NULL, + miner TEXT NOT NULL, + minerid TEXT NOT NULL, + diff REAL NOT NULL, + next REAL NOT NULL, + kp REAL NOT NULL, + interval REAL NOT NULL, + mhs REAL NOT NULL, + mhs_est REAL NOT NULL + );` + _, err = gdiff_db.Exec(createTableSQL) + if err != nil { + log.Printf("Error creating table: %v", err) + return + } +} + +func New_diff_into_db(user string, miner string, minerid string, diff float64, diff_next float64, kp float64, interval float64, mhs float64, mhs_est float64) { + if gdiff_db != nil { + insertSQL := `INSERT INTO diffs (ts, user, miner, minerid, diff, next, kp, interval, mhs, mhs_est) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)` + _, err := gdiff_db.Exec(insertSQL, time.Now().Format("2006-01-02 15:04:05"), user, miner, minerid, diff, diff_next, kp, interval, mhs, mhs_est) + if err != nil { + log.Printf("Error inserting data from diffs %s: %v", user+"."+miner+"_"+minerid, err) + return + } + } +} + +func DiffStop() { + if gdiff_db != nil { + defer gdiff_db.Close() + } +} diff --git a/internal/server/dbif/dbif.go b/internal/server/dbif/dbif.go new file mode 100644 index 0000000..bc32ecd --- /dev/null +++ b/internal/server/dbif/dbif.go @@ -0,0 +1,1224 @@ +// dbif.go +package dbif + +import ( + "fmt" + "log" + + //"pool/internal/cache" + "pool/internal/db" + "pool/internal/server/coin" + "strconv" + + //"sync/atomic" + + //"strings" + "time" +) + +const MINER_UPDATE_MINERS_DB_DURATION time.Duration = 5 + +/*const MINER_UPDATE_MINERS_STATS_DB_DURATION time.Duration = 5 +const MINER_UPDATE_USERS_DB_DURATION time.Duration = 5 +const MINER_UPDATE_USERS_STATS_DB_DURATION time.Duration = 5 +const MINER_UPDATE_POOL_DB_DURATION time.Duration = 5 +const MINER_UPDATE_POOL_STATS_DB_DURATION time.Duration = 5 +const MINER_UPDATE_ADDRESS_DB_DURATION time.Duration = 5*/ + +func Create_db_tables(DbCtx *db.DbContext, coinType string) { + //Periodic + db.CreateTable(DbCtx, "miners", coinType) + db.CreateTable(DbCtx, "miners_stats", coinType) + //Real time + //db.CreateTable(DbCtx, "miner", coinType) + //Periodic + //db.CreateTable(DbCtx, "users", coinType) + //db.CreateTable(DbCtx, "users_stats", coinType) + //Real time + //db.CreateTable(DbCtx, "users_blkstats", coinType) + //Periodic + //db.CreateTable(DbCtx, "pool", coinType) + //db.CreateTable(DbCtx, "pool_stats", coinType) + //Real time + db.CreateTable(DbCtx, "pool_blkstats", coinType) + db.CreateTable(DbCtx, "blk_detail", coinType) + db.CreateTable(DbCtx, "blk_new", coinType) + //Preset + db.CreateTable(DbCtx, "address", coinType) + //Real time + db.CreateTable(DbCtx, "blk_height_detail", coinType) + log.Println("create tables!") +} + +func NotifyMinersDb(m *coin.MinerObj, msgs *[]db.Miners_db_msg) { + var msg db.Miners_db_msg + msg.Id = 0 + msg.Msg = "miners" + msg.Date = time.Now() + msg.MinerType = m.Name + msg.Fromip = m.FromIP + if msg.Date.Sub(m.LastSubmitime).Seconds() > 300 { + msg.State = coin.MINER_STATUS_DISCONNECTED + } else { + msg.State = m.Status + } + msg.Online = m.StartSubmitTime + msg.Offline = m.OfflineTime + msg.Retry = int(m.Retry) + m.Duration = m.LastSubmitime.Sub(m.StartSubmitTime).Seconds() + m.DurationTime = m.Duration + msg.Duration = m.Duration + msg.Protocol = m.Protocol + msg.User = m.User + msg.Miner = m.Miner + msg.Index = fmt.Sprint(m.MinerIndex) + msg.Diff = m.Difficulty + msg.Height = m.CurHeight + msg.Accepts = m.Accepts + msg.Rejects = m.Rejects + if (m.Accepts + m.Rejects) > 0 { + msg.Ratio = m.Rejects / (m.Accepts + m.Rejects) + } else { + msg.Ratio = 0 + } + msg.Staleds = float64(m.ErrStaleds) + msg.Lows = float64(m.ErrLowDiffs) + msg.Duplicates = float64(m.ErrDuplicates) + msg.Formats = float64(m.ErrFormats) + msg.Others = float64(m.ErrOthers) + msg.Disabled = m.IsDisabled + msg.Last_submit = m.LastSubmitime + msg.Submits = int(m.Submits) + msg.Blocks = int(m.Blocks) + msg.Orphans = int(m.Orphans) + if m.Submits > 0 { + msg.Orphan_ratio = float64(m.Orphans) / float64(m.Submits) + } else { + msg.Orphan_ratio = 0 + } + + //m.Server.DbCtx.Miners_ch <- msg + *msgs = append(*msgs, msg) +} + +func NotifyMinersStatsDb(m *coin.MinerObj, msgs *[]db.MinersStats_db_msg) { + var msg db.MinersStats_db_msg + msg.Id = 0 + msg.Msg = "miners_stats" + msg.Date = time.Now() + msg.MinerType = m.Name + + msg.User = m.User + msg.Miner = m.Miner + msg.Index = fmt.Sprint(m.MinerIndex) + + msg.Shares5m = m.Accepts5M + msg.Shares15m = m.Accepts15M + msg.Shares30m = m.Accepts30M + msg.Shares1h = m.Accepts1h + msg.Shares3h = m.Accepts3h + msg.Shares6h = m.Accepts6h + msg.Shares12h = m.Accepts12h + msg.Shares24h = m.Accepts24h + msg.Shares48h = m.Accepts48h + + msg.Rejects5m = m.Rejects5M + msg.Rejects15m = m.Rejects15M + msg.Rejects30m = m.Rejects30M + msg.Rejects1h = m.Rejects1h + msg.Rejects3h = m.Rejects3h + msg.Rejects6h = m.Rejects6h + msg.Rejects12h = m.Rejects12h + msg.Rejects24h = m.Rejects24h + msg.Rejects48h = m.Rejects48h + + msg.Mhs5m = m.Mhs5M + msg.Mhs15m = m.Mhs15M + msg.Mhs30m = m.Mhs30M + msg.Mhs1h = m.Mhs1h + msg.Mhs3h = m.Mhs3h + msg.Mhs6h = m.Mhs6h + msg.Mhs12h = m.Mhs12h + msg.Mhs24h = m.Mhs24h + msg.Mhs48h = m.Mhs48h + + msg.Ratio5m = m.RejectRatio5M + msg.Ratio15m = m.RejectRatio15M + msg.Ratio30m = m.RejectRatio30M + msg.Ratio1h = m.RejectRatio1h + msg.Ratio3h = m.RejectRatio3h + msg.Ratio6h = m.RejectRatio6h + msg.Ratio12h = m.RejectRatio12h + msg.Ratio24h = m.RejectRatio24h + msg.Ratio48h = m.RejectRatio48h + + //m.Server.DbCtx.MinersStats_ch <- msg + *msgs = append(*msgs, msg) +} + +/*func NotifyMinerDb2(m *coin.MinerObj, block *coin.BlockMsg) { + var msg db.Miner_db_msg + msg.Id = 0 + msg.Msg = "miner" + msg.Date = time.Now() + msg.MinerType = m.Name + + msg.User = m.User + msg.Miner = m.Miner + msg.Index = fmt.Sprint(m.MinerIndex) + + msg.Target = block.Target + msg.Submit_target = block.Submit_target + msg.Height = block.Height + if block.Success { + msg.Success = 1 + } else { + msg.Success = 0 + } + msg.Pow = block.Pow + msg.Net_target = block.Net_target + msg.Submit = block.Submit + msg.Hash = block.Hash + msg.Header = block.Header + msg.Accepts = block.Accepts + msg.Total_accepts = block.Total_accepts + msg.Rejects = block.Rejects + msg.Total_rejects = block.Total_rejects + msg.Reward = block.Reward + msg.Fee = block.Fee + msg.Nonce = block.Nonce + msg.SubIdx = block.SubIdx + + m.Server.DbCtx.Miner_ch <- msg + +}*/ + +/*func NotifyUsersDb(u *coin.UserObj) { + var msg db.Users_db_msg + msg.Id = 0 + msg.Msg = "users" + msg.Date = time.Now() + msg.MinerType = u.Name + + msg.User = u.User + + msg.Normal = u.Normal + msg.Abnormal = u.Abnormal + msg.Offline = u.Offline + + msg.MhsZero = u.MhsZero + msg.MhsLow = u.MhsLow + msg.HighRejects = u.HighRejects + msg.Unstable = u.Unstable + + msg.Submits = u.Submits + msg.Blocks = u.Blocks + msg.Orphans = u.Orphans + if u.Submits > 0 { + msg.Orphan_ratio = float64(u.Orphans) / float64(u.Submits) + } else { + msg.Orphan_ratio = 0 + } + msg.Reward = u.Reward + msg.Fee = u.Fee + + u.Server.DbCtx.Users_ch <- msg +}*/ + +/*func NotifyUsersStatsDb(u *coin.UserObj) { + var msg db.UsersStats_db_msg + msg.Id = 0 + msg.Msg = "users_stats" + msg.Date = time.Now() + msg.MinerType = u.Name + + msg.User = u.User + + msg.Shares5m = u.Accepts5M + msg.Shares15m = u.Accepts15M + msg.Shares30m = u.Accepts30M + msg.Shares1h = u.Accepts1h + msg.Shares3h = u.Accepts3h + msg.Shares6h = u.Accepts6h + msg.Shares12h = u.Accepts12h + msg.Shares24h = u.Accepts24h + msg.Shares48h = u.Accepts48h + + msg.Rejects5m = u.Rejects5M + msg.Rejects15m = u.Rejects15M + msg.Rejects30m = u.Rejects30M + msg.Rejects1h = u.Rejects1h + msg.Rejects3h = u.Rejects3h + msg.Rejects6h = u.Rejects6h + msg.Rejects12h = u.Rejects12h + msg.Rejects24h = u.Rejects24h + msg.Rejects48h = u.Rejects48h + + msg.Mhs5m = u.Mhs5M + msg.Mhs15m = u.Mhs15M + msg.Mhs30m = u.Mhs30M + msg.Mhs1h = u.Mhs1h + msg.Mhs3h = u.Mhs3h + msg.Mhs6h = u.Mhs6h + msg.Mhs12h = u.Mhs12h + msg.Mhs24h = u.Mhs24h + msg.Mhs48h = u.Mhs48h + + msg.Ratio5m = u.RejectRatio5M + msg.Ratio15m = u.RejectRatio15M + msg.Ratio30m = u.RejectRatio30M + msg.Ratio1h = u.RejectRatio1h + msg.Ratio3h = u.RejectRatio3h + msg.Ratio6h = u.RejectRatio6h + msg.Ratio12h = u.RejectRatio12h + msg.Ratio24h = u.RejectRatio24h + msg.Ratio48h = u.RejectRatio48h + + u.Server.DbCtx.UsersStats_ch <- msg +}*/ + +/*func NotifyUsersBlkStatsDb2(m *coin.MinerObj, block *coin.UserBlockMsg) { + var msg db.UsersBlkStats_db_msg + msg.Id = 0 + msg.Msg = "users_blkstats" + msg.Date = time.Now() + msg.MinerType = m.Name + + msg.User = m.User + + msg.Miner = block.Miner + msg.Index = block.Index + msg.Height = block.Height + msg.Hash = block.Hash + msg.Pow = block.Pow + msg.Net_target = block.Net_target + msg.Submit = block.Submit + if block.Success { + msg.Success = 1 + } else { + msg.Success = 0 + } + msg.Accepts = block.Accepts + msg.Rejects = block.Rejects + msg.Reward = block.Reward + msg.Fee = block.Fee + msg.Nonce = block.Nonce + msg.SubIdx = block.SubIdx + + m.Server.DbCtx.UsersBlkStats_ch <- msg + +}*/ + +/*func NotifyPoolDb(server *coin.ServerContext) { + var msg db.Pool_db_msg + msg.Id = 0 + msg.Msg = "pool" + msg.Date = time.Now() + msg.MinerType = server.MinerType + + msg.Miners = server.TotalMiners + msg.Normal = server.Normal + msg.Abnormal = server.Abnormal + msg.Offline = server.Offline + + msg.MhsZero = server.MhsZero + msg.MhsLow = server.MhsLow + msg.HighRejects = server.HighRejects + msg.Unstable = server.Unstable + + msg.Net_target = server.NetTarget + msg.Height = server.NetHight + msg.Submits = server.Submits + msg.Blocks = server.Blocks + msg.Orphans = server.Orphans + + if server.Submits > 0 { + msg.Orphan_ratio = float64(server.Orphans) / float64(server.Submits) + } else { + msg.Orphan_ratio = 0 + } + msg.Reward = server.Reward + msg.Fee = server.Fee + + server.DbCtx.Pool_ch <- msg +}*/ + +/*func NotifyPoolStatsDb(server *coin.ServerContext) { + var msg db.PoolStats_db_msg + msg.Id = 0 + msg.Msg = "pool_stats" + msg.Date = time.Now() + msg.MinerType = server.MinerType + + msg.Shares5m = server.Accepts5M + msg.Shares15m = server.Accepts15M + msg.Shares30m = server.Accepts30M + msg.Shares1h = server.Accepts1h + msg.Shares3h = server.Accepts3h + msg.Shares6h = server.Accepts6h + msg.Shares12h = server.Accepts12h + msg.Shares24h = server.Accepts24h + msg.Shares48h = server.Accepts48h + + msg.Rejects5m = server.Rejects5M + msg.Rejects15m = server.Rejects15M + msg.Rejects30m = server.Rejects30M + msg.Rejects1h = server.Rejects1h + msg.Rejects3h = server.Rejects3h + msg.Rejects6h = server.Rejects6h + msg.Rejects12h = server.Rejects12h + msg.Rejects24h = server.Rejects24h + msg.Rejects48h = server.Rejects48h + + msg.Mhs5m = server.Mhs5M + msg.Mhs15m = server.Mhs15M + msg.Mhs30m = server.Mhs30M + msg.Mhs1h = server.Mhs1h + msg.Mhs3h = server.Mhs3h + msg.Mhs6h = server.Mhs6h + msg.Mhs12h = server.Mhs12h + msg.Mhs24h = server.Mhs24h + msg.Mhs48h = server.Mhs48h + + msg.Ratio5m = server.RejectRatio5M + msg.Ratio15m = server.RejectRatio15M + msg.Ratio30m = server.RejectRatio30M + msg.Ratio1h = server.RejectRatio1h + msg.Ratio3h = server.RejectRatio3h + msg.Ratio6h = server.RejectRatio6h + msg.Ratio12h = server.RejectRatio12h + msg.Ratio24h = server.RejectRatio24h + msg.Ratio48h = server.RejectRatio48h + + server.DbCtx.PoolStats_ch <- msg +}*/ + +func NotifyPoolBlkStatsDb2(server *coin.ServerContext, block *coin.PoolBlkMsg) { + var msg db.PoolBlkStats_db_msg + msg.Id = 0 + msg.Msg = "pool_blkstats" + msg.Date = time.Now() + msg.MinerType = server.MinerType + + msg.Height = block.Height + msg.Hash = block.Hash + msg.Pow = block.Pow + msg.Net_target = block.Net_target + msg.Submit = block.Submit + if block.Success { + msg.Success = 1 + } else { + msg.Success = 0 + } + msg.Accepts = block.Accepts + msg.Rejects = block.Rejects + msg.Reward = block.Reward + msg.Fee = block.Fee + msg.Nonce = block.Nonce + msg.SubIdx = block.SubIdx + + server.DbCtx.PoolBlkStats_ch <- msg + +} + +func NotifyBlkDetailDb(m *coin.MinerObj, height int64, hash string, success bool, miner_diff float64, pool_diff float64, nonce string, subidx int64) { + var msg db.BlkDetail_db_msg + msg.Id = 0 + msg.Msg = "blk_detail" + msg.Date = time.Now() + msg.MinerType = m.Name + + msg.User = m.User + msg.Miner = m.Miner + msg.Index = fmt.Sprint(m.MinerIndex) + + msg.Height = height + msg.Hash = hash + if success { + msg.Success = 1 + } else { + msg.Success = 0 + } + + msg.Miner_diff = miner_diff + msg.Pool_diff = pool_diff + msg.Nonce = nonce + msg.SubIdx = subidx + + //m.Server.DbCtx.BlkDetail_ch <- msg + db.Save_blk_detail(m.Server.DbCtx, &msg) +} + +func notify_miners_db(server *coin.ServerContext, DbCtx *db.DbContext) { + online_map := make(map[string]int) + server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + if m.User == "" || m.Miner == "" || fmt.Sprint(m.MinerIndex) == "" { + return true + } + if (m.Accepts > 0) && (m.Status == coin.MINER_STATUS_RUNNING) { + if time.Now().Sub(m.LastSubmitime).Seconds() <= 300 { + online_k := m.User + "." + m.Miner + "_" + fmt.Sprint(m.MinerIndex) + online_map[online_k] = 1 + } + } + } + } + } + return true + }) + + var miners_msg []db.Miners_db_msg + server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + if m.User == "" || m.Miner == "" || fmt.Sprint(m.MinerIndex) == "" { + return true + } + if m.Accepts > 0 /* || (m.Rejects > 0)*/ { + if (m.Status == coin.MINER_STATUS_DISCONNECTED) || (time.Now().Sub(m.LastSubmitime).Seconds() > 300) { + online_k := m.User + "." + m.Miner + "_" + fmt.Sprint(m.MinerIndex) + _, exists := online_map[online_k] + if !exists { + NotifyMinersDb(m, &miners_msg) + } + } else { + NotifyMinersDb(m, &miners_msg) + } + } + } + } + } + return true + }) + server.DbCtx.Miners_ch <- miners_msg +} + +func notify_miners_stats_db(server *coin.ServerContext, DbCtx *db.DbContext) { + var pool_accepts_5m float64 = 0 + var pool_accepts_15m float64 = 0 + var pool_accepts_30m float64 = 0 + var pool_accepts_1h float64 = 0 + var pool_accepts_3h float64 = 0 + var pool_accepts_6h float64 = 0 + var pool_accepts_12h float64 = 0 + var pool_accepts_24h float64 = 0 + var pool_accepts_48h float64 = 0 + + var pool_rejects_5m float64 = 0 + var pool_rejects_15m float64 = 0 + var pool_rejects_30m float64 = 0 + var pool_rejects_1h float64 = 0 + var pool_rejects_3h float64 = 0 + var pool_rejects_6h float64 = 0 + var pool_rejects_12h float64 = 0 + var pool_rejects_24h float64 = 0 + var pool_rejects_48h float64 = 0 + + var pool_mhs_5m float64 = 0 + var pool_mhs_15m float64 = 0 + var pool_mhs_30m float64 = 0 + var pool_mhs_1h float64 = 0 + var pool_mhs_3h float64 = 0 + var pool_mhs_6h float64 = 0 + var pool_mhs_12h float64 = 0 + var pool_mhs_24h float64 = 0 + var pool_mhs_48h float64 = 0 + + var pool_ratio_5m float64 = 0 + var pool_ratio_15m float64 = 0 + var pool_ratio_30m float64 = 0 + var pool_ratio_1h float64 = 0 + var pool_ratio_3h float64 = 0 + var pool_ratio_6h float64 = 0 + var pool_ratio_12h float64 = 0 + var pool_ratio_24h float64 = 0 + var pool_ratio_48h float64 = 0 + + var total_miners int64 = 0 + var miner_all []string + cmp := time.Now() + + var mhss_msg []db.MinersStats_db_msg + + server.MMhs.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*coin.MhsObj) + if ok { + if m != nil { + //server.Logg.Info("[mhs save]", zap.String("miner", m.User+"."+m.Miner), zap.Int("accepts", len(m.Accepts)), zap.Int("algo", m.Algo)) + + if m.User == "" || m.Miner == "" || m.Index == "" { + return true + } + + miner_all = append(miner_all, m.User+"."+m.Miner+"_"+m.Index) + + uminer, umok := server.Miners.Load(m.MinerId) + if !umok { + return true + } + + var miner coin.MinerObj + miner.Server = server + + var accepts_1h float64 = 0 + var accepts_24h float64 = 0 + + var accepts_m5 float64 = 0 + var accepts_m15 float64 = 0 + var accepts_m30 float64 = 0 + var accepts_3h float64 = 0 + var accepts_6h float64 = 0 + var accepts_12h float64 = 0 + var accepts_48h float64 = 0 + + var accepts_1h_cnt int64 = 0 + var accepts_24h_cnt int64 = 0 + + var accepts_m5_cnt float64 = 0 + var accepts_m15_cnt float64 = 0 + var accepts_m30_cnt float64 = 0 + var accepts_3h_cnt float64 = 0 + var accepts_6h_cnt float64 = 0 + var accepts_12h_cnt float64 = 0 + var accepts_48h_cnt float64 = 0 + + m.LockForMhs.Lock() + if len(m.Accepts) > 0 { + var i int = -1 + for i = len(m.Accepts) - 1; i >= 0; i-- { + tdiff := cmp.Sub(m.Accepts[i].Tt).Seconds() + if tdiff <= 3600 { + accepts_1h = accepts_1h + m.Accepts[i].Diff + accepts_1h_cnt++ + } + if tdiff <= 5*60 { + accepts_m5 = accepts_m5 + m.Accepts[i].Diff + accepts_m5_cnt++ + } + if tdiff <= 15*60 { + accepts_m15 = accepts_m15 + m.Accepts[i].Diff + accepts_m15_cnt++ + } + if tdiff <= 30*60 { + accepts_m30 = accepts_m30 + m.Accepts[i].Diff + accepts_m30_cnt++ + } + if tdiff <= 3*3600 { + accepts_3h = accepts_3h + m.Accepts[i].Diff + accepts_3h_cnt++ + } + if tdiff <= 6*3600 { + accepts_6h = accepts_6h + m.Accepts[i].Diff + accepts_6h_cnt++ + } + if tdiff <= 12*3600 { + accepts_12h = accepts_12h + m.Accepts[i].Diff + accepts_12h_cnt++ + } + if tdiff <= 24*3600 { + accepts_24h = accepts_24h + m.Accepts[i].Diff + accepts_24h_cnt++ + } + if tdiff <= 48*3600 { + accepts_48h = accepts_48h + m.Accepts[i].Diff + accepts_48h_cnt++ + } + } + m.LockForMhs.Unlock() + + miner.Accepts5M = accepts_m5 + miner.Accepts15M = accepts_m15 + miner.Accepts30M = accepts_m30 + miner.Accepts1h = accepts_1h + miner.Accepts3h = accepts_3h + miner.Accepts6h = accepts_6h + miner.Accepts12h = accepts_12h + miner.Accepts24h = accepts_24h + miner.Accepts48h = accepts_48h + + diffOneShareHashesAvg := uint64(0x00000000FFFFFFFF) + var coefficient float64 = 1 + miner.Mhs1h = accepts_1h * float64(diffOneShareHashesAvg) / coefficient / float64(3600) / 1000000 + //server.Logg.Info("[mhs save]", zap.Float64("mhs1h", msg.Mhs), zap.Float64("duration", mhs_duration), zap.Float64("diff", m.Difficulty)) + + miner.Mhs5M = accepts_m5 * float64(diffOneShareHashesAvg) / coefficient / float64(5*60) / 1000000 + miner.Mhs15M = accepts_m15 * float64(diffOneShareHashesAvg) / coefficient / float64(15*60) / 1000000 + miner.Mhs30M = accepts_m30 * float64(diffOneShareHashesAvg) / coefficient / float64(30*60) / 1000000 + miner.Mhs3h = accepts_3h * float64(diffOneShareHashesAvg) / coefficient / float64(3*3600) / 1000000 + miner.Mhs6h = accepts_6h * float64(diffOneShareHashesAvg) / coefficient / float64(6*3600) / 1000000 + miner.Mhs12h = accepts_12h * float64(diffOneShareHashesAvg) / coefficient / float64(12*3600) / 1000000 + miner.Mhs48h = accepts_48h * float64(diffOneShareHashesAvg) / coefficient / float64(48*3600) / 1000000 + miner.Mhs24h = accepts_24h * float64(diffOneShareHashesAvg) / coefficient / float64(3600*24) / 1000000 + + //server.Logg.Info("[mhs save]", zap.Int("accepts_24h", accepts_24h), zap.Float64("Mhs24h", msg.Mhs24h)) + } else { + m.LockForMhs.Unlock() + miner.Mhs1h = 0 + miner.Mhs24h = 0 + + miner.Mhs5M = 0 + miner.Mhs15M = 0 + miner.Mhs30M = 0 + miner.Mhs3h = 0 + miner.Mhs6h = 0 + miner.Mhs12h = 0 + miner.Mhs24h = 0 + } + + var rejects_1h_cnt int64 = 0 + var rejects_24h_cnt int64 = 0 + + var rejects_m5_cnt int64 = 0 + var rejects_m15_cnt int64 = 0 + var rejects_m30_cnt int64 = 0 + var rejects_3h_cnt int64 = 0 + var rejects_6h_cnt int64 = 0 + var rejects_12h_cnt int64 = 0 + var rejects_48h_cnt int64 = 0 + m.LockForMhs.Lock() + if len(m.Rejects) > 0 { + var j int = -1 + for j = 0; j < len(m.Rejects); j++ { + tdiff := cmp.Sub(m.Rejects[j].Tt).Seconds() + if tdiff <= 3600 { + rejects_1h_cnt++ + } + if tdiff <= 5*60 { + rejects_m5_cnt++ + } + if tdiff <= 15*60 { + rejects_m15_cnt++ + } + if tdiff <= 30*60 { + rejects_m30_cnt++ + } + if tdiff <= 3*3600 { + rejects_3h_cnt++ + } + if tdiff <= 6*3600 { + rejects_6h_cnt++ + } + if tdiff <= 12*3600 { + rejects_12h_cnt++ + } + if tdiff <= 24*3600 { + rejects_24h_cnt++ + } + if tdiff <= 48*3600 { + rejects_48h_cnt++ + } + } + } + m.LockForMhs.Unlock() + + miner.Rejects5M = float64(rejects_m5_cnt) + miner.Rejects15M = float64(rejects_m15_cnt) + miner.Rejects30M = float64(rejects_m30_cnt) + miner.Rejects1h = float64(rejects_1h_cnt) + miner.Rejects3h = float64(rejects_3h_cnt) + miner.Rejects6h = float64(rejects_6h_cnt) + miner.Rejects12h = float64(rejects_12h_cnt) + miner.Rejects24h = float64(rejects_24h_cnt) + miner.Rejects48h = float64(rejects_48h_cnt) + + miner.RejectRatio5M = 0 + if rejects_m5_cnt > 0 { + miner.RejectRatio5M = miner.Rejects5M / (miner.Rejects5M + float64(accepts_m5_cnt)) + } + miner.RejectRatio15M = 0 + if rejects_m15_cnt > 0 { + miner.RejectRatio15M = miner.Rejects15M / (miner.Rejects15M + float64(accepts_m15_cnt)) + } + miner.RejectRatio30M = 0 + if rejects_m30_cnt > 0 { + miner.RejectRatio30M = miner.Rejects30M / (miner.Rejects30M + float64(accepts_m30_cnt)) + } + miner.RejectRatio1h = 0 + if rejects_1h_cnt > 0 { + miner.RejectRatio1h = miner.Rejects1h / (miner.Rejects1h + float64(accepts_1h_cnt)) + } + miner.RejectRatio3h = 0 + if rejects_3h_cnt > 0 { + miner.RejectRatio3h = miner.Rejects3h / (miner.Rejects3h + float64(accepts_3h_cnt)) + } + miner.RejectRatio6h = 0 + if rejects_6h_cnt > 0 { + miner.RejectRatio6h = miner.Rejects6h / (miner.Rejects6h + float64(accepts_6h_cnt)) + } + miner.RejectRatio12h = 0 + if rejects_12h_cnt > 0 { + miner.RejectRatio12h = miner.Rejects12h / (miner.Rejects12h + float64(accepts_12h_cnt)) + } + miner.RejectRatio24h = 0 + if rejects_24h_cnt > 0 { + miner.RejectRatio24h = miner.Rejects24h / (miner.Rejects24h + float64(accepts_24h_cnt)) + } + miner.RejectRatio48h = 0 + if rejects_48h_cnt > 0 { + miner.RejectRatio48h = miner.Rejects48h / (miner.Rejects48h + float64(accepts_48h_cnt)) + } + + pool_accepts_5m = pool_accepts_5m + miner.Accepts5M + pool_accepts_15m = pool_accepts_15m + miner.Accepts15M + pool_accepts_30m = pool_accepts_30m + miner.Accepts30M + pool_accepts_1h = pool_accepts_1h + miner.Accepts1h + pool_accepts_3h = pool_accepts_3h + miner.Accepts3h + pool_accepts_6h = pool_accepts_6h + miner.Accepts6h + pool_accepts_12h = pool_accepts_12h + miner.Accepts12h + pool_accepts_24h = pool_accepts_24h + miner.Accepts24h + pool_accepts_48h = pool_accepts_48h + miner.Accepts48h + + pool_rejects_5m = pool_rejects_5m + miner.Rejects5M + pool_rejects_15m = pool_rejects_15m + miner.Rejects15M + pool_rejects_30m = pool_rejects_30m + miner.Rejects30M + pool_rejects_1h = pool_rejects_1h + miner.Rejects1h + pool_rejects_3h = pool_rejects_3h + miner.Rejects3h + pool_rejects_6h = pool_rejects_6h + miner.Rejects6h + pool_rejects_12h = pool_rejects_12h + miner.Rejects12h + pool_rejects_24h = pool_rejects_24h + miner.Rejects24h + pool_rejects_48h = pool_rejects_48h + miner.Rejects48h + + pool_mhs_5m = pool_mhs_5m + miner.Mhs5M + pool_mhs_15m = pool_mhs_15m + miner.Mhs15M + pool_mhs_30m = pool_mhs_30m + miner.Mhs30M + pool_mhs_1h = pool_mhs_1h + miner.Mhs1h + pool_mhs_3h = pool_mhs_3h + miner.Mhs3h + pool_mhs_6h = pool_mhs_6h + miner.Mhs6h + pool_mhs_12h = pool_mhs_12h + miner.Mhs12h + pool_mhs_24h = pool_mhs_24h + miner.Mhs24h + pool_mhs_48h = pool_mhs_48h + miner.Mhs48h + + pool_ratio_5m = pool_ratio_5m + miner.RejectRatio5M + pool_ratio_15m = pool_ratio_15m + miner.RejectRatio15M + pool_ratio_30m = pool_ratio_30m + miner.RejectRatio30M + pool_ratio_1h = pool_ratio_1h + miner.RejectRatio1h + pool_ratio_3h = pool_ratio_3h + miner.RejectRatio3h + pool_ratio_6h = pool_ratio_6h + miner.RejectRatio6h + pool_ratio_12h = pool_ratio_12h + miner.RejectRatio12h + pool_ratio_24h = pool_ratio_24h + miner.RejectRatio24h + pool_ratio_48h = pool_ratio_48h + miner.RejectRatio48h + + miner.Name = m.Name + miner.User = m.User + miner.Miner = m.Miner + miner.MinerIndex, _ = strconv.ParseInt(m.Index, 10, 64) + + NotifyMinersStatsDb(&miner, &mhss_msg) + + //fmt.Printf("notify_miners_stats_db store miner miner %v, miner_id %v, umok %v\n", uminer, m.MinerId, umok) + if umok { + up_miner := uminer.(*coin.MinerObj) + if up_miner != nil { + up_miner.Accepts5M = miner.Accepts5M + up_miner.Accepts15M = miner.Accepts15M + up_miner.Accepts30M = miner.Accepts30M + up_miner.Accepts1h = miner.Accepts1h + up_miner.Accepts3h = miner.Accepts3h + up_miner.Accepts6h = miner.Accepts6h + up_miner.Accepts12h = miner.Accepts12h + up_miner.Accepts24h = miner.Accepts24h + up_miner.Accepts48h = miner.Accepts48h + + up_miner.Rejects5M = miner.Rejects5M + up_miner.Rejects15M = miner.Rejects15M + up_miner.Rejects30M = miner.Rejects30M + up_miner.Rejects1h = miner.Rejects1h + up_miner.Rejects3h = miner.Rejects3h + up_miner.Rejects6h = miner.Rejects6h + up_miner.Rejects12h = miner.Rejects12h + up_miner.Rejects24h = miner.Rejects24h + up_miner.Rejects48h = miner.Rejects48h + + up_miner.Mhs5M = miner.Mhs5M + up_miner.Mhs15M = miner.Mhs15M + up_miner.Mhs30M = miner.Mhs30M + up_miner.Mhs1h = miner.Mhs1h + up_miner.Mhs3h = miner.Mhs3h + up_miner.Mhs6h = miner.Mhs6h + up_miner.Mhs12h = miner.Mhs12h + up_miner.Mhs24h = miner.Mhs24h + up_miner.Mhs48h = miner.Mhs48h + + up_miner.RejectRatio5M = miner.RejectRatio5M + up_miner.RejectRatio15M = miner.RejectRatio15M + up_miner.RejectRatio30M = miner.RejectRatio30M + up_miner.RejectRatio1h = miner.RejectRatio1h + up_miner.RejectRatio3h = miner.RejectRatio3h + up_miner.RejectRatio6h = miner.RejectRatio6h + up_miner.RejectRatio12h = miner.RejectRatio12h + up_miner.RejectRatio24h = miner.RejectRatio24h + up_miner.RejectRatio48h = miner.RejectRatio48h + //fmt.Printf("notify_miners_stats_db store miner mhs5m %v, miner_id %v, %v\n", up_miner.Mhs5M, up_miner.MinerId, up_miner) + } + } + + total_miners++ + } + } + } + return true + }) + server.DbCtx.MinersStats_ch <- mhss_msg + + server.Accepts5M = pool_accepts_5m + server.Accepts15M = pool_accepts_15m + server.Accepts30M = pool_accepts_30m + server.Accepts1h = pool_accepts_1h + server.Accepts3h = pool_accepts_3h + server.Accepts6h = pool_accepts_6h + server.Accepts12h = pool_accepts_12h + server.Accepts24h = pool_accepts_24h + server.Accepts48h = pool_accepts_48h + + server.Rejects5M = pool_rejects_5m + server.Rejects15M = pool_rejects_15m + server.Rejects30M = pool_rejects_30m + server.Rejects1h = pool_rejects_1h + server.Rejects3h = pool_rejects_3h + server.Rejects6h = pool_rejects_6h + server.Rejects12h = pool_rejects_12h + server.Rejects24h = pool_rejects_24h + server.Rejects48h = pool_rejects_48h + + server.Mhs5M = pool_mhs_5m + server.Mhs15M = pool_mhs_15m + server.Mhs30M = pool_mhs_30m + server.Mhs1h = pool_mhs_1h + server.Mhs3h = pool_mhs_3h + server.Mhs6h = pool_mhs_6h + server.Mhs12h = pool_mhs_12h + server.Mhs24h = pool_mhs_24h + server.Mhs48h = pool_mhs_48h + + server.RejectRatio5M = pool_ratio_5m / float64(total_miners) + server.RejectRatio15M = pool_ratio_15m / float64(total_miners) + server.RejectRatio30M = pool_ratio_30m / float64(total_miners) + server.RejectRatio1h = pool_ratio_1h / float64(total_miners) + server.RejectRatio3h = pool_ratio_3h / float64(total_miners) + server.RejectRatio6h = pool_ratio_6h / float64(total_miners) + server.RejectRatio12h = pool_ratio_12h / float64(total_miners) + server.RejectRatio24h = pool_ratio_24h / float64(total_miners) + server.RejectRatio48h = pool_ratio_48h / float64(total_miners) + + //NotifyPoolStatsDb(server) + + //NotifyPoolDb(server) + + //server.Logg.Info("[mhs save]", zap.Int("24hupdate", len(miner_all))) + var total int = 0 + for miner_idx := 0; miner_idx < len(miner_all); miner_idx++ { + v, ok := server.MMhs.Load(miner_all[miner_idx]) + if ok { + if v != nil { + var m *coin.MhsObj = v.(*coin.MhsObj) + if m != nil { + /*if (m.Status == coin.MINER_STATUS_DISCONNECTED) && (m.Release) { + m.Release = false + m.Accepts = nil + m.Rejects = nil + server.MMhs.Store(miner_all[miner_idx], nil) + server.MMhs.Delete(miner_all[miner_idx]) + continue + }*/ + if cmp.Sub(m.StartDayTime).Seconds() > 3600*24 { + //server.Logg.Info("[mhs save 1]", zap.String("miner", m.User+"."+m.Miner), zap.Int("accepts", len(m.Accepts)), zap.Int("rejects", len(m.Rejects))) + m.StartDayTime = m.StartDayTime.Add(time.Hour * 1) + m.LockForMhs.Lock() + if len(m.Accepts) > 0 { + var i int = 0 + for i = 0; i < len(m.Accepts); i++ { + if cmp.Sub(m.Accepts[i].Tt).Seconds() <= 3600*24 { + break + } + } + if i > 0 { + //for cnt := 0; cnt < i; cnt++ { + //cache.RemoveMhsCache(server.RedisClient, server.MinerType, m.User, m.Miner, m.Index, "accepts") + //} + /*as := m.Accepts[i:] + m.Accepts = as*/ + newAccepts := make([]coin.MhsItem, len(m.Accepts)-i) + copy(newAccepts, m.Accepts[i:]) + //m.Accepts = nil + m.Accepts = newAccepts + } else { + m.Accepts = nil + } + } + if len(m.Rejects) > 0 { + var i int = 0 + for i = 0; i < len(m.Rejects); i++ { + if cmp.Sub(m.Rejects[i].Tt).Seconds() <= 3600*24 { + break + } + } + if i > 0 { + //for cnt := 0; cnt < i; cnt++ { + //cache.RemoveMhsCache(server.RedisClient, server.MinerType, m.User, m.Miner, m.Index, "rejects") + //} + /*rs := m.Rejects[i:] + m.Rejects = rs*/ + newRejects := make([]coin.MhsItem, len(m.Rejects)-i) + copy(newRejects, m.Rejects[i:]) + //m.Rejects = nil + m.Rejects = newRejects + } else { + m.Rejects = nil + } + } + m.LockForMhs.Unlock() + //server.Logg.Info("[mhs save 1]", zap.String("miner", m.User+"."+m.Miner), zap.Int("accepts", len(m.Accepts)), zap.Int("rejects", len(m.Rejects))) + } + + server.MMhs.Store(miner_all[miner_idx], m) + //cache.StoreMhsCache(server.RedisClient, server.MinerType, m.User, m.Miner, m.Index, "starttime", m.StartDayTime) + total++ + } + } + } + } + //server.Logg.Info("[mhs save]", zap.Int("24hupdate", total)) +} + +/*func notify_users_db(server *coin.ServerContext, DbCtx *db.DbContext) { + server.Users.Range(func(k, v interface{}) bool { + u_sets, ok := v.(coin.UserMinerContainer) + if ok { + var u coin.UserObj + u.Server = server + u.User = k.(string) + user := strings.TrimSuffix(u.User, "00000000") + u.User = user + u.Name = server.MinerType + + u.Normal = 0 + u.Abnormal = 0 + + u.Offline = 0 + u.MhsZero = 0 + u.MhsLow = 0 + u.HighRejects = 0 + u.Unstable = 0 + + u.Submits = 0 + u.Blocks = 0 + u.Orphans = 0 + + u.Reward = 0 + u.Fee = 0 + //fmt.Printf("-->notify_users_db user %v data %v", u.User, u_sets.Data) + for _, miner_id := range u_sets.Data { + mobj, mok := server.Miners.Load(miner_id) + //fmt.Printf("-->notify_users_db miner_id %v, miner_obj %v\n", miner_id, mobj) + if mok { + m := mobj.(*coin.MinerObj) + u.Submits = u.Submits + int64(m.Submits) + u.Blocks = u.Blocks + int64(m.Blocks) + u.Orphans = u.Orphans + int64(m.Orphans) + + u.Reward = u.Reward + m.Reward + u.Fee = u.Fee + m.Fee + } + } + + NotifyUsersDb(&u) + } + return true + }) +}*/ + +/*func notify_users_stats_db(server *coin.ServerContext, DbCtx *db.DbContext) { + server.Users.Range(func(k, v interface{}) bool { + //fmt.Printf("notify_users_stats_db user=%v, value=%v\n", k, v) + u_sets, ok := v.(coin.UserMinerContainer) + if ok { + var u coin.UserObj + u.Server = server + u.User = k.(string) + user := strings.TrimSuffix(u.User, "00000000") + u.User = user + u.Name = server.MinerType + + u.Accepts5M = 0 + u.Accepts15M = 0 + u.Accepts30M = 0 + u.Accepts1h = 0 + u.Accepts3h = 0 + u.Accepts6h = 0 + u.Accepts12h = 0 + u.Accepts24h = 0 + u.Accepts48h = 0 + + u.Rejects5M = 0 + u.Rejects15M = 0 + u.Rejects30M = 0 + u.Rejects1h = 0 + u.Rejects3h = 0 + u.Rejects6h = 0 + u.Rejects12h = 0 + u.Rejects24h = 0 + u.Rejects48h = 0 + + u.Mhs5M = 0 + u.Mhs15M = 0 + u.Mhs30M = 0 + u.Mhs1h = 0 + u.Mhs3h = 0 + u.Mhs6h = 0 + u.Mhs12h = 0 + u.Mhs24h = 0 + u.Mhs48h = 0 + + u.RejectRatio5M = 0 + u.RejectRatio15M = 0 + u.RejectRatio30M = 0 + u.RejectRatio1h = 0 + u.RejectRatio3h = 0 + u.RejectRatio6h = 0 + u.RejectRatio12h = 0 + u.RejectRatio24h = 0 + u.RejectRatio48h = 0 + + var total_miners int64 = 0 + for _, miner_id := range u_sets.Data { + //fmt.Printf("notify_users_stats_db user=%v, miner=%v\n", k, miner_id) + mobj, mok := server.Miners.Load(miner_id) + //fmt.Printf("notify_users_stats_db miner=%v,mobj=%v, mok=%v\n", miner_id, mobj, mok) + if mok { + m := mobj.(*coin.MinerObj) + u.Accepts5M = u.Accepts5M + m.Accepts5M + //fmt.Printf("notify_users_stats_db, Accepts5M %v, %v", u.Accepts5M, m.Accepts5M) + u.Accepts15M = u.Accepts15M + m.Accepts15M + u.Accepts30M = u.Accepts30M + m.Accepts30M + u.Accepts1h = u.Accepts1h + m.Accepts1h + u.Accepts3h = u.Accepts3h + m.Accepts3h + u.Accepts6h = u.Accepts6h + m.Accepts6h + u.Accepts12h = u.Accepts12h + m.Accepts12h + u.Accepts24h = u.Accepts24h + m.Accepts24h + u.Accepts48h = u.Accepts48h + m.Accepts48h + + u.Rejects5M = u.Rejects5M + m.Rejects5M + u.Rejects15M = u.Rejects15M + m.Rejects15M + u.Rejects30M = u.Rejects30M + m.Rejects30M + u.Rejects1h = u.Rejects1h + m.Rejects1h + u.Rejects3h = u.Rejects3h + m.Rejects3h + u.Rejects6h = u.Rejects6h + m.Rejects6h + u.Rejects12h = u.Rejects12h + m.Rejects12h + u.Rejects24h = u.Rejects24h + m.Rejects24h + u.Rejects48h = u.Rejects48h + m.Rejects48h + + u.Mhs5M = u.Mhs5M + m.Mhs5M + u.Mhs15M = u.Mhs15M + m.Mhs15M + u.Mhs30M = u.Mhs30M + m.Mhs30M + u.Mhs1h = u.Mhs1h + m.Mhs1h + u.Mhs3h = u.Mhs3h + m.Mhs3h + u.Mhs6h = u.Mhs6h + m.Mhs6h + u.Mhs12h = u.Mhs12h + m.Mhs12h + u.Mhs24h = u.Mhs24h + m.Mhs24h + u.Mhs48h = u.Mhs48h + m.Mhs48h + + u.RejectRatio5M = u.RejectRatio5M + m.RejectRatio5M + u.RejectRatio15M = u.RejectRatio15M + m.RejectRatio15M + u.RejectRatio30M = u.RejectRatio30M + m.RejectRatio30M + u.RejectRatio1h = u.RejectRatio1h + m.RejectRatio1h + u.RejectRatio3h = u.RejectRatio3h + m.RejectRatio3h + u.RejectRatio6h = u.RejectRatio6h + m.RejectRatio6h + u.RejectRatio12h = u.RejectRatio12h + m.RejectRatio12h + u.RejectRatio24h = u.RejectRatio24h + m.RejectRatio24h + u.RejectRatio48h = u.RejectRatio48h + m.RejectRatio48h + + total_miners++ + } + } + if total_miners > 0 { + u.RejectRatio5M = u.RejectRatio5M / float64(total_miners) + u.RejectRatio15M = u.RejectRatio15M / float64(total_miners) + u.RejectRatio30M = u.RejectRatio30M / float64(total_miners) + u.RejectRatio1h = u.RejectRatio1h / float64(total_miners) + u.RejectRatio3h = u.RejectRatio3h / float64(total_miners) + u.RejectRatio6h = u.RejectRatio6h / float64(total_miners) + u.RejectRatio12h = u.RejectRatio12h / float64(total_miners) + u.RejectRatio24h = u.RejectRatio24h / float64(total_miners) + u.RejectRatio48h = u.RejectRatio48h / float64(total_miners) + //fmt.Printf("notify_users_stats_db, total %v, accept %v", total_miners, u.Accepts5M) + NotifyUsersStatsDb(&u) + } + } + return true + }) +}*/ + +func Handle_miners_timer(server *coin.ServerContext, DbCtx *db.DbContext) { + timer := time.NewTimer(time.Minute * MINER_UPDATE_MINERS_DB_DURATION) + for { + select { + case <-timer.C: + notify_miners_db(server, DbCtx) + notify_miners_stats_db(server, DbCtx) + //notify_users_db(server, DbCtx) + //notify_users_stats_db(server, DbCtx) + timer.Reset(time.Minute * MINER_UPDATE_MINERS_DB_DURATION) + case <-(server.ExitDbMiners): + log.Println("[server]", "Handle_user_timer exited.") + timer.Stop() + return + } + } +} + +/* +func Handle_miners_stats_timer(server *coin.ServerContext, DbCtx *db.DbContext) { + timer := time.NewTimer(time.Minute * MINER_UPDATE_MINERS_STATS_DB_DURATION) + for { + select { + case <-timer.C: + notify_miners_stats_db(server, DbCtx) + timer.Reset(time.Minute * MINER_UPDATE_MINERS_STATS_DB_DURATION) + case <-(server.ExitDbMinersStats): + log.Println("[server]", "Handle_miners_stats_timer exited.") + timer.Stop() + + return + } + } +}*/ +/* +func Handle_users_timer(server *coin.ServerContext, DbCtx *db.DbContext) { + timer := time.NewTimer(time.Minute * MINER_UPDATE_USERS_DB_DURATION) + for { + select { + case <-timer.C: + + notify_users_db(server, DbCtx) + timer.Reset(time.Minute * MINER_UPDATE_USERS_DB_DURATION) + case <-(server.ExitDbUser): + log.Println("[server]", "Handle_users_timer exited.") + timer.Stop() + + return + } + } +}*/ +/* +func Handle_users_stats_timer(server *coin.ServerContext, DbCtx *db.DbContext) { + timer := time.NewTimer(time.Minute * MINER_UPDATE_USERS_STATS_DB_DURATION) + for { + select { + case <-timer.C: + notify_users_stats_db(server, DbCtx) + timer.Reset(time.Minute * MINER_UPDATE_USERS_STATS_DB_DURATION) + case <-(server.ExitDbUserStats): + log.Println("[server]", "Handle_users_stats_timer exited.") + timer.Stop() + + return + } + } +}*/ diff --git a/internal/server/diff/diff.go b/internal/server/diff/diff.go new file mode 100644 index 0000000..b68458c --- /dev/null +++ b/internal/server/diff/diff.go @@ -0,0 +1,170 @@ +// diff.go +package diff + +import ( + "fmt" + "math" + "strconv" + "strings" +) + +type KalmanVarDiff struct { + Kf *KalmanFilter + + StartDiff float64 + MinDiff float64 + MaxDiff float64 + + TargetInterval float64 + + MhsEst float64 + DiffEst float64 +} + +type KalmanFilter struct { + X float64 // 估计的状态 + P float64 // 状态协方差 + F float64 // 状态转移矩阵 + H float64 // 观测矩阵 + Q float64 // 过程噪声协方差 + R float64 // 观测噪声协方差 + K float64 // 卡尔曼增益 +} + +func NewKalmanFilter(init_mhs float64, init_state_p float64) *KalmanFilter { + x := init_mhs + p := init_state_p + f := 1.0 + h := 1.0 + q := 0.01 + r := init_mhs * 3 + //r := 1.0 + return &KalmanFilter{ + X: x, + P: p, + F: f, + H: h, + Q: q, + R: r, + } + /* + return &KalmanFilter{ + X: 1.0, + P: 1.0, + F: 1.0, + H: 1.0, + Q: 0.1, + R: 1.0, + }*/ +} + +func (kf *KalmanFilter) Update(measurement float64) (float64, float64) { + kf.R = measurement * 2 + + // 预测 + p := kf.X*kf.Q + kf.P + + // 计算卡尔曼增益 + kf.K = p / (p + kf.R + 1) + + // 更新状态估计 + if measurement >= kf.X { + kf.X = kf.X + kf.K*(measurement-kf.X) + } else { + kf.X = kf.X - kf.K*(kf.X-measurement) + } + + // 更新协方差矩阵 + kf.P = (1 - kf.K) * p + + // 自适应调整过程噪声和观测噪声 + //kf.adapt() + + return kf.X, kf.P +} + +func (kf *KalmanFilter) adapt() { + // 自适应调整参数 + if kf.P > 10.0 { + kf.Q *= 1.1 // 增加过程噪声 + } else { + kf.Q *= 0.9 // 减少过程噪声 + } + if kf.K > 0.5 { + kf.R *= 1.1 // 增加观测噪声 + } else { + kf.R *= 0.9 // 减少观测噪声 + } +} + +func (kd *KalmanVarDiff) Init(startDiff float64, minDiff float64, maxDiff float64, targetTime float64) { + kd.StartDiff = startDiff + kd.MinDiff = minDiff + kd.MaxDiff = maxDiff + kd.TargetInterval = targetTime + kd.DiffEst = startDiff + kd.MhsEst = startDiff / targetTime + kd.Kf = NewKalmanFilter(startDiff/targetTime, 1.0) +} + +func (kd *KalmanVarDiff) DeInit() { + +} + +// 提取科学计数法有效数字(整数部分和一位小数)及指数,并合并为新的浮点数 +func extractAndCombine(num float64) float64 { + // 将浮点数格式化为科学计数法 + scientificStr := fmt.Sprintf("%.10e", num) + + // 分离小数部分和指数部分 + parts := strings.Split(scientificStr, "e") + if len(parts) != 2 { + fmt.Println("Error: unexpected scientific notation format") + return 0 + } + + // 处理小数部分 + decimalPart := parts[0] + exponentPart := parts[1] + + // 去除小数部分前的 "0." + decimalPart = strings.TrimPrefix(decimalPart, "0.") + + // 提取整数部分和一位小数 + decimalParts := strings.Split(decimalPart, ".") + if len(decimalParts) < 2 { + decimalPart = decimalParts[0] + ".0" // 没有小数部分时,添加 ".0" + } else { + decimalPart = decimalParts[0] + "." + decimalParts[1][:1] // 只取一位小数 + //decimalPart = decimalParts[0] + } + + // 将指数部分转换为整数 + exponent, err := strconv.Atoi(exponentPart) + if err != nil { + fmt.Println("Error parsing exponent:", err) + return 0 + } + + // 计算新的浮点数 + newNumber := (func() float64 { + digit, err := strconv.ParseFloat(decimalPart, 64) + if err != nil { + fmt.Println("Error parsing decimal part:", err) + return 0 + } + return digit * math.Pow(10, float64(exponent)) + })() + + return newNumber +} + +func (kd *KalmanVarDiff) Handler(diff float64, interval float64) (float64, float64) { + //newx, newp := kd.Kf.Update(kd.DiffEst / interval) + newx, newp := kd.Kf.Update(diff / interval) + kd.MhsEst = newx + newdiff := newx * kd.TargetInterval + kd.DiffEst = newdiff + newdiff2 := extractAndCombine(newdiff) + return newdiff2, newp +} diff --git a/internal/server/include/nexaapi.h b/internal/server/include/nexaapi.h new file mode 100644 index 0000000..45b528b --- /dev/null +++ b/internal/server/include/nexaapi.h @@ -0,0 +1,14 @@ +#ifndef NEXAAPI_H +#define NEXAAPI_H +#include +#ifdef __cplusplus +extern "C" { +#endif + +bool nexa_hash( unsigned char *out, unsigned char *in); +bool nexa_hash12( unsigned char *out, unsigned char *in); +#ifdef __cplusplus +} +#endif + +#endif diff --git a/internal/server/include/randomx.h b/internal/server/include/randomx.h new file mode 100644 index 0000000..4cd919e --- /dev/null +++ b/internal/server/include/randomx.h @@ -0,0 +1,288 @@ +/* +Copyright (c) 2018-2019, tevador + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * 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. + * 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. +*/ + +#ifndef RANDOMX_H +#define RANDOMX_H + +#include +#include + +#define RANDOMX_HASH_SIZE 32 +#define RANDOMX_DATASET_ITEM_SIZE 64 + +#ifndef RANDOMX_EXPORT +#define RANDOMX_EXPORT +#endif + +typedef enum { + RANDOMX_FLAG_DEFAULT = 0, + RANDOMX_FLAG_LARGE_PAGES = 1, + RANDOMX_FLAG_HARD_AES = 2, + RANDOMX_FLAG_FULL_MEM = 4, + RANDOMX_FLAG_JIT = 8, + RANDOMX_FLAG_SECURE = 16, + RANDOMX_FLAG_ARGON2_SSSE3 = 32, + RANDOMX_FLAG_ARGON2_AVX2 = 64, + RANDOMX_FLAG_ARGON2 = 96 +} randomx_flags; + +typedef struct randomx_dataset randomx_dataset; +typedef struct randomx_cache randomx_cache; +typedef struct randomx_vm randomx_vm; + + +#if defined(__cplusplus) + +#ifdef __cpp_constexpr +#define CONSTEXPR constexpr +#else +#define CONSTEXPR +#endif + +inline CONSTEXPR randomx_flags operator |(randomx_flags a, randomx_flags b) { + return static_cast(static_cast(a) | static_cast(b)); +} +inline CONSTEXPR randomx_flags operator &(randomx_flags a, randomx_flags b) { + return static_cast(static_cast(a) & static_cast(b)); +} +inline randomx_flags& operator |=(randomx_flags& a, randomx_flags b) { + return a = a | b; +} + +extern "C" { +#endif + +/** + * @return The recommended flags to be used on the current machine. + * Does not include: + * RANDOMX_FLAG_LARGE_PAGES + * RANDOMX_FLAG_FULL_MEM + * RANDOMX_FLAG_SECURE + * These flags must be added manually if desired. + * On OpenBSD RANDOMX_FLAG_SECURE is enabled by default in JIT mode as W^X is enforced by the OS. + */ +RANDOMX_EXPORT randomx_flags randomx_get_flags(void); + +/** + * Creates a randomx_cache structure and allocates memory for RandomX Cache. + * + * @param flags is any combination of these 2 flags (each flag can be set or not set): + * RANDOMX_FLAG_LARGE_PAGES - allocate memory in large pages + * RANDOMX_FLAG_JIT - create cache structure with JIT compilation support; this makes + * subsequent Dataset initialization faster + * Optionally, one of these two flags may be selected: + * RANDOMX_FLAG_ARGON2_SSSE3 - optimized Argon2 for CPUs with the SSSE3 instruction set + * makes subsequent cache initialization faster + * RANDOMX_FLAG_ARGON2_AVX2 - optimized Argon2 for CPUs with the AVX2 instruction set + * makes subsequent cache initialization faster + * + * @return Pointer to an allocated randomx_cache structure. + * Returns NULL if: + * (1) memory allocation fails + * (2) the RANDOMX_FLAG_JIT is set and JIT compilation is not supported on the current platform + * (3) an invalid or unsupported RANDOMX_FLAG_ARGON2 value is set + */ +RANDOMX_EXPORT randomx_cache *randomx_alloc_cache(randomx_flags flags); + +/** + * Initializes the cache memory and SuperscalarHash using the provided key value. + * Does nothing if called again with the same key value. + * + * @param cache is a pointer to a previously allocated randomx_cache structure. Must not be NULL. + * @param key is a pointer to memory which contains the key value. Must not be NULL. + * @param keySize is the number of bytes of the key. +*/ +RANDOMX_EXPORT void randomx_init_cache(randomx_cache *cache, const void *key, size_t keySize); + +/** + * Returns a pointer to the internal memory buffer of the cache structure. The size + * of the internal memory buffer is RANDOMX_ARGON_MEMORY KiB. + * + * @param cache is a pointer to a previously allocated randomx_cache structure. Must not be NULL. + * + * @return Pointer to the internal memory buffer of the cache structure. +*/ +RANDOMX_EXPORT void *randomx_get_cache_memory(randomx_cache *cache); + +/** + * Releases all memory occupied by the randomx_cache structure. + * + * @param cache is a pointer to a previously allocated randomx_cache structure. +*/ +RANDOMX_EXPORT void randomx_release_cache(randomx_cache* cache); + +/** + * Creates a randomx_dataset structure and allocates memory for RandomX Dataset. + * + * @param flags is the initialization flags. Only one flag is supported (can be set or not set): + * RANDOMX_FLAG_LARGE_PAGES - allocate memory in large pages + * + * @return Pointer to an allocated randomx_dataset structure. + * NULL is returned if memory allocation fails. + */ +RANDOMX_EXPORT randomx_dataset *randomx_alloc_dataset(randomx_flags flags); + +/** + * Gets the number of items contained in the dataset. + * + * @return the number of items contained in the dataset. +*/ +RANDOMX_EXPORT unsigned long randomx_dataset_item_count(void); + +/** + * Initializes dataset items. + * + * Note: In order to use the Dataset, all items from 0 to (randomx_dataset_item_count() - 1) must be initialized. + * This may be done by several calls to this function using non-overlapping item sequences. + * + * @param dataset is a pointer to a previously allocated randomx_dataset structure. Must not be NULL. + * @param cache is a pointer to a previously allocated and initialized randomx_cache structure. Must not be NULL. + * @param startItem is the item number where initialization should start. + * @param itemCount is the number of items that should be initialized. +*/ +RANDOMX_EXPORT void randomx_init_dataset(randomx_dataset *dataset, randomx_cache *cache, unsigned long startItem, unsigned long itemCount); + +/** + * Returns a pointer to the internal memory buffer of the dataset structure. The size + * of the internal memory buffer is randomx_dataset_item_count() * RANDOMX_DATASET_ITEM_SIZE. + * + * @param dataset is a pointer to a previously allocated randomx_dataset structure. Must not be NULL. + * + * @return Pointer to the internal memory buffer of the dataset structure. +*/ +RANDOMX_EXPORT void *randomx_get_dataset_memory(randomx_dataset *dataset); + +/** + * Releases all memory occupied by the randomx_dataset structure. + * + * @param dataset is a pointer to a previously allocated randomx_dataset structure. +*/ +RANDOMX_EXPORT void randomx_release_dataset(randomx_dataset *dataset); + +/** + * Creates and initializes a RandomX virtual machine. + * + * @param flags is any combination of these 5 flags (each flag can be set or not set): + * RANDOMX_FLAG_LARGE_PAGES - allocate scratchpad memory in large pages + * RANDOMX_FLAG_HARD_AES - virtual machine will use hardware accelerated AES + * RANDOMX_FLAG_FULL_MEM - virtual machine will use the full dataset + * RANDOMX_FLAG_JIT - virtual machine will use a JIT compiler + * RANDOMX_FLAG_SECURE - when combined with RANDOMX_FLAG_JIT, the JIT pages are never + * writable and executable at the same time (W^X policy) + * The numeric values of the first 4 flags are ordered so that a higher value will provide + * faster hash calculation and a lower numeric value will provide higher portability. + * Using RANDOMX_FLAG_DEFAULT (all flags not set) works on all platforms, but is the slowest. + * @param cache is a pointer to an initialized randomx_cache structure. Can be + * NULL if RANDOMX_FLAG_FULL_MEM is set. + * @param dataset is a pointer to a randomx_dataset structure. Can be NULL + * if RANDOMX_FLAG_FULL_MEM is not set. + * + * @return Pointer to an initialized randomx_vm structure. + * Returns NULL if: + * (1) Scratchpad memory allocation fails. + * (2) The requested initialization flags are not supported on the current platform. + * (3) cache parameter is NULL and RANDOMX_FLAG_FULL_MEM is not set + * (4) dataset parameter is NULL and RANDOMX_FLAG_FULL_MEM is set +*/ +RANDOMX_EXPORT randomx_vm *randomx_create_vm(randomx_flags flags, randomx_cache *cache, randomx_dataset *dataset); + +/** + * Reinitializes a virtual machine with a new Cache. This function should be called anytime + * the Cache is reinitialized with a new key. Does nothing if called with a Cache containing + * the same key value as already set. + * + * @param machine is a pointer to a randomx_vm structure that was initialized + * without RANDOMX_FLAG_FULL_MEM. Must not be NULL. + * @param cache is a pointer to an initialized randomx_cache structure. Must not be NULL. +*/ +RANDOMX_EXPORT void randomx_vm_set_cache(randomx_vm *machine, randomx_cache* cache); + +/** + * Reinitializes a virtual machine with a new Dataset. + * + * @param machine is a pointer to a randomx_vm structure that was initialized + * with RANDOMX_FLAG_FULL_MEM. Must not be NULL. + * @param dataset is a pointer to an initialized randomx_dataset structure. Must not be NULL. +*/ +RANDOMX_EXPORT void randomx_vm_set_dataset(randomx_vm *machine, randomx_dataset *dataset); + +/** + * Releases all memory occupied by the randomx_vm structure. + * + * @param machine is a pointer to a previously created randomx_vm structure. +*/ +RANDOMX_EXPORT void randomx_destroy_vm(randomx_vm *machine); + +/** + * Calculates a RandomX hash value. + * + * @param machine is a pointer to a randomx_vm structure. Must not be NULL. + * @param input is a pointer to memory to be hashed. Must not be NULL. + * @param inputSize is the number of bytes to be hashed. + * @param output is a pointer to memory where the hash will be stored. Must not + * be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing. +*/ +RANDOMX_EXPORT void randomx_calculate_hash(randomx_vm *machine, const void *input, size_t inputSize, void *output); + +/** + * Set of functions used to calculate multiple RandomX hashes more efficiently. + * randomx_calculate_hash_first will begin a hash calculation. + * randomx_calculate_hash_next will output the hash value of the previous input + * and begin the calculation of the next hash. + * randomx_calculate_hash_last will output the hash value of the previous input. + * + * WARNING: These functions may alter the floating point rounding mode of the calling thread. + * + * @param machine is a pointer to a randomx_vm structure. Must not be NULL. + * @param input is a pointer to memory to be hashed. Must not be NULL. + * @param inputSize is the number of bytes to be hashed. + * @param nextInput is a pointer to memory to be hashed for the next hash. Must not be NULL. + * @param nextInputSize is the number of bytes to be hashed for the next hash. + * @param output is a pointer to memory where the hash will be stored. Must not + * be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing. +*/ +RANDOMX_EXPORT void randomx_calculate_hash_first(randomx_vm* machine, const void* input, size_t inputSize); +RANDOMX_EXPORT void randomx_calculate_hash_next(randomx_vm* machine, const void* nextInput, size_t nextInputSize, void* output); +RANDOMX_EXPORT void randomx_calculate_hash_last(randomx_vm* machine, void* output); + +/** + * Calculate a RandomX commitment from a RandomX hash and its input. + * + * @param input is a pointer to memory that was hashed. Must not be NULL. + * @param inputSize is the number of bytes in the input. + * @param hash_in is the output from randomx_calculate_hash* (RANDOMX_HASH_SIZE bytes). + * @param com_out is a pointer to memory where the commitment will be stored. Must not + * be NULL and at least RANDOMX_HASH_SIZE bytes must be available for writing. +*/ +RANDOMX_EXPORT void randomx_calculate_commitment(const void* input, size_t inputSize, const void* hash_in, void* com_out); + +#if defined(__cplusplus) +} +#endif + +#endif diff --git a/internal/server/include/sha3xapi.h b/internal/server/include/sha3xapi.h new file mode 100644 index 0000000..4e6caa6 --- /dev/null +++ b/internal/server/include/sha3xapi.h @@ -0,0 +1,4 @@ +#ifndef SHA3X_API_H +#define SHA3X_API_H +void sha3x_hash(unsigned char * out, unsigned char * in); +#endif diff --git a/internal/server/lib/libnexa.so b/internal/server/lib/libnexa.so new file mode 100644 index 0000000..8cd4e2d Binary files /dev/null and b/internal/server/lib/libnexa.so differ diff --git a/internal/server/lib/libnexa12B.so b/internal/server/lib/libnexa12B.so new file mode 100644 index 0000000..249b1e1 Binary files /dev/null and b/internal/server/lib/libnexa12B.so differ diff --git a/internal/server/lib/libnexa16B.so b/internal/server/lib/libnexa16B.so new file mode 100644 index 0000000..6621ac0 Binary files /dev/null and b/internal/server/lib/libnexa16B.so differ diff --git a/internal/server/lib/librandomx.so b/internal/server/lib/librandomx.so new file mode 100644 index 0000000..bf96420 Binary files /dev/null and b/internal/server/lib/librandomx.so differ diff --git a/internal/server/lib/libsha3x.a b/internal/server/lib/libsha3x.a new file mode 100644 index 0000000..cb3ce76 Binary files /dev/null and b/internal/server/lib/libsha3x.a differ diff --git a/internal/server/monero/hash_randomx.go b/internal/server/monero/hash_randomx.go new file mode 100644 index 0000000..cf4ebca --- /dev/null +++ b/internal/server/monero/hash_randomx.go @@ -0,0 +1,117 @@ +package monero + +/* +#cgo CFLAGS: -I/home/lizixuan/桌面/tari-server/internal/server/include +#cgo LDFLAGS: -L/home/lizixuan/桌面/tari-server/internal/server/lib/randomx -lrandomx +#include +#include +#include +#include +*/ +import "C" + +import ( + "fmt" + "unsafe" + + "golang.org/x/sys/cpu" +) + +type RandomXValidator struct { + cache *C.randomx_cache + vm *C.randomx_vm + flags C.randomx_flags + seed []byte +} + +// NewRandomXValidator 初始化 cache + vm +func NewRandomXValidator(seed []byte) (*RandomXValidator, error) { + if len(seed) != 32 { + return nil, fmt.Errorf("seed must be 32 bytes") + } + + var flags C.randomx_flags = 0 + + // 检测 AES-NI 支持 + if cpu.X86.HasAES { + flags |= C.RANDOMX_FLAG_HARD_AES + } else { + fmt.Println("[RandomX] CPU 不支持 AES-NI,将使用纯软件模式") + } + + // ⚠️ 默认启用 JIT(如果系统禁止会报错) + flags |= C.RANDOMX_FLAG_JIT + + // 分配 cache + cache := C.randomx_alloc_cache(flags) + if cache == nil { + return nil, fmt.Errorf("failed to alloc cache") + } + C.randomx_init_cache(cache, unsafe.Pointer(&seed[0]), C.size_t(len(seed))) + + // 创建 vm + vm := C.randomx_create_vm(flags, cache, nil) + if vm == nil { + C.randomx_release_cache(cache) + return nil, fmt.Errorf("failed to create randomx vm") + } + + return &RandomXValidator{ + cache: cache, + vm: vm, + flags: flags, + seed: append([]byte{}, seed...), + }, nil +} + +// SetSeed 更新 seed(替换 cache,并重置 vm) +func (v *RandomXValidator) SetSeed(seed []byte) error { + if len(seed) != 32 { + return fmt.Errorf("seed must be 32 bytes") + } + + // 如果相同 seed,不用更新 + if string(seed) == string(v.seed) { + return nil + } + + C.randomx_init_cache(v.cache, unsafe.Pointer(&seed[0]), C.size_t(len(seed))) + C.randomx_vm_set_cache(v.vm, v.cache) + + v.seed = append(v.seed[:0], seed...) + return nil +} + +// Destroy 释放 vm + cache +func (v *RandomXValidator) Destroy() { + if v.vm != nil { + C.randomx_destroy_vm(v.vm) + v.vm = nil + } + if v.cache != nil { + C.randomx_release_cache(v.cache) + v.cache = nil + } +} + +// BuildPowHash 计算区块哈希 +func (v *RandomXValidator) BuildPowHash(blockBlob, nonce []byte) ([]byte, []byte, error) { + if v.vm == nil { + return nil, nil, fmt.Errorf("vm is nil") + } + + if len(nonce) != 4 { + return nil, nil, fmt.Errorf("nonce must be 4 bytes") + } + blockHeader := make([]byte, len(blockBlob)) + copy(blockHeader, blockBlob) + copy(blockHeader[39:43], nonce) + var hash [32]byte + C.randomx_calculate_hash(v.vm, + unsafe.Pointer(&blockHeader[0]), + C.size_t(len(blockHeader)), + unsafe.Pointer(&hash[0]), + ) + + return hash[:], blockHeader, nil +} diff --git a/internal/server/monero/monero.go b/internal/server/monero/monero.go new file mode 100644 index 0000000..dce867a --- /dev/null +++ b/internal/server/monero/monero.go @@ -0,0 +1,756 @@ +package monero + +import ( + "crypto/rand" + "strings" + + //"database/sql" + + "encoding/hex" + "encoding/json" + + //"log" + //"math" + "math/big" + //"strings" + + "fmt" + "pool/internal/msg" + "pool/internal/server/coin" + "pool/internal/server/dbif" + "pool/internal/stratum" + "pool/internal/utility" + "time" + + _ "github.com/mattn/go-sqlite3" + + "go.uber.org/zap" +) + +const SERVER_MONERO_VERSION string = "monero v0.1a" + +type ServerMoneroContext struct { + ServerCtx *coin.ServerContext + logg *zap.Logger + + Sha3xJob msg.Sha3xStratumJob + + RandomxVM *RandomXValidator +} + +var logg *zap.Logger +var ServerMoneroCtx ServerMoneroContext + +type MoneroNotify_params_msg struct { + Id string `json:"id"` + JobId string `json:"job_id"` + SeedHash string `json:"seed_hash"` + Blob string `json:"blob"` + Height uint32 `json:"height"` + Target string `json:"target"` + NextSeedHash string `json:"next_seed_hash"` + Algo string `json:"algo"` +} + +type Monero_msg struct { + Jsonrpc string `json:"jsonrpc"` + Method string `json:"method"` + Params MoneroNotify_params_msg `json:"params"` +} + +// 辅助函数:反转每个字节的小端 hex +func reverseHexBytes(s string) string { + if len(s)%2 != 0 { + s = "0" + s + } + res := "" + for i := len(s); i > 0; i -= 2 { + res += s[i-2 : i] + } + return res +} + +func calc_target(diff uint64) string { + difficulty := new(big.Int) + difficulty.SetString(fmt.Sprintf("%d", diff), 10) + + // 2^256 - 1 + max := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) + + // target = (2^256 - 1) / difficulty + target := new(big.Int).Div(max, difficulty) + + // 转为32字节 hex(大端) + targetHexBE := fmt.Sprintf("%064x", target) + return targetHexBE +} + +func calc_diff(hash string) uint64 { + be := reverseHexBytes(hash) + target_be := new(big.Int) + target_be.SetString(be, 16) + + max := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1)) + difficulty := new(big.Rat).SetFrac(max, target_be) + // Convert *big.Rat to *big.Float, then to uint64 + diffFloat := new(big.Float).SetRat(difficulty) + result, _ := diffFloat.Uint64() + return result +} + +func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + var submit_item coin.BlockMsg + /*var user_blk_item coin.UserBlockMsg*/ + var pool_blk_item coin.PoolBlkMsg + + var blk_detail_height int64 + var blk_detail_hash string + var blk_detail_success bool + var blk_detail_miner_diff float64 + var blk_detail_pool_diff float64 + + if miner.Authorized != true { + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNAUTH_WORKER) + stratum.Send_reconnect_msg(miner) + return false, false, false + } + var new_found bool = false + var ack stratum.Submit_ack + ack.ID = id + ack.Result = true + // fmt.Println("提交job_id:", job_id) + var keys []string + miner.Jobs.Range(func(k, v interface{}) bool { + if key, ok := k.(string); ok { + keys = append(keys, key) + } + return true // 继续遍历 + }) + + // fmt.Println("目前任务所有key:", keys) + v, ok := miner.Jobs.Load(job_id) + if ok { + job := v.(msg.MoneroStratumJob) + + if uint32(job.Height) < miner.CurHeight-1 { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_STALED_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + if (miner.LastNonce != nonce) || (miner.MoneroJob.BlocktemplateBlob != job.BlocktemplateBlob) { + miner.MoneroJob.BlocktemplateBlob = job.BlocktemplateBlob + miner.LastNonce = nonce + job.Nonce = nonce + + if miner.ZlogInit { + miner.Zlog.Info().Msg("height " + string(job.Height) + " target " + job.Target + " " + miner.User + "." + miner.Miner) + } + + var calc_hash []byte + var completeHeader []byte + nonceByte, err := hex.DecodeString(nonce) + if err != nil { + fmt.Println(err) + return false, false, false + } + headerByte, err := hex.DecodeString(job.BlockhashingBlob) + if err != nil { + fmt.Println(err) + return false, false, false + } + + calc_hash, completeHeader, err = ServerMoneroCtx.RandomxVM.BuildPowHash(headerByte, nonceByte) + if err != nil { + fmt.Println("calc_hash error:", err) + return false, false, false + } + job.CompleteHeader = completeHeader + if miner.ZlogInit { + miner.Zlog.Info().Msg("hash in " + submit_item.Header + " calc_hash " + hex.EncodeToString(calc_hash) + " " + miner.User + "." + miner.Miner) + } + submit_target := new(big.Int) + + submit_target.SetBytes(calc_hash) + + calc_diff := utility.MoneroTarget2Diff(calc_hash) + + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " target diff " + fmt.Sprintf("%f", (miner.Difficulty)) + " submit diff " + fmt.Sprintf("%f", (calc_diff))) + } + + if calc_diff < float64(job.Difficulty) { + ack.Result = false + miner.ErrLowDiffs = miner.ErrLowDiffs + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_LOW_DIF_SHARE) + return false, false, false + + } + + stb, _ := hex.DecodeString(job.Target) + + server_diff := utility.MoneroTarget2Diff(utility.Reverse(stb)) + network_target := new(big.Int) + network_target.SetBytes(stb) + + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " calc_diff " + fmt.Sprintf("%f", (calc_diff)) + " miner.Difficulty " + fmt.Sprintf("%f", (miner.Difficulty)) + " server_diff " + fmt.Sprintf("%f", (server_diff))) + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " submit_target " + hex.EncodeToString(submit_target.Bytes()) + " network_target " + hex.EncodeToString(network_target.Bytes()) + " target " + hex.EncodeToString(miner.ServerTarget.Bytes()) + " cmp " + fmt.Sprintf("%d", (network_target.Cmp(submit_target)))) + } + + submit_item.Hash = hex.EncodeToString(calc_hash) + submit_item.Target = hex.EncodeToString(miner.Target.Bytes()) + submit_item.Submit_target = hex.EncodeToString(calc_hash) + submit_item.Height = int64(job.Height) + submit_item.Pow = hex.EncodeToString(calc_hash) + submit_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + pool_blk_item.Height = int64(job.Height) + pool_blk_item.Hash = hex.EncodeToString(calc_hash) + pool_blk_item.Pow = hex.EncodeToString(calc_hash) + pool_blk_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + blk_detail_height = int64(job.Height) + blk_detail_hash = hex.EncodeToString(calc_hash) + blk_detail_success = false + + blk_detail_miner_diff = float64(job.Difficulty) + blk_detail_pool_diff = miner.Server.RefDifficulty + if ack.Result == true { + if (calc_diff >= server_diff) || (network_target.Cmp(submit_target) >= 0) { + miner.Server.SubIdx++ + Produce_block_submit(miner /*header,*/, &job, submit_item.Hash, miner.Server.SubIdx) + miner.SubmitIndex++ + miner.Submits = miner.Submits + 1 + new_found = true + } + if new_found && float64(miner.Server.MoneroJob.Difficulty) <= calc_diff { + pool_blk_item.Submit = "y" + pool_blk_item.Success = false + pool_blk_item.Accepts = miner.Accepts + pool_blk_item.Rejects = miner.Rejects + pool_blk_item.Reward = 0 + pool_blk_item.Fee = 0 + pool_blk_item.Nonce = nonce + pool_blk_item.SubIdx = miner.Server.SubIdx + dbif.NotifyPoolBlkStatsDb2(miner.Server, &pool_blk_item) + } + } + } else { + miner.LastHeader = job.BlocktemplateBlob + miner.LastNonce = nonce + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_DUP_SHARE) + miner.ErrDuplicates = miner.ErrDuplicates + 1 + return false, false, false + } + + } else { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_NOT_FOUND_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + miner.LastJobId = job_id + + ack.Error = nil + body, err := json.Marshal(ack) + if err != nil { + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit Marshal " + err.Error()) + } + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNKNOWN) + return false, false, false + } + + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //miner.Server.Miners.Delete(miner.MinerId) + } + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } + miner.TxLock.Lock() + miner.Status = coin.MINER_STATUS_RUNNING + miner.TxLock.Unlock() + + if ack.Result { + + miner.Accepts += miner.Difficulty + miner.M5Accepts += miner.Difficulty + + miner.VarDiffOpt.SubmitShares += miner.Difficulty + + } else { + miner.Rejects += miner.Difficulty + + } + now := time.Now() + if miner.Server.Config.Diff.Filter == "kalman" { + if ack.Result { + share_interval := now.Sub(miner.LastSubmitime).Seconds() + mhs := miner.Difficulty * share_interval + diff_next, kalman_p := miner.DiffHandler.Handler(miner.Difficulty, share_interval) + mhs_est := diff_next * miner.Server.Config.Diff.DiffAdjustInterval + + ratio := diff_next / miner.Difficulty + if ratio > 0 { + if now.Sub(miner.StartSubmitTime).Seconds() > 180 { + if ratio >= 2 { + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else if ratio <= 0.5 { + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else { + } + } else { + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } + } + if miner.DifficultyNext > 0.0 { + if miner.DifficultyNext < miner.VarDiffOpt.MinDiff { + miner.DifficultyNext = miner.VarDiffOpt.MinDiff + } else if miner.DifficultyNext > miner.VarDiffOpt.MaxDiff { + miner.DifficultyNext = miner.VarDiffOpt.MaxDiff + } + } + + if miner.Server.Config.Diff.Dbg { + coin.New_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, diff_next, kalman_p, share_interval, mhs, mhs_est) + } + + } + } else { + if now.Sub(miner.LastSubmitime).Seconds() < miner.Server.Config.Diff.DiffAdjustInterval { + if ack.Result { + if miner.VarDiffOpt.Uptimes++; miner.VarDiffOpt.Uptimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.UP_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Uptimes = 0 + } + if now.Sub(miner.LastSubmitime).Seconds() > miner.Server.Config.Diff.DiffAdjustInterval*2 { + if ack.Result { + if miner.VarDiffOpt.Downtimes++; miner.VarDiffOpt.Downtimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.DOWN_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Downtimes = 0 + } + } + if ack.Result { + miner.LastSubmitime = now + miner.VarDiffOpt.LastSubmitTime = now + } + var duration float64 = float64(now.Sub(miner.StartSubmitTime)) / 1000000000 + + if duration < 1 { + duration = 1 + } + + diffOneShareHashesAvg := uint64(0xFFFFFFFFFFFFFFFF) + miner.AverageHashrate = miner.Accepts * float64(diffOneShareHashesAvg) / duration / 1000000 + var m5_duration float64 = float64(now.Sub(miner.M5SubmitTime)) / 1000000000 + if m5_duration >= float64(time.Minute*5)/1000000000 { + miner.M5SubmitTime = now + miner.M5Hashrate = miner.M5Accepts * float64(diffOneShareHashesAvg) / m5_duration / 1000000 + + miner.M5Accepts = 0 + } + + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit M5Accepts " + fmt.Sprintf("%f", (miner.M5Accepts)) + " M5Hashrate(MH/S) " + fmt.Sprintf("%f", (miner.M5Hashrate))) + } + + if miner.Server.Config.Diff.Filter == "kalman" { + } else { + if float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000 >= miner.VarDiffOpt.AdjustTime { + coin.VarAdjustDifficulty(miner, coin.UPDATE_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + + if ack.Result { + + submit_item.Success = false + if new_found { + submit_item.Submit = "y" + submit_item.SubIdx = miner.Server.SubIdx + } else { + submit_item.Submit = "n" + submit_item.SubIdx = -1 + } + + submit_item.Accepts = miner.Accepts + submit_item.Total_accepts = miner.Accepts + submit_item.Rejects = miner.Rejects + submit_item.Total_rejects = miner.Rejects + submit_item.Reward = 0 + submit_item.Fee = 0 + submit_item.Nonce = nonce + + dbif.NotifyBlkDetailDb(miner, blk_detail_height, blk_detail_hash, blk_detail_success, blk_detail_miner_diff, blk_detail_pool_diff, nonce, submit_item.SubIdx) + return true, new_found, true + } + return false, false, true +} + +func contractBlockTemplateBlob(miner *coin.MinerObj, nonceHex string) (string, error) { + blockTemplateStr := miner.MoneroJob.BlocktemplateBlob + block, err := hex.DecodeString(blockTemplateStr) + if err != nil { + return "", err + } + if len(block) < 43 { + return "", fmt.Errorf("blocktemplate blob too short: %d", len(block)) + } + + // nonce 是 4 字节 hex,直接解码成 bytes + nonceBytes, err := hex.DecodeString(nonceHex) + if err != nil { + return "", fmt.Errorf("invalid nonce hex: %v", err) + } + if len(nonceBytes) != 4 { + return "", fmt.Errorf("nonce must be 4 bytes, got %d", len(nonceBytes)) + } + + // 覆盖 nonce 区域 (39~42) + copy(block[39:43], nonceBytes) + + return hex.EncodeToString(block), nil +} + +func Produce_block_submit(miner *coin.MinerObj /*header Sha3xBlockHeader,*/, job *msg.MoneroStratumJob, PowHash string, SubIdx int64) { + var nm msg.BlockMoneroMsg + blockBlob, err := contractBlockTemplateBlob(miner, job.Nonce) + if err != nil { + fmt.Println(err) + return + } + nm.Id = job.Id + nm.Header = blockBlob + nm.Nonce = job.Nonce + nm.Pow = PowHash + nm.SubIdx = SubIdx + nm.User = miner.User + nm.Miner = miner.Miner + nm.Height = job.Height + nm.Index = fmt.Sprint(miner.MinerIndex) + body, err := json.Marshal(nm) + if err != nil { + logg.Error("[server]", zap.String("failed to Marshal job", err.Error())) + return + } + + // JSON主体 + blk := string(body) + + // 高度(uint32 → 4字节 → hex编码8字符) + heightHex := fmt.Sprintf("%08x", job.Height) + + // Index(uint32 → 4字节 → hex编码8字符) + indexHex := fmt.Sprintf("%08x", miner.MinerIndex) + + // 拼接最终消息 + msg := blk + heightHex + indexHex + // fmt.Println(msg) + logg.Info("[server]", zap.String("final_msg", msg)) + + if miner.Server.PubCh == nil { + miner.Server.PubCh = utility.InitZmqPub(miner.Server.Config.Zmq.Pub) + } + if miner.Server.PubCh != nil { + // fmt.Println(msg) + err := miner.Server.PubCh.SendMessage([][]byte{[]byte("blkmonero"), []byte(msg)}) + if err != nil { + miner.Server.PubCh.Destroy() + miner.Server.PubCh = nil + logg.Info("[server]", zap.String("blk", err.Error())) + } else { + logg.Info("[server]", zap.String("blk", "sent")) + } + } + +} + +// var start_job_id uint64 = 0 + +// server-->miner +func parse_miner_notify(miner *coin.MinerObj, msg msg.MoneroStratumJob) int { + if miner.MoneroJob.Height != msg.Height { + miner.Job.IsClean = true + } + miner.MoneroJob = msg + miner.MoneroJob.JobId = msg.JobId + return 1 +} + +func Init(server *coin.ServerContext) { + ServerMoneroCtx.ServerCtx = server + ServerMoneroCtx.RandomxVM = &RandomXValidator{} + logg = server.Logg + logg.Info("[server]", zap.String("server_sha3x_version", SERVER_MONERO_VERSION)) + coin.Init_diff_db() +} + +func Start() { + +} + +func Stop() { + coin.DiffStop() +} + +func InitMiner(miner *coin.MinerObj) { + miner.MoneroJob = miner.Server.MoneroJob + // miner.MoneroJob.Extranonce1 = miner.Job.Extranonce1 + + server_target := new(big.Int) + t_bytes, err := hex.DecodeString(miner.MoneroJob.Target) + if err != nil { + logg.Error("[server]", zap.String("DecodeString", err.Error())) + return + } + //server_target.SetBytes(common.Reverse(t_bytes)) + miner.MoneroJob = ServerMoneroCtx.ServerCtx.MoneroJob + server_target.SetBytes(t_bytes) + miner.ServerTarget = server_target + miner.ServerTargetS = miner.Server.SJob.Target + miner.CurHeight = uint32(miner.MoneroJob.Height) +} + +func Handle_subscribe_sha3x(miner *coin.MinerObj, id float64, extranonce1 string) { + +} + +func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) { + +} + +func HandleMinerAuth(miner *coin.MinerObj) { + +} + +func HandleMinerSubmit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + //nonce_str, _ := stratum.ReverseHexStringByByte(nonce) + accept_ok, submit_ok, handle_ok := handle_submit(miner, id, miner_user, job_id, nonce2, ntime, nonce) + return accept_ok, submit_ok, handle_ok +} + +func SetDifficulty(miner *coin.MinerObj) { + stratum.Set_difficulty(miner) +} + +func MoneroNotify(miner *coin.MinerObj) { + miner.TxLock.Lock() + if !((miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING)) { + miner.TxLock.Unlock() + return + } + miner.TxLock.Unlock() + if miner.DifficultyNext > -1 { + ratio := miner.DifficultyNext / miner.Difficulty + if ratio > 1.1 || ratio < 0.9 { + miner.Difficulty = miner.DifficultyNext + miner.DifficultyNext = -1 + stratum.Set_difficulty(miner) + //logg.Info("[gbt]", zap.Float64("update Diff", miner.Difficulty)) + } else { + miner.DifficultyNext = -1 + } + } + + miner.TxLock.Lock() + //log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId) + + var msg Monero_msg + + msg.Params.Id = miner.Session + msg.Params.SeedHash = miner.MoneroJob.SeedHash + msg.Params.JobId = miner.MoneroJob.JobId + msg.Params.Blob = miner.MoneroJob.BlockhashingBlob + msg.Params.Height = uint32(miner.MoneroJob.Height) + miner.MoneroJob.Difficulty = uint64(miner.Difficulty) + msg.Params.NextSeedHash = "" + msg.Params.Algo = "rx/0" + //target_s, _ := stratum.ReverseHexStringByByte(miner.Sha3xJob.Target) + //msg.Params.Target = target_s[48:] + target_new, _ := utility.MoneroDiffToTarget(miner.Difficulty) + target_str := fmt.Sprintf("%064x", target_new.Bytes()) + target_strr, strerr := stratum.ReverseHexStringByByte(target_str) + if strerr != nil { + println("ReverseHexStringByByte", strerr.Error()) + } + //println("target=", target_str, "r=", target_strr) + msg.Params.Target = target_strr[48:] + + miner.CurHeight = uint32(miner.MoneroJob.Height) + + // miner.MoneroJob.JobDifficulty = miner.Difficulty + + miner.Jobs.LoadOrStore(miner.MoneroJob.JobId, miner.MoneroJob) + + stratum.AddAndUpdateJob(miner) + + stratum.UpdateJobs(miner) + + miner.JobId++ + + var body []byte + var err error + + msg.Jsonrpc = "2.0" + msg.Method = "job" + + body, err = json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + miner.TxLock.Unlock() + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +func Notify(miner *coin.MinerObj) { + MoneroNotify(miner) +} + +func formatUint64ToHexWithPadding(val uint64) string { + hexStr := fmt.Sprintf("%016x", val) + + if len(hexStr) < 64 { + paddingLen := 64 - len(hexStr) + hexStr += string(make([]byte, paddingLen)) + for i := len(hexStr) - paddingLen; i < 64; i++ { + hexStr = hexStr[:i] + "0" + hexStr[i+1:] + } + } + return hexStr +} + +func formatWideTargetTo32BytesTarget(wide_target string) string { + if len(wide_target) > 64 { + panic("任务中的wide_target错误:") + } + // 去掉前缀 0x 或 0X + wide_target = strings.TrimPrefix(wide_target, "0x") + wide_target = strings.TrimPrefix(wide_target, "0X") + wide_target = fmt.Sprintf("%0*s%s", 64-len(wide_target), "", wide_target) + return wide_target +} + +var last_seed string = "" + +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 HandleJobMsg(server *coin.ServerContext, Msg []byte) { + var result msg.MoneroStratumJob + server.Logg.Warn("[server]", zap.String("receive", "job")) + + if err := json.Unmarshal(Msg, &result); err != nil { + server.Logg.Error("[server]", zap.String("Unmarshal", err.Error())) + return + } + result.Target = calc_target(result.Difficulty) + // 上个模板 seed_hash 和本次 seed_hash 不一致时,重置 randomx 虚拟机 + if result.SeedHash != last_seed { + fmt.Println("开始创建新的 randomx vm, 本次 seed_hash:", result.SeedHash) + + seedBytes, err := hex.DecodeString(result.SeedHash) + if err != nil { + panic(err) + } + + // 如果已有旧 VM,先释放 + if ServerMoneroCtx.RandomxVM != nil { + ServerMoneroCtx.RandomxVM.Destroy() + } + + // 创建新 VM + vm, err := NewRandomXValidator(seedBytes) + if err != nil { + panic(err) + } + + ServerMoneroCtx.RandomxVM = vm + last_seed = result.SeedHash + } + + server.MoneroJob = msg.MoneroStratumJob(result) + logg.Debug("[gbt]", zap.String("Target", server.MoneroJob.Target)) + logg.Debug("[gbt]", zap.Uint64("Id", server.MoneroJob.Id), zap.Float64("network diff", float64(server.MoneroJob.Difficulty))) + + server.NetHight = uint64(server.MoneroJob.Height) // 当前server中的全网高度 + server.NetTarget = result.Target // 当前server中的全网target + server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + server.Logg.Info("[server]", zap.String("lock", "start")) + m.TxLock.Lock() + status := m.Status + cmd := parse_miner_notify(m, server.MoneroJob) + m.TxLock.Unlock() + server.Logg.Info("[server]", zap.String("lock", "end")) + var need_notify bool = true + if time.Now().Sub(m.ConnSetupTime) >= time.Duration(coin.CONN_EXPIRED_TIME)*time.Second { + if (status != coin.MINER_STATUS_RUNNING) && (status != coin.MINER_STATUS_AUTHORIZED) { + //m.Conn.Close() + need_notify = false + } + } + if need_notify { + switch cmd { + case 0: //extranonce 1 and extranonce2 size + //TODO + case 1: //notify + MoneroNotify(m) + } + } + } + } + } + return true + }) +} + +func IsMhsLow(miner *coin.MinerObj) bool { + if miner.Mhs5M < 1 { + return true + } + return false +} + +func GetBlockInterval() int { + return 3600 +} diff --git a/internal/server/nexa/hash_nexa.go b/internal/server/nexa/hash_nexa.go new file mode 100644 index 0000000..925d2f9 --- /dev/null +++ b/internal/server/nexa/hash_nexa.go @@ -0,0 +1,61 @@ +// hash_nexa.go +package nexa + +/* +#cgo CFLAGS : -I../include +#cgo LDFLAGS: -L../lib -lnexa + +#include +#include +#include "nexaapi.h" +*/ +import "C" +import ( + //"encoding/hex" + //"log" + "unsafe" +) + +func BuildPowHash(h NexaBlockHeader) []byte { + outputs := make([]byte, 32) + inb := NexaBlockHeaderToBytes(h) + //log.Println("[nexa]in", hex.EncodeToString(inb)) + in := (*C.uchar)(C.CBytes(inb)) + output := (*C.uchar)(C.malloc(32)) + C.nexa_hash(output, in) + p := uintptr(unsafe.Pointer(output)) + for i := 0; i < 32; i++ { + j := *(*byte)(unsafe.Pointer(p)) + outputs[i] = j + p += unsafe.Sizeof(j) + } + C.free(unsafe.Pointer(output)) + C.free(unsafe.Pointer(in)) + outputs32 := make([]byte, 32) + for i := 0; i < 32; i++ { + outputs32[i] = outputs[i] + } + return outputs32 +} + +func BuildPowHash12(h NexaBlockHeader12) []byte { + outputs := make([]byte, 32) + inb := NexaBlockHeaderToBytes12(h) + //log.Println("[nexa]in", hex.EncodeToString(inb)) + in := (*C.uchar)(C.CBytes(inb)) + output := (*C.uchar)(C.malloc(32)) + C.nexa_hash12(output, in) + p := uintptr(unsafe.Pointer(output)) + for i := 0; i < 32; i++ { + j := *(*byte)(unsafe.Pointer(p)) + outputs[i] = j + p += unsafe.Sizeof(j) + } + C.free(unsafe.Pointer(output)) + C.free(unsafe.Pointer(in)) + outputs32 := make([]byte, 32) + for i := 0; i < 32; i++ { + outputs32[i] = outputs[i] + } + return outputs32 +} diff --git a/internal/server/nexa/nexa.go b/internal/server/nexa/nexa.go new file mode 100644 index 0000000..0de4236 --- /dev/null +++ b/internal/server/nexa/nexa.go @@ -0,0 +1,943 @@ +// nexa.go +package nexa + +import ( + //"database/sql" + "encoding/binary" + "encoding/hex" + "encoding/json" + + //"log" + //"math" + "math/big" + "strings" + + "fmt" + "pool/internal/msg" + "pool/internal/server/coin" + "pool/internal/server/dbif" + "pool/internal/stratum" + "pool/internal/utility" + "time" + + _ "github.com/mattn/go-sqlite3" + + "go.uber.org/zap" +) + +const SERVER_NEXA_VERSION string = "nexa v2.0x" + +type NexaBlockHeader struct { + Header [32]byte + Nonce [16]byte +} + +func NexaBlockHeaderToBytes(h NexaBlockHeader) []byte { + out := make([]byte, 49) + for i := 0; i < 32; i++ { + out[i] = h.Header[i] + } + out[32] = 0x10 + for i := 0; i < 16; i++ { + out[33+i] = h.Nonce[i] + } + return out +} + +type NexaBlockHeader12 struct { + Header [32]byte + Nonce [12]byte +} + +func NexaBlockHeaderToBytes12(h NexaBlockHeader12) []byte { + out := make([]byte, 45) + for i := 0; i < 32; i++ { + out[i] = h.Header[i] + } + out[32] = 0x0c + for i := 0; i < 12; i++ { + out[33+i] = h.Nonce[i] + } + return out +} + +type ServerNexaContext struct { + ServerCtx *coin.ServerContext + logg *zap.Logger + + NexaJob msg.NexaStratumJob +} + +var logg *zap.Logger +var ServerNexaCtx ServerNexaContext + +type Notify_msg_nexa struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params [5]interface{} `json:"params"` +} + +type Notify_msg_nexa_gpu struct { + Jsonrpc string `json:"jsonrpc"` + ID interface{} `json:"id"` + Method string `json:"method"` + Params [4]interface{} `json:"params"` +} + +func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + var submit_item coin.BlockMsg + /*var user_blk_item coin.UserBlockMsg*/ + var pool_blk_item coin.PoolBlkMsg + + var blk_detail_height int64 + var blk_detail_hash string + var blk_detail_success bool + var blk_detail_miner_diff float64 + var blk_detail_pool_diff float64 + + if miner.Authorized != true { + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNAUTH_WORKER) + stratum.Send_reconnect_msg(miner) + return false, false, false + } + var new_found bool = false + var ack stratum.Submit_ack + ack.ID = id + ack.Result = true + //logg.Warn("[server]", zap.String("user", miner.User), zap.String("miner", miner.Miner)) + //logg.Debug("[server]", zap.Float64("id", id), zap.String("job_id", job_id)) + //logg.Debug("[server]", zap.String("nonce2", nonce2), zap.String("ntime", ntime), zap.String("nonce", nonce)) + //stratum.UpdateJobs(miner) + v, ok := miner.Jobs.Load(job_id) + if ok { + job := v.(msg.NexaStratumJob) + + if job.Height < miner.CurHeight-1 { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_STALED_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + //logg.Debug("[server]", zap.Uint64("ntime", nt), zap.Uint64("mintime", uint64(job.Mintime)), zap.Uint64("jobtime", jt_reverse)) + /*if nt < uint64(job.Mintime) { + ack.Result = false + util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_OLD) + } else if nt > jt_reverse+uint64(600) { + ack.Result = false + util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_NEW) + } else */{ + if (miner.LastNonce != nonce) || (miner.LastHeader != job.Header) { + miner.LastHeader = job.Header + miner.LastNonce = nonce + job.Nonce = nonce + job.Extranonce2 = nonce2 + //logg.Debug("[server]", zap.Uint32("height", job.Height), zap.String("target", job.Target)) + if miner.ZlogInit { + miner.Zlog.Info().Msg("height " + string(job.Height) + " target " + job.Target + " " + miner.User + "." + miner.Miner) + } + + phb, _ := hex.DecodeString(job.Header) + nb, _ := hex.DecodeString(nonce) + + var calc_hash []byte + if miner.Protocol == "yxminer" { + var header NexaBlockHeader + for i := 0; i < 32; i++ { + header.Header[i] = phb[i] + } + for i := 0; i < 16; i++ { + header.Nonce[i] = nb[i] + } + submit_item.Header = hex.EncodeToString(NexaBlockHeaderToBytes(header)) + calc_hash = BuildPowHash(header) + } else if miner.Protocol == "bzminer" || miner.Protocol == "lolminer" || miner.Protocol == "Rigel" || miner.Protocol == "WildRig" { + var header NexaBlockHeader12 + for i := 0; i < 32; i++ { + header.Header[i] = phb[i] + } + for i := 0; i < 12; i++ { + header.Nonce[i] = nb[i] + } + submit_item.Header = hex.EncodeToString(NexaBlockHeaderToBytes12(header)) + calc_hash = BuildPowHash12(header) + } else { + var header NexaBlockHeader + for i := 0; i < 32; i++ { + header.Header[i] = phb[i] + } + for i := 0; i < 16; i++ { + header.Nonce[i] = nb[i] + } + submit_item.Header = hex.EncodeToString(NexaBlockHeaderToBytes(header)) + calc_hash = BuildPowHash(header) + } + + //logg.Debug("[server]", zap.String("hash in", submit_item.Header)) + //calc_hash, header := util.BuildBlockHash(&(job), true, Build_PowHash) + //logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/) + if miner.ZlogInit { + miner.Zlog.Info().Msg("hash in " + submit_item.Header + " calc_hash " + hex.EncodeToString(calc_hash) + " " + miner.User + "." + miner.Miner) + } + submit_target := new(big.Int) + //submit_target.SetBytes(common.Reverse(calc_hash)) + + //hashs, _ := utility.ReverseS(hex.EncodeToString(calc_hash)) + + //hashb, _ := hex.DecodeString(hashs) + //submit_target.SetBytes(hashb) + submit_target.SetBytes(calc_hash) + /*logg.Debug("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.Target.Bytes()))) + if submit_target.Cmp(miner.Target) > 0 {*/ + //calc_diff := Target2Diff(common.Reverse(calc_hash)) + calc_diff := utility.Target2Diff(calc_hash) + //log.Printf("diff,calc_diff:%f difficulty:%f ", calc_diff, miner.Difficulty) + //logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff)) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " target diff " + fmt.Sprintf("%f", (miner.Difficulty)) + " submit diff " + fmt.Sprintf("%f", (calc_diff))) + } + //logg.Debug("[server]", zap.String("target", miner.Target.String()), zap.Any("bytes", miner.Target.Bytes())) + //logg.Info("[server]", zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff), zap.String("target", hex.EncodeToString(miner.Target.Bytes()))) + + //if calc_diff < miner.Difficulty { + if calc_diff < job.JobDifficulty { + //gpu protocol handler + /*for i := 0; i < 8; i++ { + temp_nonce := header.Nonce[8+i] + header.Nonce[8+i] = header.Nonce[i] + header.Nonce[i] = temp_nonce + } + submit_item.Header = hex.EncodeToString(NexaBlockHeaderToBytes(header)) + calc_hash = BuildPowHash(header) + logg.Debug("[server]", zap.String("hash in", hex.EncodeToString(NexaBlockHeaderToBytes(header))))*/ + //logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/) + //submit_target = new(big.Int) + /*submit_target.SetBytes(calc_hash) + calc_diff = utility.Target2Diff(calc_hash) + logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff)) + if calc_diff < miner.Difficulty { + */ + ack.Result = false + miner.ErrLowDiffs = miner.ErrLowDiffs + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_LOW_DIF_SHARE) + return false, false, false + //} + + } + //logg.Warn("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes()))) + //submit_target.Text(16) + /*if submit_target.Cmp(miner.ServerTarget) <= 0 {*/ + //log.Println("[server]server_target", miner.ServerTargetS) + //stb, _ := hex.DecodeString(miner.ServerTargetS) + stb, _ := hex.DecodeString(job.Target) + //logg.Info("[server]", zap.String("target", job.Target)) + //server_diff := Target2Diff(common.Reverse(stb)) + server_diff := utility.Target2Diff(utility.Reverse(stb)) + //log.Printf("[server]server_diff %f", server_diff) + //logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff)) + //logg.Debug("[server]", zap.String("ServerTargetS", miner.ServerTargetS)) + network_target := new(big.Int) + network_target.SetBytes(stb) + //logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff)) + //logg.Debug("[server]", zap.String("submit_target", hex.EncodeToString(submit_target.Bytes())), zap.String("network_target", hex.EncodeToString(network_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes())), zap.Int("cmp", network_target.Cmp(submit_target))) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " calc_diff " + fmt.Sprintf("%f", (calc_diff)) + " miner.Difficulty " + fmt.Sprintf("%f", (miner.Difficulty)) + " server_diff " + fmt.Sprintf("%f", (server_diff))) + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " submit_target " + hex.EncodeToString(submit_target.Bytes()) + " network_target " + hex.EncodeToString(network_target.Bytes()) + " target " + hex.EncodeToString(miner.ServerTarget.Bytes()) + " cmp " + fmt.Sprintf("%d", (network_target.Cmp(submit_target)))) + } + + submit_item.Hash = hex.EncodeToString(calc_hash) + submit_item.Target = hex.EncodeToString(miner.Target.Bytes()) + submit_item.Submit_target = hex.EncodeToString(calc_hash) + submit_item.Height = int64(job.Height) + submit_item.Pow = hex.EncodeToString(calc_hash) + submit_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + /*user_blk_item.Height = int64(job.Height) + user_blk_item.Hash = hex.EncodeToString(calc_hash) + user_blk_item.Pow = hex.EncodeToString(calc_hash) + user_blk_item.Net_target = hex.EncodeToString(network_target.Bytes())*/ + + pool_blk_item.Height = int64(job.Height) + pool_blk_item.Hash = hex.EncodeToString(calc_hash) + pool_blk_item.Pow = hex.EncodeToString(calc_hash) + pool_blk_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + blk_detail_height = int64(job.Height) + blk_detail_hash = hex.EncodeToString(calc_hash) + blk_detail_success = false + //blk_detail_miner_diff = miner.Difficulty + blk_detail_miner_diff = job.JobDifficulty + blk_detail_pool_diff = miner.Server.RefDifficulty + + if ack.Result == true { + /*if miner.CurHeight != 0 && miner.CurHeight == job.Height { + return + }*/ + + //if true { + if (calc_diff >= server_diff) || (network_target.Cmp(submit_target) >= 0) { + miner.Server.SubIdx++ + Produce_block_submit(miner /*header,*/, &job, submit_item.Hash, miner.Server.SubIdx) + miner.SubmitIndex++ + miner.Submits = miner.Submits + 1 + //miner.CurHeight = job.Height + new_found = true + } + } + } else { + miner.LastHeader = job.Header + miner.LastNonce = nonce + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_DUP_SHARE) + miner.ErrDuplicates = miner.ErrDuplicates + 1 + return false, false, false + } + } + } else { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_NOT_FOUND_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + miner.LastJobId = job_id + + ack.Error = nil + body, err := json.Marshal(ack) + if err != nil { + //logg.Error("[server]", zap.String("Marshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit Marshal " + err.Error()) + } + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNKNOWN) + return false, false, false + } + + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //miner.Server.Miners.Delete(miner.MinerId) + } + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } + //logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Lock() + miner.Status = coin.MINER_STATUS_RUNNING + miner.TxLock.Unlock() + + if ack.Result { + + miner.Accepts += miner.Difficulty + miner.M5Accepts += miner.Difficulty + + miner.VarDiffOpt.SubmitShares += miner.Difficulty + + } else { + miner.Rejects += miner.Difficulty + + } + now := time.Now() + if miner.Server.Config.Diff.Filter == "kalman" { + if ack.Result { + share_interval := now.Sub(miner.LastSubmitime).Seconds() + mhs := miner.Difficulty * share_interval + diff_next, kalman_p := miner.DiffHandler.Handler(miner.Difficulty, share_interval) + mhs_est := diff_next * miner.Server.Config.Diff.DiffAdjustInterval + + ratio := diff_next / miner.Difficulty + if ratio > 0 { + if now.Sub(miner.StartSubmitTime).Seconds() > 180 { + if ratio >= 2 { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else if ratio <= 0.5 { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else { + } + } else { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + /*if ratio >= 1.1 { + miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else if ratio <= 0.8 { + miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else { + }*/ + } + } + if miner.DifficultyNext > 0.0 { + if miner.DifficultyNext < miner.VarDiffOpt.MinDiff { + miner.DifficultyNext = miner.VarDiffOpt.MinDiff + } else if miner.DifficultyNext > miner.VarDiffOpt.MaxDiff { + miner.DifficultyNext = miner.VarDiffOpt.MaxDiff + } + } + //miner.VarDiffOpt.LastCalcTime = now + + if miner.Server.Config.Diff.Dbg { + coin.New_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, diff_next, kalman_p, share_interval, mhs, mhs_est) + } + + //log.Println("diff adjust", ratio, diff_next, miner.Difficulty, miner.DifficultyNext) + } + } else { + // submit time < DiffAdjustInterval,then up adjust diff + if now.Sub(miner.LastSubmitime).Seconds() < miner.Server.Config.Diff.DiffAdjustInterval { + if ack.Result { + if miner.VarDiffOpt.Uptimes++; miner.VarDiffOpt.Uptimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.UP_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Uptimes = 0 + } + + // submit time > 2 * DiffAdjustInterval,then down adjust diff + if now.Sub(miner.LastSubmitime).Seconds() > miner.Server.Config.Diff.DiffAdjustInterval*2 { + if ack.Result { + if miner.VarDiffOpt.Downtimes++; miner.VarDiffOpt.Downtimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.DOWN_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Downtimes = 0 + } + } + if ack.Result { + miner.LastSubmitime = now + miner.VarDiffOpt.LastSubmitTime = now + } + var duration float64 = float64(now.Sub(miner.StartSubmitTime)) / 1000000000 + + if duration < 1 { + duration = 1 + } + diffOneShareHashesAvg := uint64(0x00000000FFFFFFFF) + miner.AverageHashrate = miner.Accepts * float64(diffOneShareHashesAvg) / duration / 1000000 + var m5_duration float64 = float64(now.Sub(miner.M5SubmitTime)) / 1000000000 + if m5_duration >= float64(time.Minute*5)/1000000000 { + miner.M5SubmitTime = now + miner.M5Hashrate = miner.M5Accepts * float64(diffOneShareHashesAvg) / m5_duration / 1000000 + //logg.Info("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate)) + miner.M5Accepts = 0 + } + + //logg.Warn("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("Rejects", miner.Rejects)) + //logg.Info("[server]", zap.Float64("TargetShares", miner.VarDiffOpt.TargetShares), zap.Float64("MinShares", miner.VarDiffOpt.MinShares), zap.Float64("MaxShares", miner.VarDiffOpt.MaxShares), zap.Float64("SubmitShares", miner.VarDiffOpt.SubmitShares)) + //logg.Warn("[server]", zap.Float64("reject rate", miner.Rejects/(miner.Accepts+miner.Rejects)), zap.Float64("Hashrate(MH/S)", miner.AverageHashrate)) + //logg.Warn("[server]", zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate)) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit M5Accepts " + fmt.Sprintf("%f", (miner.M5Accepts)) + " M5Hashrate(MH/S) " + fmt.Sprintf("%f", (miner.M5Hashrate))) + } + + //logg.Info("[server]", zap.Float64("LastCalcTime", float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000)) + //calc acutal submit shares period of time, then compare with target shares and adjust diff + + if miner.Server.Config.Diff.Filter == "kalman" { + } else { + if float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000 >= miner.VarDiffOpt.AdjustTime { + coin.VarAdjustDifficulty(miner, coin.UPDATE_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + + if new_found { + //util.StaleAllJobs(miner) + + /*user_blk_item.User = miner.User + user_blk_item.Miner = miner.Miner + user_blk_item.Index = fmt.Sprint(miner.MinerIndex) + + user_blk_item.Submit = "y" + user_blk_item.Success = false + user_blk_item.Accepts = miner.Accepts + user_blk_item.Rejects = miner.Rejects + user_blk_item.Reward = 0 + user_blk_item.Fee = 0 + user_blk_item.Nonce = nonce + user_blk_item.SubIdx = miner.Server.SubIdx + dbif.NotifyUsersBlkStatsDb2(miner, &user_blk_item)*/ + + pool_blk_item.Submit = "y" + pool_blk_item.Success = false + pool_blk_item.Accepts = miner.Accepts + pool_blk_item.Rejects = miner.Rejects + pool_blk_item.Reward = 0 + pool_blk_item.Fee = 0 + pool_blk_item.Nonce = nonce + pool_blk_item.SubIdx = miner.Server.SubIdx + dbif.NotifyPoolBlkStatsDb2(miner.Server, &pool_blk_item) + + } + + if ack.Result { + + submit_item.Success = false + if new_found { + submit_item.Submit = "y" + submit_item.SubIdx = miner.Server.SubIdx + } else { + submit_item.Submit = "n" + submit_item.SubIdx = -1 + } + + submit_item.Accepts = miner.Accepts + submit_item.Total_accepts = miner.Accepts + submit_item.Rejects = miner.Rejects + submit_item.Total_rejects = miner.Rejects + submit_item.Reward = 0 + submit_item.Fee = 0 + submit_item.Nonce = nonce + + //dbif.NotifyMinerDb2(miner, &submit_item) + + dbif.NotifyBlkDetailDb(miner, blk_detail_height, blk_detail_hash, blk_detail_success, blk_detail_miner_diff, blk_detail_pool_diff, nonce, submit_item.SubIdx) + return true, new_found, true + } + return false, false, true +} + +func Produce_block_submit(miner *coin.MinerObj /*header NexaBlockHeader,*/, job *msg.NexaStratumJob, PowHash string, SubIdx int64) { + var nm msg.BlockNexaMsg + nm.Id = job.Id + nm.Header = job.Header + nm.Nonce = job.Nonce + nm.Pow = PowHash + nm.SubIdx = SubIdx + nm.User = miner.User + nm.Miner = miner.Miner + nm.Index = fmt.Sprint(miner.MinerIndex) + body, err := json.Marshal(nm) + if err != nil { + logg.Error("[server]", zap.String("failed to Marshal job", err.Error())) + return + } + blk := string(body) + //Add Height + heightb := utility.Uint32ToByte(job.Height) + heights := hex.EncodeToString(heightb) + blk += heights + var Height uint32 = utility.ByteToUint32(heightb) + logg.Warn("[server]", zap.Uint32("Height", Height)) + + //Add SubmitIndex + indexb := utility.Uint32ToByte(miner.SubmitIndex) + indexs := hex.EncodeToString(indexb) + blk += indexs + var SubmitIndex uint32 = utility.ByteToUint32(indexb) + logg.Info("[server]", zap.Uint32("SubmitIndex", SubmitIndex)) + logg.Info("[server]", zap.String("blk", blk)) + + if miner.Server.PubCh == nil { + miner.Server.PubCh = utility.InitZmqPub(miner.Server.Config.Zmq.Pub) + } + if miner.Server.PubCh != nil { + //miner.Server.PubCh.SendChan <- [][]byte{[]byte("blknexa"), []byte(blk)} + err := miner.Server.PubCh.SendMessage([][]byte{[]byte("blknexa"), []byte(blk)}) + if err != nil { + miner.Server.PubCh.Destroy() + miner.Server.PubCh = nil + logg.Info("[server]", zap.String("blk", err.Error())) + } else { + logg.Info("[server]", zap.String("blk", "sent")) + } + } +} + +// server-->miner +func nexa_parse_miner_notify(miner *coin.MinerObj, msg msg.NexaStratumJob) int { + if miner.NexaJob.Height != msg.Height { + miner.Job.IsClean = true + } + miner.NexaJob = msg + miner.NexaJob.Extranonce1 = miner.Job.Extranonce1 + miner.Job.Extranonce2_size = msg.Extranonce2_size + + //miner.Server.Logg.Info("[server]", zap.Int32("miner.Version", miner.Version), zap.Int32("msg.Version", msg.Version)) + return 1 +} + +func Init(server *coin.ServerContext) { + ServerNexaCtx.ServerCtx = server + logg = server.Logg + logg.Info("[server]", zap.String("server_nexa_version", SERVER_NEXA_VERSION)) + coin.Init_diff_db() +} + +func Start() { + +} + +func Stop() { + coin.DiffStop() +} + +func InitMiner(miner *coin.MinerObj) { + miner.NexaJob = miner.Server.NexaJob + miner.NexaJob.Extranonce1 = miner.Job.Extranonce1 + + server_target := new(big.Int) + t_bytes, err := hex.DecodeString(miner.NexaJob.Target) + if err != nil { + logg.Error("[server]", zap.String("DecodeString", err.Error())) + return + } + //server_target.SetBytes(common.Reverse(t_bytes)) + server_target.SetBytes(t_bytes) + miner.ServerTarget = server_target + miner.ServerTargetS = miner.Server.SJob.Target +} + +func Handle_subscribe_nexa(miner *coin.MinerObj, id float64, extranonce1 string) { + miner.TxLock.Lock() + + var result [3]interface{} + //result[0] = results + result[0] = nil + if miner.Protocol == "yxminer" { + result[1] = extranonce1 + } else if miner.Protocol == "bzminer" || miner.Protocol == "lolminer" || miner.Protocol == "Rigel" || miner.Protocol == "WildRig" { + var result2 [2]interface{} + var result3 [2]interface{} + var result4 [2]interface{} + result3[0] = "mining.set_difficulty" + if miner.Protocol == "WildRig" { + result3[1] = extranonce1[:8] + } else { + result3[1] = miner.Difficulty + } + result4[0] = "mining.notify" + //result4[1] = extranonce1 + result4[1] = extranonce1[:8] + result2[0] = result3 + result2[1] = result4 + result[0] = result2 + + result[1] = extranonce1[:8] + //result[0] = fmt.Sprintf("[[%s,%.2f],[%s,%s]]", "mining.set_difficulty", miner.Difficulty, "mining.notify", extranonce1) + } else { + result[1] = extranonce1 + } + //result[1] = miner.Job.Extranonce1 + + //miner.Server.Logg.Debug("[server]", zap.Uint64("extra2", miner.Job.Extranonce2_size)) + if miner.Job.Extranonce2_size == 0 { + result[2] = 4 + } else { + if miner.Protocol == "yxminer" { + result[2] = miner.Job.Extranonce2_size + } else if miner.Protocol == "bzminer" || miner.Protocol == "lolminer" || miner.Protocol == "Rigel" || miner.Protocol == "WildRig" { + result[2] = 4 + } else { + result[2] = miner.Job.Extranonce2_size + } + } + + if extranonce1 == "" { + miner.TxLock.Unlock() + stratum.Handle_exception(miner, id, stratum.MINER_ERR_NOT_SUBSCRIBED) + return + } + + var body []byte + var err error + if miner.Protocol == "yxminer" { + var ack stratum.Subscribe_reply + ack.ID = id + ack.Result = result + ack.Error = nil + body, err = json.Marshal(ack) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + } else if miner.Protocol == "bzminer" || miner.Protocol == "lolminer" || miner.Protocol == "Rigel" || miner.Protocol == "WildRig" { + var ack stratum.SubscribeGpu_reply + ack.Jsonrpc = "2.0" + ack.ID = id + ack.Result = result + ack.Error = nil + body, err = json.Marshal(ack) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + } else { + var ack stratum.Subscribe_reply + ack.ID = id + ack.Result = result + ack.Error = nil + body, err = json.Marshal(ack) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + } + + var body_string = string(body) + "\n" + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + + miner.Status = coin.MINER_STATUS_SUBSCRIBED + miner.TxLock.Unlock() + + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) { + if strings.Contains(msg, "YxMiner") { + miner.Protocol = "yxminer" + } else if strings.Contains(msg, "BzMiner") { + miner.Protocol = "bzminer" + } else if strings.Contains(msg, "lolMiner") { + miner.Protocol = "lolminer" + } else if strings.Contains(msg, "Rigel") { + miner.Protocol = "Rigel" + } else if strings.Contains(msg, "WildRig") { + miner.Protocol = "WildRig" + } else { + miner.Protocol = "standard" + } + Handle_subscribe_nexa(miner, id, extranonce1) +} + +func HandleMinerAuth(miner *coin.MinerObj) { + +} + +func HandleMinerSubmit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + if miner.Protocol == "yxminer" { + } else if miner.Protocol == "bzminer" || miner.Protocol == "lolminer" || miner.Protocol == "Rigel" || miner.Protocol == "WildRig" { + nonce = nonce2 + nonce + } else { + } + accept_ok, submit_ok, handle_ok := handle_submit(miner, id, miner_user, job_id, nonce2, ntime, nonce) + return accept_ok, submit_ok, handle_ok +} + +func SetDifficulty(miner *coin.MinerObj) { + if miner.Protocol == "yxminer" { + stratum.Set_difficulty(miner) + } else { + stratum.Set_difficulty_nexa(miner) + } +} + +func NexaNotify(miner *coin.MinerObj) { + miner.TxLock.Lock() + if !((miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING)) { + miner.TxLock.Unlock() + return + } + miner.TxLock.Unlock() + if miner.DifficultyNext > -1 { + ratio := miner.DifficultyNext / miner.Difficulty + if ratio > 1.1 || ratio < 0.9 { + miner.Difficulty = miner.DifficultyNext + miner.DifficultyNext = -1 + if miner.Protocol == "yxminer" { + stratum.Set_difficulty(miner) + } else { + stratum.Set_difficulty_nexa(miner) + } + //logg.Info("[gbt]", zap.Float64("update Diff", miner.Difficulty)) + } else { + miner.DifficultyNext = -1 + } + } + miner.TxLock.Lock() + //log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId) + var params [5]interface{} + + idb := make([]byte, 4) + binary.BigEndian.PutUint32(idb, miner.JobId) + miner.Job.Job_id = hex.EncodeToString(idb) + params[0] = miner.Job.Job_id + params[1] = miner.NexaJob.Header + //params[3] = miner.NexaJob.Height + if miner.Protocol == "yxminer" { + params[2] = miner.NexaJob.NBits + params[3] = miner.NexaJob.CurTime + } else if miner.Protocol == "bzminer" || miner.Protocol == "lolminer" || miner.Protocol == "Rigel" || miner.Protocol == "WildRig" { + params[2] = miner.NexaJob.Height + params[3] = miner.NexaJob.NBits + } else { + params[2] = miner.NexaJob.NBits + params[3] = miner.NexaJob.CurTime + } + + miner.CurHeight = miner.NexaJob.Height + + if miner.Reconnect { + params[4] = true + miner.Reconnect = false + } else { + params[4] = miner.Job.IsClean + } + params[4] = true + miner.NexaJob.JobDifficulty = miner.Difficulty + + miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.NexaJob) + + /*var entry coin.JobListEntry + entry.Job_id = miner.Job.Job_id + entry.Ts = time.Now() + + miner.LockForJobs.Lock() + miner.JobList.PushFront(entry) + var removes string = "" + if miner.JobList.Len() > int(coin.LOCAL_JOBS_TOTAL_SIZE) { + e := miner.JobList.Back() + entry := e.Value.(coin.JobListEntry) + removes = entry.Job_id + miner.JobList.Remove(e) + } + miner.LockForJobs.Unlock() + + if len(removes) > 0 { + miner.Jobs.Delete(removes) + }*/ + stratum.AddAndUpdateJob(miner) + + stratum.UpdateJobs(miner) + + //miner.LastJobId = miner.Job.Job_id + miner.JobId++ + + var body []byte + var err error + + if miner.Protocol == "yxminer" { + var msg Notify_msg_nexa + msg.ID = nil + msg.Method = "mining.notify" + msg.Params = params + body, err = json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + } else if miner.Protocol == "bzminer" || miner.Protocol == "lolminer" || miner.Protocol == "Rigel" || miner.Protocol == "WildRig" { + var msg Notify_msg_nexa_gpu + msg.ID = nil + msg.Method = "mining.notify" + var params4 [4]interface{} + params4[0] = params[0] + params4[1] = params[1] + params4[2] = params[2] + params4[3] = params[3] + msg.Params = params4 + msg.Jsonrpc = "2.0" + body, err = json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + } else { + var msg Notify_msg_nexa + msg.ID = nil + msg.Method = "mining.notify" + msg.Params = params + body, err = json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + } + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Unlock() + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +func Notify(miner *coin.MinerObj) { + NexaNotify(miner) +} + +func HandleJobMsg(server *coin.ServerContext, Msg []byte) { + var result msg.NexaStratumJob + server.Logg.Warn("[server]", zap.String("receive", "job")) + + if err := json.Unmarshal(Msg, &result); err != nil { + server.Logg.Error("[server]", zap.String("Unmarshal", err.Error())) + return + } + server.NexaJob = msg.NexaStratumJob(result) + logg.Debug("[gbt]", zap.String("Target", server.NexaJob.Target)) + + server.NexaJob.Extranonce2_size = 8 + server.SJob.Extranonce2_size = 8 + logg.Debug("[gbt]", zap.Uint32("Height", server.NexaJob.Height), zap.String("Target", server.NexaJob.Target), zap.String("Header", server.NexaJob.Header) /*, zap.Uint64("Timastamp", server.NexaJob.CurTime)*/) + targetb, _ := hex.DecodeString(server.NexaJob.Target) + logg.Debug("[gbt]", zap.Uint64("Id", server.NexaJob.Id), zap.Float64("network diff", utility.Target2Diff(utility.Reverse(targetb)))) + + server.NetHight = uint64(server.NexaJob.Height) + server.NetTarget = server.NexaJob.Target + server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + server.Logg.Info("[server]", zap.String("lock", "start")) + m.TxLock.Lock() + status := m.Status + cmd := nexa_parse_miner_notify(m, server.NexaJob) + m.TxLock.Unlock() + server.Logg.Info("[server]", zap.String("lock", "end")) + var need_notify bool = true + if time.Now().Sub(m.ConnSetupTime) >= time.Duration(coin.CONN_EXPIRED_TIME)*time.Second { + if (status != coin.MINER_STATUS_RUNNING) && (status != coin.MINER_STATUS_AUTHORIZED) { + //m.Conn.Close() + need_notify = false + } + } + if need_notify { + switch cmd { + case 0: //extranonce 1 and extranonce2 size + //TODO + case 1: //notify + NexaNotify(m) + } + } + } + } + } + return true + }) +} + +func IsMhsLow(miner *coin.MinerObj) bool { + if miner.Mhs5M < 1 { + return true + } + return false +} + +func GetBlockInterval() int { + return 180 +} diff --git a/internal/server/randomxT/hash_randomx.go b/internal/server/randomxT/hash_randomx.go new file mode 100644 index 0000000..238c635 --- /dev/null +++ b/internal/server/randomxT/hash_randomx.go @@ -0,0 +1,117 @@ +package randomxT + +/* +#cgo CFLAGS: -I/home/lizixuan/桌面/tari-server/internal/server/include +#cgo LDFLAGS: -L/home/lizixuan/桌面/tari-server/internal/server/lib/randomx -lrandomx +#include +#include +#include +#include +*/ +import "C" + +import ( + "fmt" + "unsafe" + + "golang.org/x/sys/cpu" +) + +type RandomXValidator struct { + cache *C.randomx_cache + vm *C.randomx_vm + flags C.randomx_flags + seed []byte +} + +// NewRandomXValidator 初始化 cache + vm +func NewRandomXValidator(seed []byte) (*RandomXValidator, error) { + if len(seed) != 32 { + return nil, fmt.Errorf("seed must be 32 bytes") + } + + var flags C.randomx_flags = 0 + + // 检测 AES-NI 支持 + if cpu.X86.HasAES { + flags |= C.RANDOMX_FLAG_HARD_AES + } else { + fmt.Println("[RandomX] CPU 不支持 AES-NI,将使用纯软件模式") + } + + // ⚠️ 默认启用 JIT(如果系统禁止会报错) + flags |= C.RANDOMX_FLAG_JIT + + // 分配 cache + cache := C.randomx_alloc_cache(flags) + if cache == nil { + return nil, fmt.Errorf("failed to alloc cache") + } + C.randomx_init_cache(cache, unsafe.Pointer(&seed[0]), C.size_t(len(seed))) + + // 创建 vm + vm := C.randomx_create_vm(flags, cache, nil) + if vm == nil { + C.randomx_release_cache(cache) + return nil, fmt.Errorf("failed to create randomx vm") + } + + return &RandomXValidator{ + cache: cache, + vm: vm, + flags: flags, + seed: append([]byte{}, seed...), + }, nil +} + +// SetSeed 更新 seed(替换 cache,并重置 vm) +func (v *RandomXValidator) SetSeed(seed []byte) error { + if len(seed) != 32 { + return fmt.Errorf("seed must be 32 bytes") + } + + // 如果相同 seed,不用更新 + if string(seed) == string(v.seed) { + return nil + } + + C.randomx_init_cache(v.cache, unsafe.Pointer(&seed[0]), C.size_t(len(seed))) + C.randomx_vm_set_cache(v.vm, v.cache) + + v.seed = append(v.seed[:0], seed...) + return nil +} + +// Destroy 释放 vm + cache +func (v *RandomXValidator) Destroy() { + if v.vm != nil { + C.randomx_destroy_vm(v.vm) + v.vm = nil + } + if v.cache != nil { + C.randomx_release_cache(v.cache) + v.cache = nil + } +} + +// BuildPowHash 计算区块哈希 +func (v *RandomXValidator) BuildPowHash(blockBlob, nonce []byte) ([]byte, []byte, error) { + if v.vm == nil { + return nil, nil, fmt.Errorf("vm is nil") + } + + if len(nonce) != 4 { + return nil, nil, fmt.Errorf("nonce must be 4 bytes") + } + blockHeader := make([]byte, len(blockBlob)) + copy(blockHeader, blockBlob) + copy(blockHeader[39:43], nonce) + var hash [32]byte + C.randomx_calculate_hash(v.vm, + unsafe.Pointer(&blockHeader[0]), + C.size_t(len(blockHeader)), + unsafe.Pointer(&hash[0]), + ) + + return hash[:], blockHeader, nil +} diff --git a/internal/server/randomxT/randomxT.go b/internal/server/randomxT/randomxT.go new file mode 100644 index 0000000..e189435 --- /dev/null +++ b/internal/server/randomxT/randomxT.go @@ -0,0 +1,761 @@ +// sha3x.go +package randomxT + +import ( + "strconv" + //"database/sql" + "encoding/binary" + "encoding/hex" + "encoding/json" + + //"log" + //"math" + "math/big" + //"strings" + + "fmt" + "pool/internal/msg" + "pool/internal/server/coin" + "pool/internal/server/dbif" + "pool/internal/stratum" + "pool/internal/utility" + "time" + + _ "github.com/mattn/go-sqlite3" + + "go.uber.org/zap" +) + +const SERVER_SHA3X_VERSION string = "sha3x v0.1a" + +type Sha3xBlockHeader struct { + Nonce [8]byte + Header [32]byte + Algo byte +} + +func Sha3xBlockHeaderToBytes(h Sha3xBlockHeader) []byte { + out := make([]byte, 8+32+1) + for i := 0; i < 8; i++ { + out[i] = h.Nonce[i] + } + for i := 0; i < 32; i++ { + out[8+i] = h.Header[i] + } + out[8+32] = h.Algo + + return out +} + +type ServerSha3xContext struct { + ServerCtx *coin.ServerContext + logg *zap.Logger + + Sha3xJob msg.Sha3xStratumJob +} + +var logg *zap.Logger +var ServerSha3xCtx ServerSha3xContext + +type Sha3xNotify_params_msg struct { + Algo string `json:"algo"` + Blob string `json:"blob"` + Height uint32 `json:"height"` + Job_id string `json:"job_id"` + Target string `json:"target"` +} + +type Sha3xNotify_msg struct { + Jsonrpc string `json:"jsonrpc"` + Method string `json:"method"` + Params Sha3xNotify_params_msg `json:"params"` +} + +func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + var submit_item coin.BlockMsg + /*var user_blk_item coin.UserBlockMsg*/ + var pool_blk_item coin.PoolBlkMsg + + var blk_detail_height int64 + var blk_detail_hash string + var blk_detail_success bool + var blk_detail_miner_diff float64 + var blk_detail_pool_diff float64 + + if miner.Authorized != true { + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNAUTH_WORKER) + stratum.Send_reconnect_msg(miner) + return false, false, false + } + var new_found bool = false + var ack stratum.Submit_ack + ack.ID = id + ack.Result = true + //logg.Warn("[server]", zap.String("user", miner.User), zap.String("miner", miner.Miner)) + //logg.Debug("[server]", zap.Float64("id", id), zap.String("job_id", job_id)) + //logg.Debug("[server]", zap.String("nonce2", nonce2), zap.String("ntime", ntime), zap.String("nonce", nonce)) + //stratum.UpdateJobs(miner) + v, ok := miner.Jobs.Load(job_id) + if ok { + job := v.(msg.Sha3xStratumJob) + + if job.Height < miner.CurHeight-1 { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_STALED_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + //logg.Debug("[server]", zap.Uint64("ntime", nt), zap.Uint64("mintime", uint64(job.Mintime)), zap.Uint64("jobtime", jt_reverse)) + /*if nt < uint64(job.Mintime) { + ack.Result = false + util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_OLD) + } else if nt > jt_reverse+uint64(600) { + ack.Result = false + util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_NEW) + } else */{ + if (miner.LastNonce != nonce) || (miner.LastHeader != job.Header) { + miner.LastHeader = job.Header + miner.LastNonce = nonce + job.Nonce = nonce + job.Extranonce2 = nonce2 + //logg.Debug("[server]", zap.Uint32("height", job.Height), zap.String("target", job.Target)) + if miner.ZlogInit { + miner.Zlog.Info().Msg("height " + string(job.Height) + " target " + job.Target + " " + miner.User + "." + miner.Miner) + } + + phb, _ := hex.DecodeString(job.Header) + + nb, _ := hex.DecodeString(nonce) + + var calc_hash []byte + + var header Sha3xBlockHeader + for i := 0; i < 8; i++ { + header.Nonce[i] = nb[i] + } + for i := 0; i < 32; i++ { + header.Header[i] = phb[i] + } + header.Algo = 1 + submit_item.Header = hex.EncodeToString(Sha3xBlockHeaderToBytes(header)) + calc_hash = BuildPowHash(header) + + //logg.Debug("[server]", zap.String("hash in", submit_item.Header)) + //calc_hash, header := util.BuildBlockHash(&(job), true, Build_PowHash) + //logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/) + if miner.ZlogInit { + miner.Zlog.Info().Msg("hash in " + submit_item.Header + " calc_hash " + hex.EncodeToString(calc_hash) + " " + miner.User + "." + miner.Miner) + } + submit_target := new(big.Int) + //submit_target.SetBytes(common.Reverse(calc_hash)) + + //hashs, _ := utility.ReverseS(hex.EncodeToString(calc_hash)) + + //hashb, _ := hex.DecodeString(hashs) + //submit_target.SetBytes(hashb) + submit_target.SetBytes(calc_hash) + /*logg.Debug("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.Target.Bytes()))) + if submit_target.Cmp(miner.Target) > 0 {*/ + calc_diff := utility.Target2Diff(utility.Reverse(calc_hash)) + //calc_diff := utility.Target2Diff(calc_hash) + //log.Printf("diff,calc_diff:%f difficulty:%f ", calc_diff, miner.Difficulty) + //logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff)) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " target diff " + fmt.Sprintf("%f", (miner.Difficulty)) + " submit diff " + fmt.Sprintf("%f", (calc_diff))) + } + //logg.Debug("[server]", zap.String("target", miner.Target.String()), zap.Any("bytes", miner.Target.Bytes())) + //logg.Info("[server]", zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff), zap.String("target", hex.EncodeToString(miner.Target.Bytes()))) + + //if calc_diff < miner.Difficulty { + if calc_diff < job.JobDifficulty { + //gpu protocol handler + /*for i := 0; i < 8; i++ { + temp_nonce := header.Nonce[8+i] + header.Nonce[8+i] = header.Nonce[i] + header.Nonce[i] = temp_nonce + } + submit_item.Header = hex.EncodeToString(Sha3xBlockHeaderToBytes(header)) + calc_hash = BuildPowHash(header) + logg.Debug("[server]", zap.String("hash in", hex.EncodeToString(Sha3xBlockHeaderToBytes(header))))*/ + //logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/) + //submit_target = new(big.Int) + /*submit_target.SetBytes(calc_hash) + calc_diff = utility.Target2Diff(calc_hash) + logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff)) + if calc_diff < miner.Difficulty { + */ + ack.Result = false + miner.ErrLowDiffs = miner.ErrLowDiffs + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_LOW_DIF_SHARE) + return false, false, false + //} + + } + //logg.Warn("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes()))) + //submit_target.Text(16) + /*if submit_target.Cmp(miner.ServerTarget) <= 0 {*/ + //log.Println("[server]server_target", miner.ServerTargetS) + //stb, _ := hex.DecodeString(miner.ServerTargetS) + stb, _ := hex.DecodeString(job.Target) + //logg.Info("[server]", zap.String("target", job.Target)) + //server_diff := Target2Diff(common.Reverse(stb)) + server_diff := utility.Target2Diff(utility.Reverse(stb)) + //log.Printf("[server]server_diff %f", server_diff) + //logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff)) + //logg.Debug("[server]", zap.String("ServerTargetS", miner.ServerTargetS)) + network_target := new(big.Int) + network_target.SetBytes(stb) + //logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff)) + //logg.Debug("[server]", zap.String("submit_target", hex.EncodeToString(submit_target.Bytes())), zap.String("network_target", hex.EncodeToString(network_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes())), zap.Int("cmp", network_target.Cmp(submit_target))) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " calc_diff " + fmt.Sprintf("%f", (calc_diff)) + " miner.Difficulty " + fmt.Sprintf("%f", (miner.Difficulty)) + " server_diff " + fmt.Sprintf("%f", (server_diff))) + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " submit_target " + hex.EncodeToString(submit_target.Bytes()) + " network_target " + hex.EncodeToString(network_target.Bytes()) + " target " + hex.EncodeToString(miner.ServerTarget.Bytes()) + " cmp " + fmt.Sprintf("%d", (network_target.Cmp(submit_target)))) + } + + submit_item.Hash = hex.EncodeToString(calc_hash) + submit_item.Target = hex.EncodeToString(miner.Target.Bytes()) + submit_item.Submit_target = hex.EncodeToString(calc_hash) + submit_item.Height = int64(job.Height) + submit_item.Pow = hex.EncodeToString(calc_hash) + submit_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + /*user_blk_item.Height = int64(job.Height) + user_blk_item.Hash = hex.EncodeToString(calc_hash) + user_blk_item.Pow = hex.EncodeToString(calc_hash) + user_blk_item.Net_target = hex.EncodeToString(network_target.Bytes())*/ + + pool_blk_item.Height = int64(job.Height) + pool_blk_item.Hash = hex.EncodeToString(calc_hash) + pool_blk_item.Pow = hex.EncodeToString(calc_hash) + pool_blk_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + blk_detail_height = int64(job.Height) + blk_detail_hash = hex.EncodeToString(calc_hash) + blk_detail_success = false + //blk_detail_miner_diff = miner.Difficulty + blk_detail_miner_diff = job.JobDifficulty + blk_detail_pool_diff = miner.Server.RefDifficulty + + if ack.Result == true { + /*if miner.CurHeight != 0 && miner.CurHeight == job.Height { + return + }*/ + + //if true { + if (calc_diff >= server_diff) || (network_target.Cmp(submit_target) >= 0) { + //if true { + miner.Server.SubIdx++ + Produce_block_submit(miner /*header,*/, &job, submit_item.Hash, miner.Server.SubIdx) + miner.SubmitIndex++ + miner.Submits = miner.Submits + 1 + //miner.CurHeight = job.Height + new_found = true + } + if new_found && float64(miner.Server.Sha3xJob.U64target) <= calc_diff { + pool_blk_item.Submit = "y" + pool_blk_item.Success = false + pool_blk_item.Accepts = miner.Accepts + pool_blk_item.Rejects = miner.Rejects + pool_blk_item.Reward = 0 + pool_blk_item.Fee = 0 + pool_blk_item.Nonce = nonce + pool_blk_item.SubIdx = miner.Server.SubIdx + dbif.NotifyPoolBlkStatsDb2(miner.Server, &pool_blk_item) + } + } + } else { + miner.LastHeader = job.Header + miner.LastNonce = nonce + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_DUP_SHARE) + miner.ErrDuplicates = miner.ErrDuplicates + 1 + return false, false, false + } + } + } else { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_NOT_FOUND_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + miner.LastJobId = job_id + + ack.Error = nil + body, err := json.Marshal(ack) + if err != nil { + //logg.Error("[server]", zap.String("Marshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit Marshal " + err.Error()) + } + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNKNOWN) + return false, false, false + } + + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //miner.Server.Miners.Delete(miner.MinerId) + } + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } + //logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Lock() + miner.Status = coin.MINER_STATUS_RUNNING + miner.TxLock.Unlock() + + if ack.Result { + + miner.Accepts += miner.Difficulty + miner.M5Accepts += miner.Difficulty + + miner.VarDiffOpt.SubmitShares += miner.Difficulty + + } else { + miner.Rejects += miner.Difficulty + + } + now := time.Now() + if miner.Server.Config.Diff.Filter == "kalman" { + if ack.Result { + share_interval := now.Sub(miner.LastSubmitime).Seconds() + mhs := miner.Difficulty * share_interval + diff_next, kalman_p := miner.DiffHandler.Handler(miner.Difficulty, share_interval) + mhs_est := diff_next * miner.Server.Config.Diff.DiffAdjustInterval + + ratio := diff_next / miner.Difficulty + if ratio > 0 { + if now.Sub(miner.StartSubmitTime).Seconds() > 180 { + if ratio >= 2 { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else if ratio <= 0.5 { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else { + } + } else { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + /*if ratio >= 1.1 { + miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else if ratio <= 0.8 { + miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else { + }*/ + } + } + if miner.DifficultyNext > 0.0 { + if miner.DifficultyNext < miner.VarDiffOpt.MinDiff { + miner.DifficultyNext = miner.VarDiffOpt.MinDiff + } else if miner.DifficultyNext > miner.VarDiffOpt.MaxDiff { + miner.DifficultyNext = miner.VarDiffOpt.MaxDiff + } + } + //miner.VarDiffOpt.LastCalcTime = now + + if miner.Server.Config.Diff.Dbg { + coin.New_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, diff_next, kalman_p, share_interval, mhs, mhs_est) + } + + //log.Println("diff adjust", ratio, diff_next, miner.Difficulty, miner.DifficultyNext) + } + } else { + // submit time < DiffAdjustInterval,then up adjust diff + if now.Sub(miner.LastSubmitime).Seconds() < miner.Server.Config.Diff.DiffAdjustInterval { + if ack.Result { + if miner.VarDiffOpt.Uptimes++; miner.VarDiffOpt.Uptimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.UP_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Uptimes = 0 + } + + // submit time > 2 * DiffAdjustInterval,then down adjust diff + if now.Sub(miner.LastSubmitime).Seconds() > miner.Server.Config.Diff.DiffAdjustInterval*2 { + if ack.Result { + if miner.VarDiffOpt.Downtimes++; miner.VarDiffOpt.Downtimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.DOWN_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Downtimes = 0 + } + } + if ack.Result { + miner.LastSubmitime = now + miner.VarDiffOpt.LastSubmitTime = now + } + var duration float64 = float64(now.Sub(miner.StartSubmitTime)) / 1000000000 + + if duration < 1 { + duration = 1 + } + //diffOneShareHashesAvg := uint64(0x00000000FFFFFFFF) + diffOneShareHashesAvg := uint64(0xFFFFFFFFFFFFFFFF) + miner.AverageHashrate = miner.Accepts * float64(diffOneShareHashesAvg) / duration / 1000000 + var m5_duration float64 = float64(now.Sub(miner.M5SubmitTime)) / 1000000000 + if m5_duration >= float64(time.Minute*5)/1000000000 { + miner.M5SubmitTime = now + miner.M5Hashrate = miner.M5Accepts * float64(diffOneShareHashesAvg) / m5_duration / 1000000 + //logg.Info("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate)) + miner.M5Accepts = 0 + } + + //logg.Warn("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("Rejects", miner.Rejects)) + //logg.Info("[server]", zap.Float64("TargetShares", miner.VarDiffOpt.TargetShares), zap.Float64("MinShares", miner.VarDiffOpt.MinShares), zap.Float64("MaxShares", miner.VarDiffOpt.MaxShares), zap.Float64("SubmitShares", miner.VarDiffOpt.SubmitShares)) + //logg.Warn("[server]", zap.Float64("reject rate", miner.Rejects/(miner.Accepts+miner.Rejects)), zap.Float64("Hashrate(MH/S)", miner.AverageHashrate)) + //logg.Warn("[server]", zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate)) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit M5Accepts " + fmt.Sprintf("%f", (miner.M5Accepts)) + " M5Hashrate(MH/S) " + fmt.Sprintf("%f", (miner.M5Hashrate))) + } + + //logg.Info("[server]", zap.Float64("LastCalcTime", float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000)) + //calc acutal submit shares period of time, then compare with target shares and adjust diff + + if miner.Server.Config.Diff.Filter == "kalman" { + } else { + if float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000 >= miner.VarDiffOpt.AdjustTime { + coin.VarAdjustDifficulty(miner, coin.UPDATE_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + + if ack.Result { + + submit_item.Success = false + if new_found { + submit_item.Submit = "y" + submit_item.SubIdx = miner.Server.SubIdx + } else { + submit_item.Submit = "n" + submit_item.SubIdx = -1 + } + + submit_item.Accepts = miner.Accepts + submit_item.Total_accepts = miner.Accepts + submit_item.Rejects = miner.Rejects + submit_item.Total_rejects = miner.Rejects + submit_item.Reward = 0 + submit_item.Fee = 0 + submit_item.Nonce = nonce + + //dbif.NotifyMinerDb2(miner, &submit_item) + + dbif.NotifyBlkDetailDb(miner, blk_detail_height, blk_detail_hash, blk_detail_success, blk_detail_miner_diff, blk_detail_pool_diff, nonce, submit_item.SubIdx) + return true, new_found, true + } + return false, false, true +} + +func Produce_block_submit(miner *coin.MinerObj /*header Sha3xBlockHeader,*/, job *msg.Sha3xStratumJob, PowHash string, SubIdx int64) { + var nm msg.BlockSha3xMsg + nm.Id = job.Id + nm.Header = job.Header + //nm.Nonce = job.Nonce + noncer, _ := stratum.ReverseHexStringByByte(job.Nonce) + nonce, err := strconv.ParseUint(noncer, 16, 64) + nm.Nonce = nonce + nm.Pow = PowHash + nm.SubIdx = SubIdx + nm.User = miner.User + nm.Miner = miner.Miner + nm.Index = fmt.Sprint(miner.MinerIndex) + body, err := json.Marshal(nm) + if err != nil { + logg.Error("[server]", zap.String("failed to Marshal job", err.Error())) + return + } + blk := string(body) + + //Add Height + /*heightb := utility.Uint32ToByte(job.Height) + heights := hex.EncodeToString(heightb) + blk += heights + var Height uint32 = utility.ByteToUint32(heightb)*/ + nm.Height = (uint64)(job.Height) + logg.Warn("[server]", zap.Uint32("Height", job.Height)) + + //Add SubmitIndex + /*indexb := utility.Uint32ToByte(miner.SubmitIndex) + indexs := hex.EncodeToString(indexb) + blk += indexs + var SubmitIndex uint32 = utility.ByteToUint32(indexb)*/ + nm.SubmitIdx = (uint64)(miner.SubmitIndex) + logg.Info("[server]", zap.Uint32("SubmitIndex", miner.SubmitIndex)) + logg.Info("[server]", zap.String("blk", blk)) + + if miner.Server.PubCh == nil { + miner.Server.PubCh = utility.InitZmqPub(miner.Server.Config.Zmq.Pub) + } + if miner.Server.PubCh != nil { + //miner.Server.PubCh.SendChan <- [][]byte{[]byte("blksha3x"), []byte(blk)} + err := miner.Server.PubCh.SendMessage([][]byte{[]byte("blksha3x"), []byte(blk)}) + if err != nil { + miner.Server.PubCh.Destroy() + miner.Server.PubCh = nil + logg.Info("[server]", zap.String("blk", err.Error())) + } else { + logg.Info("[server]", zap.String("blk", "sent")) + } + } +} + +// server-->miner +func sha3x_parse_miner_notify(miner *coin.MinerObj, msg msg.Sha3xStratumJob) int { + if miner.Sha3xJob.Height != msg.Height { + miner.Job.IsClean = true + } + miner.Sha3xJob = msg + miner.Sha3xJob.Extranonce1 = miner.Job.Extranonce1 + miner.Job.Extranonce2_size = msg.Extranonce2_size + + //miner.Server.Logg.Info("[server]", zap.Int32("miner.Version", miner.Version), zap.Int32("msg.Version", msg.Version)) + return 1 +} + +func Init(server *coin.ServerContext) { + ServerSha3xCtx.ServerCtx = server + logg = server.Logg + logg.Info("[server]", zap.String("server_sha3x_version", SERVER_SHA3X_VERSION)) + coin.Init_diff_db() +} + +func Start() { + +} + +func Stop() { + coin.DiffStop() +} + +func InitMiner(miner *coin.MinerObj) { + miner.Sha3xJob = miner.Server.Sha3xJob + miner.Sha3xJob.Extranonce1 = miner.Job.Extranonce1 + + server_target := new(big.Int) + t_bytes, err := hex.DecodeString(miner.NexaJob.Target) + if err != nil { + logg.Error("[server]", zap.String("DecodeString", err.Error())) + return + } + //server_target.SetBytes(common.Reverse(t_bytes)) + server_target.SetBytes(t_bytes) + miner.ServerTarget = server_target + miner.ServerTargetS = miner.Server.SJob.Target +} + +func Handle_subscribe_sha3x(miner *coin.MinerObj, id float64, extranonce1 string) { + +} + +func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) { + +} + +func HandleMinerAuth(miner *coin.MinerObj) { + +} + +func HandleMinerSubmit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + //nonce_str, _ := stratum.ReverseHexStringByByte(nonce) + accept_ok, submit_ok, handle_ok := handle_submit(miner, id, miner_user, job_id, nonce2, ntime, nonce) + return accept_ok, submit_ok, handle_ok +} + +func SetDifficulty(miner *coin.MinerObj) { + stratum.Set_difficulty(miner) +} + +func Sha3xNotify(miner *coin.MinerObj) { + miner.TxLock.Lock() + if !((miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING)) { + miner.TxLock.Unlock() + return + } + miner.TxLock.Unlock() + if miner.DifficultyNext > -1 { + ratio := miner.DifficultyNext / miner.Difficulty + if ratio > 1.1 || ratio < 0.9 { + miner.Difficulty = miner.DifficultyNext + miner.DifficultyNext = -1 + stratum.Set_difficulty(miner) + //logg.Info("[gbt]", zap.Float64("update Diff", miner.Difficulty)) + } else { + miner.DifficultyNext = -1 + } + } + + miner.TxLock.Lock() + //log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId) + + var msg Sha3xNotify_msg + + idb := make([]byte, 4) + binary.BigEndian.PutUint32(idb, miner.JobId) + miner.Job.Job_id = hex.EncodeToString(idb) + + msg.Params.Algo = "sha3x" + msg.Params.Job_id = miner.Job.Job_id + msg.Params.Blob = miner.Sha3xJob.Header + msg.Params.Height = miner.Sha3xJob.Height + //target_s, _ := stratum.ReverseHexStringByByte(miner.Sha3xJob.Target) + //msg.Params.Target = target_s[48:] + target_new, _ := utility.DiffToTarget(miner.Difficulty) + target_str := fmt.Sprintf("%064x", target_new.Bytes()) + target_strr, strerr := stratum.ReverseHexStringByByte(target_str) + if strerr != nil { + println("ReverseHexStringByByte", strerr.Error()) + } + //println("target=", target_str, "r=", target_strr) + msg.Params.Target = target_strr[48:] + + miner.CurHeight = miner.Sha3xJob.Height + + miner.Sha3xJob.JobDifficulty = miner.Difficulty + + miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.Sha3xJob) + + /*var entry coin.JobListEntry + entry.Job_id = miner.Job.Job_id + entry.Ts = time.Now() + + miner.LockForJobs.Lock() + miner.JobList.PushFront(entry) + var removes string = "" + if miner.JobList.Len() > int(coin.LOCAL_JOBS_TOTAL_SIZE) { + e := miner.JobList.Back() + entry := e.Value.(coin.JobListEntry) + removes = entry.Job_id + miner.JobList.Remove(e) + } + miner.LockForJobs.Unlock() + + if len(removes) > 0 { + miner.Jobs.Delete(removes) + }*/ + stratum.AddAndUpdateJob(miner) + + stratum.UpdateJobs(miner) + + //miner.LastJobId = miner.Job.Job_id + miner.JobId++ + + var body []byte + var err error + + msg.Jsonrpc = "2.0" + msg.Method = "job" + + body, err = json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Unlock() + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +func Notify(miner *coin.MinerObj) { + Sha3xNotify(miner) +} + +func formatUint64ToHexWithPadding(val uint64) string { + hexStr := fmt.Sprintf("%016x", val) + + if len(hexStr) < 64 { + paddingLen := 64 - len(hexStr) + hexStr += string(make([]byte, paddingLen)) + for i := len(hexStr) - paddingLen; i < 64; i++ { + hexStr = hexStr[:i] + "0" + hexStr[i+1:] + } + } + return hexStr +} + +func HandleJobMsg(server *coin.ServerContext, Msg []byte) { + var result msg.Sha3xStratumJob + server.Logg.Warn("[server]", zap.String("receive", "job")) + + if err := json.Unmarshal(Msg, &result); err != nil { + server.Logg.Error("[server]", zap.String("Unmarshal", err.Error())) + return + } + result.Target = formatUint64ToHexWithPadding(result.U64target) + + //target_new, _ := utility.DiffToTarget((float64)(result.U64target)) + //target_str := fmt.Sprintf("%064x", target_new.Bytes()) + //result.Target = target_str + + server.Sha3xJob = msg.Sha3xStratumJob(result) + logg.Debug("[gbt]", zap.String("Target", server.Sha3xJob.Target)) + + server.Sha3xJob.Extranonce2_size = 8 + server.SJob.Extranonce2_size = 8 + logg.Debug("[gbt]", zap.Uint32("Height", server.Sha3xJob.Height), zap.String("Target", server.Sha3xJob.Target), zap.String("Header", server.Sha3xJob.Header) /*, zap.Uint64("Timastamp", server.Sha3xJob.CurTime)*/) + targetb, _ := hex.DecodeString(server.Sha3xJob.Target) + logg.Debug("[gbt]", zap.Uint64("Id", server.Sha3xJob.Id), zap.Float64("network diff", utility.Target2Diff(utility.Reverse(targetb)))) + + server.NetHight = uint64(server.Sha3xJob.Height) + server.NetTarget = server.Sha3xJob.Target + server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + server.Logg.Info("[server]", zap.String("lock", "start")) + m.TxLock.Lock() + status := m.Status + cmd := sha3x_parse_miner_notify(m, server.Sha3xJob) + m.TxLock.Unlock() + server.Logg.Info("[server]", zap.String("lock", "end")) + var need_notify bool = true + if time.Now().Sub(m.ConnSetupTime) >= time.Duration(coin.CONN_EXPIRED_TIME)*time.Second { + if (status != coin.MINER_STATUS_RUNNING) && (status != coin.MINER_STATUS_AUTHORIZED) { + //m.Conn.Close() + need_notify = false + } + } + if need_notify { + switch cmd { + case 0: //extranonce 1 and extranonce2 size + //TODO + case 1: //notify + Sha3xNotify(m) + } + } + } + } + } + return true + }) +} + +func IsMhsLow(miner *coin.MinerObj) bool { + if miner.Mhs5M < 1 { + return true + } + return false +} + +func GetBlockInterval() int { + return 3600 +} diff --git a/internal/server/server.go b/internal/server/server.go new file mode 100644 index 0000000..1915a0a --- /dev/null +++ b/internal/server/server.go @@ -0,0 +1,1865 @@ +// server.go +package server + +import ( + "bufio" + "container/list" + "context" + "encoding/binary" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "log" + + //"math/big" + "net" + "os" + "os/signal" + "pool/internal/db" + "pool/internal/server/coin" + "pool/internal/server/dbif" + "pool/internal/server/sha3x" + + "math/rand" + "pool/internal/cache" + "pool/internal/stratum" + "pool/internal/utility" + + "runtime" + "strings" + "sync" + "sync/atomic" + "syscall" + "time" + + "github.com/rs/zerolog" + + "github.com/redis/go-redis/v9" + "go.uber.org/zap" + "gopkg.in/natefinch/lumberjack.v2" +) + +var logg *zap.Logger +var logr *lumberjack.Logger +var ServerCtx coin.ServerContext + +func InitConfig() *coin.ServerConfig { + var config coin.ServerConfig + data, err := ioutil.ReadFile("server.conf") + if err != nil { + panic(err.Error()) + } + if err = json.Unmarshal(data, &config); err != nil { + panic(err.Error()) + } + return &config +} + +/*func ServerLivingHandler(server *coin.ServerContext) { + timer := time.NewTimer(time.Duration(600) * time.Second) + defer timer.Stop() + for { + select { + case living := <-server.AlivingChan: + if !living { + timer.Stop() + //log.Println("ServerLivingHandler exited, living: false") + server.Logg.Error("[server]", zap.String("ServerLivingHandler exited", "living: false")) + return + } else { + if !timer.Stop() { + <-timer.C + } + timer.Reset(time.Duration(600) * time.Second) + } + server.Logg.Error("[server]", zap.String("ServerLivingHandler exited", "living: true")) + case <-timer.C: + //log.Println("ServerLivingHandler exited, timer expired") + server.Logg.Error("[server]", zap.String("ServerLivingHandler exited", "timer expired")) + server.LiveingExpired = true + server.DbCtx.AppExit <- true + return + } + } +}*/ + +func ServerLivingHandler(server *coin.ServerContext) { + var to_cnt int = 0 + for { + flagAliving := atomic.LoadInt32(&(server.FlagAliving)) + flagExit := atomic.LoadInt32(&(server.FlagAlivingExit)) + + if flagExit == 1 { + server.Logg.Error("[server]", zap.String("ServerLivingHandler exited", "exit")) + break + } + + if flagAliving == 0 { + if to_cnt > server.CoinCtx.GetBlockInterval() { + server.Logg.Error("[server]", zap.String("ServerLivingHandler exited", "timer expired")) + server.DbCtx.AppExit <- true + break + } + to_cnt++ + } else { + to_cnt = 0 + atomic.StoreInt32(&(server.FlagAliving), 0) + } + + time.Sleep(time.Second) + } +} + +var coinobjs = []coin.CoinObj{ + // { + // Coin: "nexa", + // Init: nexa.Init, + // Start: nexa.Start, + // Stop: nexa.Stop, + // InitMiner: nexa.InitMiner, + // HandleMinerSubscribe: nexa.HandleMinerSubscribe, + // HandleMinerAuth: nexa.HandleMinerAuth, + // HandleMinerSubmit: nexa.HandleMinerSubmit, + // SetDifficulty: nexa.SetDifficulty, + // Notify: nexa.Notify, + // HandleJobMsg: nexa.HandleJobMsg, + // IsMhsLow: nexa.IsMhsLow, + // GetBlockInterval: nexa.GetBlockInterval, + // }, + { + Coin: "sha3x", + Init: sha3x.Init, + Start: sha3x.Start, + Stop: sha3x.Stop, + InitMiner: sha3x.InitMiner, + HandleMinerSubscribe: sha3x.HandleMinerSubscribe, + HandleMinerAuth: sha3x.HandleMinerAuth, + HandleMinerSubmit: sha3x.HandleMinerSubmit, + SetDifficulty: sha3x.SetDifficulty, + Notify: sha3x.Notify, + HandleJobMsg: sha3x.HandleJobMsg, + IsMhsLow: sha3x.IsMhsLow, + GetBlockInterval: sha3x.GetBlockInterval, + }, + // { + // Coin: "monero", + // Init: monero.Init, + // Start: monero.Start, + // Stop: monero.Stop, + // InitMiner: monero.InitMiner, + // HandleMinerSubscribe: monero.HandleMinerSubscribe, + // HandleMinerAuth: monero.HandleMinerAuth, + // HandleMinerSubmit: monero.HandleMinerSubmit, + // SetDifficulty: monero.SetDifficulty, + // Notify: monero.Notify, + // HandleJobMsg: monero.HandleJobMsg, + // IsMhsLow: monero.IsMhsLow, + // GetBlockInterval: monero.GetBlockInterval, + // }, +} + +func register_signal(dbctx *db.DbContext) { + signal_ch := make(chan os.Signal, 1) + signal.Notify(signal_ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT) + go signal_handle(signal_ch, dbctx) +} + +func signal_handle(signal_ch chan os.Signal, DbCtx *db.DbContext) { + for s := range signal_ch { + switch s { + case syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT: + DbCtx.AppExit <- true + //log.Println("stop signal!") + if logg != nil { + logg.Error("[server]", zap.String("signal", "stop")) + } + default: + //fmt.Println("other signal", s) + } + } +} + +func register_user_signal(server *coin.ServerContext) { + signal_ch := make(chan os.Signal, 1) + signal.Notify(signal_ch, syscall.SIGUSR1) + go user_signal_handle(signal_ch, server) +} + +func user_signal_handle(signal_ch chan os.Signal, ctx *coin.ServerContext) { + for s := range signal_ch { + switch s { + case syscall.SIGUSR1: + //log.Println("user signal 1!") + if logg != nil { + logg.Error("[server]", zap.String("signal", "user 1")) + } + default: + //fmt.Println("other signal", s) + } + } +} + +func do_keepalive_ping(server *coin.ServerContext) { + timer := time.NewTimer(time.Duration(5) * time.Second) + defer timer.Stop() + var total_miners int32 = 0 + for { + if server.ExitFlag { + break + } + select { + //case <-time.After(time.Duration(5) * time.Second): + case <-timer.C: + timer.Reset(time.Duration(5) * time.Second) + var cur_miners int32 = 0 + server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + //if m.User == "" || m.Miner == "" { + //return true + //} + //if (m.Status != coin.MINER_STATUS_AUTHORIZED) && (m.Status != coin.MINER_STATUS_RUNNING) { + //return true + //} + cur_miners += 1 + if time.Now().Sub(m.ConnSetupTime).Seconds() < 10 { + return true + } + + if (m.Status == coin.MINER_STATUS_CONNECTED) || (m.Status == coin.MINER_STATUS_SUBSCRIBED) { + log.Println("ip status error", m.Status, m.FromIP) + m.Conn.Close() + return true + } + + if time.Now().Sub(m.ConnSetupTime).Seconds() > 120 { + if m.Status == coin.MINER_STATUS_AUTHORIZED { + log.Println("ip not submit", m.Status, m.FromIP) + m.Conn.Close() + return true + } + } + + if m.RecvedLiveAck { + m.RecvedLiveAck = false + m.PongFailCnt = 0 + m.PingEnabled = true + } else { + if m.PingEnabled { + m.PongFailCnt = m.PongFailCnt + 1 + //log.Println("ping", m.RecvedLiveAck, m.PongFailCnt) + if m.PongFailCnt > stratum.STRATUM_PING_FAILED_MAX_CNT { + //server.Logg.Error("[server]", zap.String("ping fail", fmt.Sprint(m.PongFailCnt)+m.User+"."+m.Miner)) + if m.ZlogInit { + m.Zlog.Info().Msg("ping failed " + fmt.Sprint(m.PongFailCnt) + " " + m.User + "." + m.Miner) + } + + m.Conn.Close() + return true + } + } + } + m.PingCnt = m.PingCnt + 1 + if m.PingCnt > stratum.STRATUM_PING_INTERVAL_CNT { + if server.CoinCtx.Coin != "sha3x" || server.CoinCtx.Coin != "monero" { + m.PingCnt = 0 + var msg stratum.Ping_msg + msg.ID = m.KeepliveCnt + msg.Method = "mining.ping" + msg.Params = nil + m.KeepliveCnt++ + body, err := json.Marshal(msg) + if err != nil { + //server.Logg.Error("[server]", zap.String("failed to do_keeplive_ping", err.Error()), zap.String("user", m.User), zap.String("miner", m.Miner)) + if m.ZlogInit { + m.Zlog.Info().Msg("failed to Marshal " + err.Error() + " " + m.User + "." + m.Miner) + } + return true + } + body_string := string(body) + "\n" + err = stratum.Conn_tx(m.Conn, []byte(body_string)) + if err != nil { + //server.Logg.Error("[server]", zap.String("failed to do_keeplive_ping", err.Error()), zap.String("user", m.User), zap.String("miner", m.Miner)) + if m.ZlogInit { + m.Zlog.Info().Msg("failed to do_keeplive_ping " + err.Error() + " " + m.User + "." + m.Miner) + } + return true + } + } + } + } + } + } + return true + }) + //if cur_miners > total_miners { + total_miners = cur_miners + log.Println("total_miners", total_miners) + //} + case <-server.ExitPingChan: + //log.Println("exit do_keepalive_ping!") + server.Logg.Error("[server]", zap.String("do_keepalive_ping", "exit by chan")) + return + } + } +} + +func HandleKeepAlive(server *coin.ServerContext) { + // do_keepalive_ping(server) +} + +func init_miner(miner *coin.MinerObj, conn net.Conn, server *coin.ServerContext) { + atomic.StoreInt32(&(miner.NeedExit), 0) + miner.ZlogInit = false + //miner.EndCh = make(chan bool, 32768) + miner.FromIP = conn.RemoteAddr().String() + est_time := time.Now() + miner.OnlineTime = est_time + miner.OfflineTime = est_time + miner.Retry = 0 + miner.DurationTime = 0 + miner.MinerIndex = server.MinerIndex + //server.MinerIndex++ + + miner.ErrStaleds = 0 + miner.ErrLowDiffs = 0 + miner.ErrDuplicates = 0 + miner.ErrFormats = 0 + miner.ErrOthers = 0 + + miner.IsDisabled = false + + miner.Submits = 0 + miner.Blocks = 0 + miner.Orphans = 0 + + miner.Accepts5M = 0 + miner.Accepts15M = 0 + miner.Accepts30M = 0 + miner.Accepts1h = 0 + miner.Accepts3h = 0 + miner.Accepts6h = 0 + miner.Accepts12h = 0 + miner.Accepts24h = 0 + miner.Accepts48h = 0 + + miner.Rejects5M = 0 + miner.Rejects15M = 0 + miner.Rejects30M = 0 + miner.Rejects1h = 0 + miner.Rejects3h = 0 + miner.Rejects6h = 0 + miner.Rejects12h = 0 + miner.Rejects24h = 0 + miner.Rejects48h = 0 + + miner.Mhs5M = 0 + miner.Mhs15M = 0 + miner.Mhs30M = 0 + miner.Mhs1h = 0 + miner.Mhs3h = 0 + miner.Mhs6h = 0 + miner.Mhs12h = 0 + miner.Mhs24h = 0 + miner.Mhs48h = 0 + + miner.Reward = 0 + miner.Fee = 0 + + miner.Name = server.MinerType + miner.MinerId = coin.Guid() + miner.Accepts = 0 + miner.Rejects = 0 + miner.M5Accepts = 0 + miner.AverageHashrate = 0 + miner.M5Hashrate = 0 + miner.Conn = conn + + miner.KeepliveCnt = 0 + miner.RecvedLiveAck = false + miner.PongFailCnt = 0 + miner.PingCnt = 0 + + miner.Difficulty = server.Config.Diff.StartDifficulty + miner.DifficultyNext = -1 + + var jobs sync.Map + miner.Jobs = jobs + + var jobs_lock sync.Mutex + miner.LockForJobs = jobs_lock + + miner.JobList = list.New() + miner.LastJobId = "" + miner.Server = server + miner.StartSubmitTime = est_time + miner.LastSubmitime = est_time + miner.SubmitIndex = 0 + miner.M5SubmitTime = est_time + + miner.Job = server.SJob + + miner.Status = coin.MINER_STATUS_CONNECTED + var txlock sync.Mutex + miner.TxLock = txlock + miner.ConnSetupTime = est_time + miner.Reconnect = true + miner.Authorized = false + miner.PingEnabled = false + be1 := make([]byte, 8) + binary.LittleEndian.PutUint64(be1, (miner.Server.Extranonce1 /* + 0x81000000*/)) + miner.Job.Extranonce1 = hex.EncodeToString(be1) + //miner.NexaJob.Extranonce1 = miner.Job.Extranonce1 + miner.Server.Extranonce1++ + + target, err := utility.DiffToTarget(miner.Difficulty) + if err != nil { + logg.Error("[server]", zap.String("DiffToTarget", err.Error())) + return + } + miner.Target = target + logg.Debug("[target]", zap.String("target", hex.EncodeToString(target.Bytes())), zap.Float64("diff", miner.Difficulty)) + + /*server_target := new(big.Int) + t_bytes, err := hex.DecodeString(miner.NexaJob.Target) + if err != nil { + logg.Error("[server]", zap.String("DecodeString", err.Error())) + return + } + //server_target.SetBytes(common.Reverse(t_bytes)) + server_target.SetBytes(t_bytes) + miner.ServerTarget = server_target + miner.ServerTargetS = server.SJob.Target*/ + + miner.VarDiffOpt.VariancePercent = miner.Server.Config.Diff.DiffAdjustPercentage + miner.VarDiffOpt.AdjustTime = miner.Server.Config.Diff.DiffAdjustTime + miner.VarDiffOpt.MinShares = miner.VarDiffOpt.AdjustTime / miner.Server.Config.Diff.DiffAdjustInterval * miner.Difficulty * (1 - miner.VarDiffOpt.VariancePercent) + miner.VarDiffOpt.MaxShares = miner.VarDiffOpt.AdjustTime / miner.Server.Config.Diff.DiffAdjustInterval * miner.Difficulty * (1 + miner.VarDiffOpt.VariancePercent) + miner.VarDiffOpt.TargetShares = miner.VarDiffOpt.AdjustTime / miner.Server.Config.Diff.DiffAdjustInterval * miner.Difficulty + miner.VarDiffOpt.MinDiff = miner.Server.Config.Diff.DiffMin + miner.VarDiffOpt.MaxDiff = miner.Server.Config.Diff.DiffMax + miner.VarDiffOpt.AdjustInterval = miner.Server.Config.Diff.DiffAdjustInterval + miner.VarDiffOpt.SubmitShares = 0 + miner.VarDiffOpt.SilenceCount = 0 + miner.VarDiffOpt.LastCalcTime = est_time + miner.VarDiffOpt.LastSubmitTime = est_time + miner.VarDiffOpt.Level = coin.Mid + miner.VarDiffOpt.Uptimes = 0 + miner.VarDiffOpt.Downtimes = 0 + + miner.DiffHandler.Init(miner.Difficulty, miner.Server.Config.Diff.DiffMin, miner.Server.Config.Diff.DiffMax, miner.Server.Config.Diff.DiffAdjustInterval) + + server.CoinCtx.InitMiner(miner) +} + +/*func UpdateUserSets(miner *coin.MinerObj, is_delete bool) { + + miner.Server.UsersSLock.Lock() + + user_key := miner.User + "00000000" + + item_key := miner.User + "_" + miner.Miner + "_" + fmt.Sprint(miner.MinerIndex) + + sets, ok := miner.Server.Users.Load(user_key) + if ok { + c_sets := sets.(coin.UserMinerContainer) + _, ok_item := c_sets.Data[item_key] + if ok_item { + if is_delete { + delete(c_sets.Data, item_key) + if len(c_sets.Data) > 0 { + miner.Server.Users.Store(user_key, c_sets) + logg.Debug("[server]", zap.String("delete user item", user_key+":"+item_key)) + + } else { + miner.Server.Users.Delete(user_key) + logg.Debug("[server]", zap.String("delete user", user_key+":"+item_key)) + } + } + } else { + c_sets.Data[item_key] = miner.MinerId + miner.Server.Users.Store(user_key, c_sets) + logg.Debug("[server]", zap.String("add user item", user_key+":"+item_key)) + //fmt.Printf("UpdateUserSets user_key=%v,new_c=%v\n", user_key, c_sets) + } + } else { + if !is_delete { + new_sets := make(map[string]string) + new_sets[item_key] = miner.MinerId + var new_c coin.UserMinerContainer + new_c.Data = new_sets + miner.Server.Users.Store(user_key, new_c) + logg.Debug("[server]", zap.String("new user", user_key+":"+item_key)) + //fmt.Printf("UpdateUserSets user_key=%v,new_c=%v\n", user_key, new_c) + } + } + + miner.Server.UsersSLock.Unlock() +}*/ + +func NotifyMinerEnd(miner *coin.MinerObj) { + miner.Server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + if m.User == "" || m.Miner == "" || fmt.Sprint(m.MinerIndex) == "" { + return true + } + //if (m.Accepts > 0) && (m.Status == coin.MINER_STATUS_DISCONNECTED) { + if m.Status == coin.MINER_STATUS_DISCONNECTED { + if (m.User == miner.User) && (m.Miner == miner.Miner) && (m.MinerId != miner.MinerId) { + miner.OfflineTime = m.OfflineTime + //m.EndCh <- true + atomic.StoreInt32(&(m.NeedExit), 1) + + } + } + } + } + } + return true + }) +} + +func RestoreMinerFromCache(miner *coin.MinerObj) { + val := cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "submits") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.Submits += intVal + } + } + + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "blocks") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.Blocks += intVal + } + } + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "rejects") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.Rejects += float64(intVal) + } + } + + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "retry") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.Retry += int64(intVal) + } + } + + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "staleds") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.ErrStaleds += intVal + } + } + + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "lowdiffs") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.ErrLowDiffs += intVal + } + } + + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "duplicates") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.ErrDuplicates += intVal + } + } + + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "formats") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.ErrFormats += intVal + } + } + + val = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "others") + if val != nil { + if intVal, ok := val.(int64); ok { + miner.ErrOthers += intVal + } + } + + val_f := cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "accepts") + if val_f != nil { + if fVal, ok := val_f.(float64); ok { + miner.Accepts = fVal + } + } + + val_f = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "rewards") + if val_f != nil { + if fVal, ok := val_f.(float64); ok { + miner.Reward = fVal + } + } + + val_f = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "fee") + if val_f != nil { + if fVal, ok := val_f.(float64); ok { + miner.Fee = fVal + } + } + + /*val_f = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "diff") + if val_f != nil { + if fVal, ok := val_f.(float64); ok { + miner.Difficulty = fVal + } + }*/ + + val_t := cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "startsubmit") + if val_f != nil { + if tVal, ok := val_t.(time.Time); ok { + miner.StartSubmitTime = tVal + } + } + + /*val_t = cache.LoadMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "lastsubmit") + if val_t != nil { + if tVal, ok := val_t.(time.Time); ok { + miner.LastSubmitTime = tVal + } + }*/ + StartSubmitTime_cnt := 0 + Accepts_cnt := 0 + Rejects_cnt := 0 + k := miner.User + "." + miner.Miner + "_" + fmt.Sprint(miner.MinerIndex) + m, ok := miner.Server.MMhs.Load(k) + if ok { + if m != nil { + var mhs *coin.MhsObj = m.(*coin.MhsObj) + if mhs != nil { + val_t = cache.LoadMhsCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "starttime") + if val_t != nil { + if tVal, ok := val_t.(time.Time); ok { + mhs.StartSubmitTime = tVal + StartSubmitTime_cnt++ + } + } + + val_items := cache.LoadMhsCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "accepts") + if val_items != nil { + if itemsVal, ok := val_items.(*[]cache.CacheMhsItem); ok { + for _, item := range *itemsVal { + var mhsItem coin.MhsItem + mhsItem.Tt, _ = time.Parse(time.RFC3339, item.Tt) + mhsItem.Diff = item.Diff + mhs.Accepts = append(mhs.Accepts, mhsItem) + Accepts_cnt++ + } + } + } + val_items = cache.LoadMhsCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "rejects") + if val_items != nil { + if itemsVal, ok := val_items.(*[]cache.CacheMhsItem); ok { + for _, item := range *itemsVal { + var mhsItem coin.MhsItem + mhsItem.Tt, _ = time.Parse(time.RFC3339, item.Tt) + mhsItem.Diff = item.Diff + mhs.Rejects = append(mhs.Rejects, mhsItem) + Rejects_cnt++ + } + } + } + miner.Server.MMhs.Store(k, m) + } + } + } + + log.Println("from redis", miner.User+"."+miner.Miner, "Submits", miner.Submits, "Blocks", miner.Blocks, "Rejects", miner.Rejects, "Retry", miner.Retry, "ErrStaleds", miner.ErrStaleds, "ErrLowDiffs", miner.ErrLowDiffs, "ErrDuplicates", miner.ErrDuplicates, "ErrFormats", miner.ErrFormats, "ErrOthers", miner.ErrOthers, "Accepts", miner.Accepts, "Reward", miner.Reward, "Fee", miner.Fee, "StartSubmitTime", miner.StartSubmitTime, "mhs cnt", StartSubmitTime_cnt, Accepts_cnt, Rejects_cnt) +} + +func RandomSleep(min time.Duration, max time.Duration) { + // Seed the random number generator + rand.Seed(time.Now().UnixNano()) + + // Generate a random duration between min and max + duration := time.Duration(rand.Int63n(int64(max-min)) + int64(min)) + + // Sleep for the generated duration + //fmt.Printf("Sleeping for %v\n", duration) + time.Sleep(duration) + //fmt.Println("Woke up!") +} + +func handle_miner_connection(miner *coin.MinerObj) { + //var count int = 0 + + miner.Conn.SetReadDeadline(time.Now().Add(30 * time.Second)) + + reader := bufio.NewReader(miner.Conn) + //var rxmsg string + for { + /*msg, err := reader.ReadString('\n') + if err != nil { + //if err != io.EOF { + logg.Error("[server]", zap.String("ReadString", err.Error())) + break + //} else { + // continue + //} + }*/ + msg, err := reader.ReadString('\n') + + if err != nil { + if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + logg.Warn("[server] read timeout, retrying...") + time.Sleep(1 * time.Second) + miner.Conn.SetReadDeadline(time.Now().Add(30 * time.Second)) + continue + } + need_break := true + if errors.Is(err, net.ErrClosed) || errors.Is(err, io.EOF) { + if errors.Is(err, io.EOF) && len(msg) > 0 { + need_break = false + } else { + logg.Error("[server]", zap.String("ReadString", err.Error())) + break + } + } + if need_break { + logg.Error("[server] read error", zap.Error(err)) + break + } + /*if err, ok := err.(net.Error); ok && err.Timeout() { + time.Sleep(1 * time.Second) + miner.Conn.SetReadDeadline(time.Now().Add(30 * time.Second)) + continue + } + if err != io.EOF { + logg.Error("[server]", zap.String("ReadString", err.Error())) + break + } else { + if (err == io.EOF) && len(msg) <= 0 { + logg.Error("[server]", zap.String("ReadString", err.Error())) + break + } + }*/ + } + + miner.Conn.SetReadDeadline(time.Now().Add(30 * time.Second)) + + msgSize := len(msg) + if msgSize >= 1024 { + logg.Error("[server]", zap.Int("ReadString too long", msgSize)) + break + } + /*var msg string + buffer := make([]byte, 1024) + rdn, err := reader.Read(buffer) + if err != nil { + if err != io.EOF || ((err == io.EOF) && (rdn <= 0)) { + //logg.Error("[server]", zap.String("Read", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " Read " + err.Error()) + } + break + } + } + if rdn > 0 { + //count = 0 + //log.Println("rxmsg", string(buffer[:rdn])) + rxmsg += string(buffer[:rdn]) + retch_index := strings.Index(rxmsg, "\n") + if retch_index != -1 { //found + msg = rxmsg[:retch_index+1] + tempmsg := rxmsg[retch_index+1:] + rxmsg = tempmsg + } else { //not found, discard + rxmsg = "" + } + }*/ + //log.Println("msg", msg) + if len(msg) > 0 { + miner.RecvedLiveAck = true + msg = strings.TrimSpace(msg) + if (miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING) { + if miner.ZlogInit { + miner.Zlog.Info().Msg(msg) + } + } + var ret map[string]interface{} + err = json.Unmarshal([]byte(msg), &ret) + if err == nil { + //logg.Debug("[server]", zap.Any("msg", msg)) + + _, ok := ret["method"].(string) + if ok { + switch ret["method"].(string) { + case "mining.pong": + Miner_difficulty_adjust(miner) + //miner.RecvedLiveAck = true + break + case "mining.subscribe": + _, idok := (ret["id"].(float64)) + if idok { + miner.Server.CoinCtx.HandleMinerSubscribe(miner, (ret["id"].(float64)), miner.Job.Extranonce1, msg) + } + break + case "mining.extranonce.subscribe": + _, idok := (ret["id"].(float64)) + if idok { + stratum.Handle_extranonce(miner, (ret["id"].(float64))) + } + break + case "mining.authorize": + case "login": + _, idok := (ret["id"].(float64)) + if idok { + auth_ok := stratum.Handle_authorize(miner, (ret["id"].(float64)), msg, miner.Server.DbCtx) + if auth_ok { + // miner.Server.CoinCtx.SetDifficulty(miner) + // miner.Server.CoinCtx.Notify(miner) + } + } + break + case "submit": + prev_status := miner.Status + var s stratum.Sha3xSubmit_nonce + if err = json.Unmarshal([]byte(msg), &s); err != nil { + //logg.Error("[server]", zap.String("mining.submit Unmarshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg("failed to mining.submit Unmarshal " + err.Error() + " " + miner.User + "." + miner.Miner) + } + } else { + accept_ok := false + submit_ok := false + handle_ok := false + accept_ok, submit_ok, handle_ok = miner.Server.CoinCtx.HandleMinerSubmit(miner, (ret["id"].(float64)), s.Params.Id, s.Params.Job_id, "", "", s.Params.Nonce) + + if handle_ok { + if (prev_status == coin.MINER_STATUS_AUTHORIZED) && (miner.Status == coin.MINER_STATUS_RUNNING) { + NotifyMinerEnd(miner) + stratum.InitMinerMhs(miner, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.MinerId, miner.Status, miner.Server.DbCtx) + } + if accept_ok { + if submit_ok { + miner.Submits += 1 + } + if miner.Accepts == 1 { + miner.Retry += 1 + } + + stratum.UpdateMhs(miner, true, miner.Difficulty, 0, miner.Server.DbCtx) + } else { + stratum.UpdateMhs(miner, false, miner.Difficulty, 0, miner.Server.DbCtx) + } + } + } + break + case "keepalived": + if params, ok := ret["params"].(map[string]interface{}); ok { + if params["id"] == miner.Session { + // handle keepalived + var keepalived_msg stratum.KeepAlived_resp + keepalived_msg.ID = 1 + keepalived_msg.Jsonrpc = "2.0" + keepalived_msg.Result.Status = "KEEPALIVED" + // 转换成 JSON []byte + data, err := json.Marshal(keepalived_msg) + if err != nil { + panic(err) + } + stratum.Conn_tx(miner.Conn, data) + } + } + case "mining.submit": + prev_status := miner.Status + var s stratum.Submit_nonce + if err = json.Unmarshal([]byte(msg), &s); err != nil { + //logg.Error("[server]", zap.String("mining.submit Unmarshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg("failed to mining.submit Unmarshal " + err.Error() + " " + miner.User + "." + miner.Miner) + } + } else { + accept_ok := false + submit_ok := false + handle_ok := false + if len(s.Params) == 3 { + accept_ok, submit_ok, handle_ok = miner.Server.CoinCtx.HandleMinerSubmit(miner, (ret["id"].(float64)), s.Params[0], s.Params[1], "", "", s.Params[2]) + } else if len(s.Params) == 5 { + accept_ok, submit_ok, handle_ok = miner.Server.CoinCtx.HandleMinerSubmit(miner, (ret["id"].(float64)), s.Params[0], s.Params[1], s.Params[2], s.Params[3], s.Params[4]) + } else { + stratum.Handle_exception(miner, (ret["id"].(float64)), stratum.MINER_ERR_ILLEGAL_PARARMS) + } + if handle_ok { + //miner.RecvedLiveAck = true + if (prev_status == coin.MINER_STATUS_AUTHORIZED) && (miner.Status == coin.MINER_STATUS_RUNNING) { + NotifyMinerEnd(miner) + stratum.InitMinerMhs(miner, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.MinerId, miner.Status, miner.Server.DbCtx) + + //RestoreMinerFromCache(miner) + } + if accept_ok { + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "accepts", miner.Accepts) + if submit_ok { + miner.Submits += 1 + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "submits", miner.Submits) + /*miner.Server.PoolSLock.Lock() + miner.Server.Submits += 1 + cache.StorePoolCache(miner.Server.RedisClient, miner.Server.MinerType, "submits", miner.Server.Submits) + miner.Server.PoolSLock.Unlock()*/ + } + if miner.Accepts == 1 { + miner.Retry += 1 + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "retry", miner.Retry) + } + /*miner.Server.PoolSLock.Lock() + miner.Server.Accepts += miner.Difficulty + cache.StorePoolCache(miner.Server.RedisClient, miner.Server.MinerType, "accepts", miner.Server.Accepts) + miner.Server.PoolSLock.Unlock()*/ + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "lastsubmit", miner.LastSubmitime) + + stratum.UpdateMhs(miner, true, miner.Difficulty, 0, miner.Server.DbCtx) + + } else { + + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "staleds", miner.ErrStaleds) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "lowdiffs", miner.ErrLowDiffs) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "duplicates", miner.ErrDuplicates) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "formats", miner.ErrFormats) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "others", miner.ErrOthers) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "rejects", miner.Rejects) + /*miner.Server.PoolSLock.Lock() + miner.Server.Rejects += 1 + cache.StorePoolCache(miner.Server.RedisClient, miner.Server.MinerType, "rejects", miner.Server.Rejects) + miner.Server.PoolSLock.Unlock()*/ + stratum.UpdateMhs(miner, false, miner.Difficulty, 0, miner.Server.DbCtx) + } + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "diff", miner.Difficulty) + //UpdateUserSets(miner, false) + } + } + break + } + } else { + if result, exists := ret["result"]; exists { + switch result.(type) { + //switch ret["result"].(type) { + case string: + result := ret["result"].(string) + if result == "mining.pong" || result == "pong" { + Miner_difficulty_adjust(miner) + //miner.RecvedLiveAck = true + //logg.Info("[server]", zap.String("ack pong result", result), zap.String("user", miner.User), zap.String("miner", miner.Miner), zap.Float64("id", ret["id"].(float64))) + } + break + } + } + } + } else { + //logg.Error("[server]", zap.String("Unmarshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg("failed to mining.submit Unmarshal " + err.Error() + " " + miner.User + "." + miner.Miner) + } + stratum.Handle_exception(miner, 0, stratum.MINER_ERR_ILLEGAL_PARARMS) + } + } else { + //if rdn > 0 { + + //} else { + //time.Sleep(20 * time.Millisecond) + /*if count++; count >= 10 { + break + }*/ + //time.Sleep(time.Duration(1) * time.Second / 50) + runtime.Gosched() + //} + //time.Sleep(time.Duration(1) * time.Second / 2) + + //runtime.Gosched() + + } + } + + miner.TxLock.Lock() + prev_status := miner.Status + miner.Status = coin.MINER_STATUS_DISCONNECTED + miner.TxLock.Unlock() + + //minDuration := 100 * time.Millisecond + //maxDuration := 5 * time.Second + //RandomSleep(minDuration, maxDuration) + + stratum.UpdateMhsStatus(miner, miner.Server.DbCtx) + atomic.AddInt32(&miner.Server.CurrentConns, -1) + IpRelease(miner.Server, miner.FromIP) + miner.Conn.Close() + if miner.Accepts > 0 /*|| (miner.Rejects > 0)*/ { + miner.OfflineTime = miner.LastSubmitime + } + if miner.ZlogInit { + miner.Zlog.Level(zerolog.Disabled) + } + //defer miner.LogR.Close() + if miner.LogR != nil { + defer miner.LogR.Close() + } + //logg.Error("[server]", zap.String("miner disconnect", miner.MinerId)) + if miner.ZlogInit { + miner.Zlog.Info().Msg("miner disconnect prepare " + " " + miner.User + "." + miner.Miner) + } + + stratum.StaleAllJobs(miner) + stratum.SetMhsRelease(miner) + + if prev_status == coin.MINER_STATUS_RUNNING { + + min := 310 + max := 330 + random_to := rand.Intn(max-min+1) + min + + /* + select { + case <-time.After(600 * time.Second): + logg.Error("[server]", zap.String("miner end", miner.MinerId+" "+miner.User+"."+miner.Miner+"_"+fmt.Sprint(miner.MinerIndex))) + case <-miner.EndCh: + logg.Error("[server]", zap.String("miner end chan", miner.MinerId+" "+miner.User+"."+miner.Miner+"_"+fmt.Sprint(miner.MinerIndex))) + }*/ + var to_cnt int = 0 + for { + if atomic.LoadInt32(&(miner.NeedExit)) == 1 { + break + } + if to_cnt >= random_to { + break + } + time.Sleep(time.Duration(1) * time.Second) + to_cnt++ + } + } + + //UpdateUserSets(miner, true) + //miner.Server.Miners.Store(miner.MinerId, nil) + miner.Server.Miners.Delete(miner.MinerId) + + //logg.Error("[server]", zap.String("miner disconnect", miner.MinerId), zap.String("user ", miner.User), zap.String("miner ", miner.Miner), zap.Int("connected num ", num)) + logg.Error("[server]", zap.String("miner disconnected", miner.MinerId), zap.String("user ", miner.User), zap.String("miner ", miner.Miner)) + +} + +func handle_miner_connection_old(miner *coin.MinerObj) { + //var count int = 0 + reader := bufio.NewReader(miner.Conn) + var rxmsg string + for { + /*msg, err := reader.ReadString('\n') + if err != nil { + //if err != io.EOF { + logg.Error("[server]", zap.String("ReadString", err.Error())) + break + //} else { + // continue + //} + }*/ + var msg string + buffer := make([]byte, 1024) + rdn, err := reader.Read(buffer) + if err != nil { + if err != io.EOF || ((err == io.EOF) && (rdn <= 0)) { + //logg.Error("[server]", zap.String("Read", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " Read " + err.Error()) + } + break + } + } + if rdn > 0 { + //count = 0 + //log.Println("rxmsg", string(buffer[:rdn])) + rxmsg += string(buffer[:rdn]) + retch_index := strings.Index(rxmsg, "\n") + if retch_index != -1 { //found + msg = rxmsg[:retch_index+1] + //tempmsg := rxmsg[retch_index+1:] + tempmsg := string([]byte(rxmsg[retch_index+1:])) + rxmsg = tempmsg + } else { //not found, discard + rxmsg = "" + } + } + //log.Println("msg", msg) + if len(msg) > 0 { + miner.RecvedLiveAck = true + msg = strings.TrimSpace(msg) + if (miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING) { + if miner.ZlogInit { + miner.Zlog.Info().Msg(msg) + } + } + var ret map[string]interface{} + err = json.Unmarshal([]byte(msg), &ret) + if err == nil { + //logg.Debug("[server]", zap.Any("msg", msg)) + _, ok := ret["method"].(string) + if ok { + switch ret["method"].(string) { + case "mining.pong": + Miner_difficulty_adjust(miner) + //miner.RecvedLiveAck = true + break + case "mining.subscribe": + miner.Server.CoinCtx.HandleMinerSubscribe(miner, (ret["id"].(float64)), miner.Job.Extranonce1, msg) + break + case "mining.extranonce.subscribe": + stratum.Handle_extranonce(miner, (ret["id"].(float64))) + break + case "mining.authorize": + auth_ok := stratum.Handle_authorize(miner, (ret["id"].(float64)), msg, miner.Server.DbCtx) + if auth_ok { + miner.Server.CoinCtx.SetDifficulty(miner) + miner.Server.CoinCtx.Notify(miner) + } + break + case "mining.submit": + prev_status := miner.Status + var s stratum.Submit_nonce + if err = json.Unmarshal([]byte(msg), &s); err != nil { + //logg.Error("[server]", zap.String("mining.submit Unmarshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg("failed to mining.submit Unmarshal " + err.Error() + " " + miner.User + "." + miner.Miner) + } + } else { + accept_ok := false + submit_ok := false + handle_ok := false + if len(s.Params) == 3 { + accept_ok, submit_ok, handle_ok = miner.Server.CoinCtx.HandleMinerSubmit(miner, (ret["id"].(float64)), s.Params[0], s.Params[1], "", "", s.Params[2]) + } else if len(s.Params) == 5 { + accept_ok, submit_ok, handle_ok = miner.Server.CoinCtx.HandleMinerSubmit(miner, (ret["id"].(float64)), s.Params[0], s.Params[1], s.Params[2], s.Params[3], s.Params[4]) + } else { + stratum.Handle_exception(miner, (ret["id"].(float64)), stratum.MINER_ERR_ILLEGAL_PARARMS) + } + if handle_ok { + //miner.RecvedLiveAck = true + if (prev_status == coin.MINER_STATUS_AUTHORIZED) && (miner.Status == coin.MINER_STATUS_RUNNING) { + NotifyMinerEnd(miner) + stratum.InitMinerMhs(miner, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.MinerId, miner.Status, miner.Server.DbCtx) + + //RestoreMinerFromCache(miner) + } + if accept_ok { + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "accepts", miner.Accepts) + if submit_ok { + miner.Submits += 1 + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "submits", miner.Submits) + /*miner.Server.PoolSLock.Lock() + miner.Server.Submits += 1 + cache.StorePoolCache(miner.Server.RedisClient, miner.Server.MinerType, "submits", miner.Server.Submits) + miner.Server.PoolSLock.Unlock()*/ + } + if miner.Accepts == 1 { + miner.Retry += 1 + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "retry", miner.Retry) + } + /*miner.Server.PoolSLock.Lock() + miner.Server.Accepts += miner.Difficulty + cache.StorePoolCache(miner.Server.RedisClient, miner.Server.MinerType, "accepts", miner.Server.Accepts) + miner.Server.PoolSLock.Unlock()*/ + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "lastsubmit", miner.LastSubmitime) + + stratum.UpdateMhs(miner, true, miner.Difficulty, 0, miner.Server.DbCtx) + + } else { + + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "staleds", miner.ErrStaleds) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "lowdiffs", miner.ErrLowDiffs) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "duplicates", miner.ErrDuplicates) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "formats", miner.ErrFormats) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "others", miner.ErrOthers) + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "rejects", miner.Rejects) + /*miner.Server.PoolSLock.Lock() + miner.Server.Rejects += 1 + cache.StorePoolCache(miner.Server.RedisClient, miner.Server.MinerType, "rejects", miner.Server.Rejects) + miner.Server.PoolSLock.Unlock()*/ + stratum.UpdateMhs(miner, false, miner.Difficulty, 0, miner.Server.DbCtx) + } + //cache.StoreMinerCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "diff", miner.Difficulty) + //UpdateUserSets(miner, false) + } + } + break + } + } else { + switch ret["result"].(type) { + case string: + result := ret["result"].(string) + if result == "mining.pong" || result == "pong" { + Miner_difficulty_adjust(miner) + //miner.RecvedLiveAck = true + //logg.Info("[server]", zap.String("ack pong result", result), zap.String("user", miner.User), zap.String("miner", miner.Miner), zap.Float64("id", ret["id"].(float64))) + } + break + } + } + } else { + //logg.Error("[server]", zap.String("Unmarshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg("failed to mining.submit Unmarshal " + err.Error() + " " + miner.User + "." + miner.Miner) + } + stratum.Handle_exception(miner, 0, stratum.MINER_ERR_ILLEGAL_PARARMS) + } + } else { + if rdn > 0 { + + } else { + //time.Sleep(20 * time.Millisecond) + /*if count++; count >= 10 { + break + }*/ + //time.Sleep(time.Duration(1) * time.Second / 50) + runtime.Gosched() + } + //time.Sleep(time.Duration(1) * time.Second / 2) + + //runtime.Gosched() + + } + } + + miner.TxLock.Lock() + prev_status := miner.Status + miner.Status = coin.MINER_STATUS_DISCONNECTED + miner.TxLock.Unlock() + + //minDuration := 100 * time.Millisecond + //maxDuration := 5 * time.Second + //RandomSleep(minDuration, maxDuration) + + stratum.UpdateMhsStatus(miner, miner.Server.DbCtx) + atomic.AddInt32(&miner.Server.CurrentConns, -1) + IpRelease(miner.Server, miner.FromIP) + miner.Conn.Close() + if miner.Accepts > 0 /*|| (miner.Rejects > 0)*/ { + miner.OfflineTime = miner.LastSubmitime + } + if miner.ZlogInit { + miner.Zlog.Level(zerolog.Disabled) + } + //defer miner.LogR.Close() + if miner.LogR != nil { + defer miner.LogR.Close() + } + //logg.Error("[server]", zap.String("miner disconnect", miner.MinerId)) + if miner.ZlogInit { + miner.Zlog.Info().Msg("miner disconnect prepare " + " " + miner.User + "." + miner.Miner) + } + + if prev_status == coin.MINER_STATUS_RUNNING { + /* + select { + case <-time.After(600 * time.Second): + logg.Error("[server]", zap.String("miner end", miner.MinerId+" "+miner.User+"."+miner.Miner+"_"+fmt.Sprint(miner.MinerIndex))) + case <-miner.EndCh: + logg.Error("[server]", zap.String("miner end chan", miner.MinerId+" "+miner.User+"."+miner.Miner+"_"+fmt.Sprint(miner.MinerIndex))) + }*/ + var to_cnt int = 0 + for { + if atomic.LoadInt32(&(miner.NeedExit)) == 1 { + break + } + if to_cnt > 360 { + break + } + time.Sleep(time.Duration(1) * time.Second) + to_cnt++ + } + } + + //UpdateUserSets(miner, true) + //miner.Server.Miners.Store(miner.MinerId, nil) + miner.Server.Miners.Delete(miner.MinerId) + + //logg.Error("[server]", zap.String("miner disconnect", miner.MinerId), zap.String("user ", miner.User), zap.String("miner ", miner.Miner), zap.Int("connected num ", num)) + logg.Error("[server]", zap.String("miner disconnected", miner.MinerId), zap.String("user ", miner.User), zap.String("miner ", miner.Miner)) + +} + +func Miner_difficulty_adjust(m *coin.MinerObj) { + if m.User == "" || m.Miner == "" { + return + } + now := time.Now() + //if now.Sub(m.LastSubmitime).Seconds() > m.VarDiffOpt.AdjustInterval*5 { + if now.Sub(m.VarDiffOpt.LastSubmitTime).Seconds() > m.VarDiffOpt.AdjustInterval*10 { + if m.Server.Config.Diff.Filter == "kalman" { + share_interval := now.Sub(m.VarDiffOpt.LastSubmitTime).Seconds() + mhs := m.Difficulty * share_interval + diff_next, kalman_p := m.DiffHandler.Handler(m.Difficulty, share_interval) + //diff_next, _ := m.DiffHandler.Handler(m.Difficulty, share_interval) + mhs_est := diff_next * m.Server.Config.Diff.DiffAdjustInterval + + ratio := diff_next / m.Difficulty + if ratio > 0 { + if now.Sub(m.StartSubmitTime).Seconds() > 180 { + if ratio >= 2 { + //m.DifficultyNext = math.Ceil(diff_next*100.0) / 100.0 + m.DifficultyNext = diff_next * 10000000 / 10000000 + } else if ratio <= 0.5 { + //m.DifficultyNext = math.Ceil(diff_next*100.0) / 100.0 + m.DifficultyNext = diff_next * 10000000 / 10000000 + } else { + } + } else { + //m.DifficultyNext = math.Ceil(diff_next*100.0) / 100.0 + m.DifficultyNext = diff_next * 10000000 / 10000000 + /*if ratio >= 1.1 { + m.DifficultyNext = math.Ceil(diff_next*100.0) / 100.0 + } else if ratio <= 0.8 { + m.DifficultyNext = math.Ceil(diff_next*100.0) / 100.0 + } else { + }*/ + } + } + if m.DifficultyNext > 0.0 { + if m.DifficultyNext < m.VarDiffOpt.MinDiff { + m.DifficultyNext = m.VarDiffOpt.MinDiff + } else if m.DifficultyNext > m.VarDiffOpt.MaxDiff { + m.DifficultyNext = m.VarDiffOpt.MaxDiff + } + } + + if m.Server.Config.Diff.Dbg { + coin.New_diff_into_db(m.User, m.Miner, fmt.Sprint(m.MinerIndex), m.Difficulty, diff_next, kalman_p, share_interval, mhs, mhs_est) + } + + //m.VarDiffOpt.LastCalcTime = now + m.VarDiffOpt.LastSubmitTime = now + //log.Println("diff adjust timeout", ratio, diff_next, m.Difficulty, m.DifficultyNext) + } else { + m.VarDiffOpt.Level = coin.Hign + coin.VarAdjustDifficulty(m, coin.DOWN_DIFF) + m.VarDiffOpt.LastCalcTime = now + m.VarDiffOpt.LastSubmitTime = now + } + } +} + +/*func difficulty_adjust(server *coin.ServerContext) { + server.Miners.Range(func(k, v interface{}) bool { + m, ok := v.(*coin.MinerObj) + if ok { + if m.User == "" || m.Miner == "" { + return true + } + now := time.Now() + if now.Sub(m.LastSubmitime).Seconds() > m.VarDiffOpt.AdjustInterval*5 { + if server.Config.Diff.Filter == "kalman" { + share_interval := now.Sub(m.LastSubmitime).Seconds() + //mhs := m.Difficulty * share_interval + //diff_next, kalman_p := m.DiffHandler.Handler(m.Difficulty, share_interval) + diff_next, _ := m.DiffHandler.Handler(m.Difficulty, share_interval) + //mhs_est := diff_next * share_interval + + ratio := diff_next / m.Difficulty + if ratio >= 2.0 { + m.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else if ratio <= 0.5 { + m.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else { + } + //new_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, miner.DifficultyNext, kalman_p, share_interval, mhs, mhs_est) + m.LastSubmitime = now + } else { + m.VarDiffOpt.Level = coin.Hign + coin.VarAdjustDifficulty(m, coin.DOWN_DIFF) + m.LastSubmitime = now + } + } + } + return true + }) +}*/ + +/*func Handle_difficulty_adjust_timer(server *coin.ServerContext) { + timer := time.NewTimer(time.Second * coin.MINER_DIFFICULTY_ADJUST_DURATION) + for { + select { + case <-timer.C: + difficulty_adjust(server) + timer.Reset(time.Second * coin.MINER_DIFFICULTY_ADJUST_DURATION) + case <-(server.ExitDiffVar): + timer.Stop() + server.ExitDiffVar <- true + return + } + } +}*/ + +func IpAllow(server *coin.ServerContext, ip string) bool { + server.IpMutex.Lock() + defer server.IpMutex.Unlock() + const maxPerIP = 3000 + if server.IpCounts[ip] >= maxPerIP { + return false + } + server.IpCounts[ip]++ + return true +} + +func IpRelease(server *coin.ServerContext, ip string) { + server.IpMutex.Lock() + defer server.IpMutex.Unlock() + _, exists := server.IpCounts[ip] + if exists { + server.IpCounts[ip]-- + if server.IpCounts[ip] == 0 { + delete(server.IpCounts, ip) + } + } +} + +func isTooManyOpenFiles(err error) bool { + return errors.Is(err, syscall.EMFILE) || errors.Is(err, syscall.ENFILE) +} + +func StartServer(server *coin.ServerContext) { + zerolog.TimeFieldFormat = zerolog.TimeFormatUnix + + select { + case issync := <-server.SyncJobChan: + if !issync { + return + } + server.Synced = true + log.Println("StartServer receive job! start") + case <-time.After(time.Duration(60) * time.Second): + log.Println("StartServer not receive job! exited") + if logg != nil { + logg.Error("[server]", zap.String("StartServer not receive job", "exited")) + } + } + + var miners sync.Map + server.Miners = miners + var mmhs sync.Map + server.MMhs = mmhs + + var cacheusers sync.Map + server.CacheUsers = cacheusers + atomic.StoreInt32(&(ServerCtx.CacheUsersCnt), 0) + + /*var update_map sync.Map + server.UpdateMap = update_map*/ + + listener, err := net.Listen("tcp", server.Config.Host.Listen) + server.Listener = listener + if err != nil { + logg.Fatal("[server]", zap.String("Listen", err.Error())) + return + } + + go HandleKeepAlive(server) + //go Handle_difficulty_adjust_timer(server) + + go dbif.Handle_miners_timer(server, server.DbCtx) + //go dbif.Handle_miners_stats_timer(server, server.DbCtx) + //go dbif.Handle_users_timer(server, server.DbCtx) + //go dbif.Handle_users_stats_timer(server, server.DbCtx) + + server.CurrentConns = 0 + const maxConns = 5000 + + server.IpCounts = make(map[string]int) + var ip_mutex sync.Mutex + server.IpMutex = ip_mutex + + for { + conn, err := listener.Accept() + if err != nil { + if server.ExitFlag { + break + } + logg.Error("[server]", zap.String("Accept", err.Error())) + if isTooManyOpenFiles(err) { + break + } + continue + } + + if atomic.LoadInt32(&server.CurrentConns) >= maxConns { + conn.Close() + log.Printf("too many connections %d: %s", server.CurrentConns, conn.RemoteAddr()) + continue + } + + clientIP := conn.RemoteAddr().String() + + if !IpAllow(server, clientIP) { + conn.Close() + log.Printf("ip too many connections :%s", conn.RemoteAddr()) + continue + } + + atomic.AddInt32(&server.CurrentConns, 1) + + var miner coin.MinerObj + init_miner(&miner, conn, server) + + server.Miners.LoadOrStore(miner.MinerId, &miner) + go handle_miner_connection(&miner) + } + +} + +func HandleJob(server *coin.ServerContext) { + for { + if server.ExitFlag { + break + } + if server.SubCh == nil { + server.SubCh = utility.InitZmqSub(ServerCtx.Config.Zmq.Sub, "job"+server.MinerType) + } + if server.SubCh != nil { + cmsg_sub, err := server.SubCh.RecvMessage() + if err != nil { + time.Sleep(time.Duration(1) * time.Second) + server.SubCh.SetSubscribe("job" + server.MinerType) + server.SubCh.Connect(ServerCtx.Config.Zmq.Sub) + //server.SubCh.Destroy() + //server.SubCh = utility.InitZmqSub(ServerCtx.Config.Zmq.Sub, "job"+server.MinerType) + logg.Error("[server]", zap.String("HandleJob", err.Error())) + continue + } + if cmsg_sub != nil { + if len(cmsg_sub) >= 2 { + cmp_topic := "job" + server.CoinCtx.Coin + // log.Println("job 1", string(cmsg_sub[0]), cmp_topic) + if string(cmsg_sub[0]) == cmp_topic { + //logg.Error("[server]", zap.String("job 1", string(cmsg_sub[0])+","+cmp_topic)) + //server.AlivingChan <- true + atomic.StoreInt32(&(server.FlagAliving), 1) + + cmsg := cmsg_sub[1] + //logg.Error("[server]", zap.String("job 2", string(cmsg_sub[0])+","+cmp_topic)) + // log.Println("job 2", string(cmsg_sub[0]), string(cmsg_sub[0])+","+cmp_topic) + server.CoinCtx.HandleJobMsg(server, cmsg) + if !server.Synced { + server.SyncJobChan <- true + } + logg.Error("[server]", zap.String("job 3", string(cmsg_sub[0])+","+cmp_topic)) + } + } + } + } else { + logg.Error("[server]", zap.String("HandleJob", "SubCh fail!")) + time.Sleep(time.Duration(1) * time.Second) + } + } + +} + +/*func LoadCache(server *coin.ServerContext) { +val := cache.LoadPoolCache(server.RedisClient, server.MinerType, "submits") +if val != nil { + if intVal, ok := val.(int64); ok { + server.Submits = intVal + } +} + +val = cache.LoadPoolCache(server.RedisClient, server.MinerType, "blocks") +if val != nil { + if intVal, ok := val.(int64); ok { + server.Blocks = intVal + } +} + +val = cache.LoadPoolCache(server.RedisClient, server.MinerType, "rejects") +if val != nil { + if intVal, ok := val.(int64); ok { + server.Rejects = float64(intVal) + } +} + +val_f := cache.LoadPoolCache(server.RedisClient, server.MinerType, "accepts") +if val_f != nil { + if fVal, ok := val_f.(float64); ok { + server.Accepts = fVal + } +}*/ + +/*val_f = cache.LoadPoolCache(server.RedisClient, server.MinerType, "reward") +if val_f != nil { + if fVal, ok := val_f.(float64); ok { + server.Reward = fVal + } +} + +val_f = cache.LoadPoolCache(server.RedisClient, server.MinerType, "fee") +if val_f != nil { + if fVal, ok := val_f.(float64); ok { + server.Fee = fVal + } +}*/ + +/*val_f = cache.LoadPoolCache(server.RedisClient, server.MinerType, "refdiff") + if val_f != nil { + if fVal, ok := val_f.(float64); ok { + if fVal > 0 { + server.RefDifficulty = fVal + } + } + } + +}*/ + +func Start(Coin string, DbCtx *db.DbContext) { + rand.Seed(time.Now().UnixNano()) + ServerCtx.MinerType = Coin + + atomic.StoreInt32(&(ServerCtx.FlagAliving), 0) + atomic.StoreInt32(&(ServerCtx.FlagAlivingExit), 0) + //atomic.StoreInt32(&(ServerCtx.NotifyBlkDetailIdx), 0) + + ServerCtx.MinerIndex = 0 + + ServerCtx.Accepts5M = 0 + ServerCtx.Accepts15M = 0 + ServerCtx.Accepts30M = 0 + ServerCtx.Accepts1h = 0 + ServerCtx.Accepts3h = 0 + ServerCtx.Accepts6h = 0 + ServerCtx.Accepts12h = 0 + ServerCtx.Accepts24h = 0 + ServerCtx.Accepts48h = 0 + + ServerCtx.Rejects5M = 0 + ServerCtx.Rejects15M = 0 + ServerCtx.Rejects30M = 0 + ServerCtx.Rejects1h = 0 + ServerCtx.Rejects3h = 0 + ServerCtx.Rejects6h = 0 + ServerCtx.Rejects12h = 0 + ServerCtx.Rejects24h = 0 + ServerCtx.Rejects48h = 0 + + ServerCtx.Mhs5M = 0 + ServerCtx.Mhs15M = 0 + ServerCtx.Mhs30M = 0 + ServerCtx.Mhs1h = 0 + ServerCtx.Mhs3h = 0 + ServerCtx.Mhs6h = 0 + ServerCtx.Mhs12h = 0 + ServerCtx.Mhs24h = 0 + ServerCtx.Mhs48h = 0 + + ServerCtx.Normal = 0 + ServerCtx.Abnormal = 0 + ServerCtx.Offline = 0 + ServerCtx.MhsZero = 0 + ServerCtx.MhsLow = 0 + ServerCtx.HighRejects = 0 + ServerCtx.Unstable = 0 + + ServerCtx.NetTarget = "" + ServerCtx.NetHight = 0 + + ServerCtx.Submits = 0 + ServerCtx.Blocks = 0 + ServerCtx.Orphans = 0 + + ServerCtx.Reward = 0 + ServerCtx.Fee = 0 + + ServerCtx.Synced = false + + ServerCtx.ExitFlag = false + ServerCtx.ExitDiffVar = make(chan bool, 256) + ServerCtx.SyncJobChan = make(chan bool, 256) + ServerCtx.ExitDbMiners = make(chan bool, 256) + ServerCtx.ExitDbMinersStats = make(chan bool, 256) + + ServerCtx.ExitDbUser = make(chan bool, 256) + ServerCtx.ExitDbUserStats = make(chan bool, 256) + + ServerCtx.ExitDbPoolStats = make(chan bool, 256) + + /*var users_slock sync.Mutex + ServerCtx.UsersSLock = users_slock*/ + + /*var pool_slock sync.Mutex + ServerCtx.PoolSLock = pool_slock*/ + + ServerCtx.DbCtx = DbCtx + ServerCtx.Config = InitConfig() + + ServerCtx.RefDifficulty = 1 //ServerCtx.Config.Diff.StartDifficulty + + l, r, _ := utility.InitLogg(&(ServerCtx.Config.Zaplog), &(ServerCtx.Config.Logrotae), Coin, "server") + logg = l + logr = r + ServerCtx.Logg = l + ServerCtx.LogR = logr + + opts := &redis.Options{ + Addr: ServerCtx.Config.Redis.Addr, + Password: ServerCtx.Config.Redis.Password, + DB: ServerCtx.Config.Redis.DB, + } + + ServerCtx.RedisClient = redis.NewClient(opts) + + err := ServerCtx.RedisClient.Set(context.Background(), "server", Coin, 0).Err() + if err != nil { + fmt.Println(err) + return + } + + register_signal(DbCtx) + register_user_signal(&ServerCtx) + + dbif.Create_db_tables(ServerCtx.DbCtx, ServerCtx.MinerType) + + ServerCtx.PubCh = utility.InitZmqPub(ServerCtx.Config.Zmq.Pub) + + ServerCtx.SubCh = utility.InitZmqSub(ServerCtx.Config.Zmq.Sub, "job"+Coin) + + //ServerCtx.AlivingChan = make(chan bool, 32768) + //ServerCtx.LiveingExpired = false + ServerCtx.ExitPingChan = make(chan bool, 32768) + ServerCtx.ExitJobChan = make(chan bool, 32768) + + ServerCtx.Started = true + for _, coinobj := range coinobjs { + if coinobj.Coin == Coin { + ServerCtx.CoinCtx = coinobj + break + } + } + // ServerCtx.CoinCtx = coin.CoinObj{} + + ServerCtx.CoinCtx.Init(&ServerCtx) + + //LoadCache(&ServerCtx) + + ServerCtx.CoinCtx.Start() + + go StartServer(&ServerCtx) + go HandleJob(&ServerCtx) + + go ServerLivingHandler(&ServerCtx) + + <-DbCtx.AppExit + + log.Println("received exit signal") +} + +func Stop() { + log.Println("enter Stop") + + ServerCtx.ExitFlag = true + time.Sleep(time.Second) + + //if !ServerCtx.LiveingExpired { + //ServerCtx.AlivingChan <- false + //} + atomic.StoreInt32(&(ServerCtx.FlagAlivingExit), 1) + + ServerCtx.ExitPingChan <- true + + ServerCtx.ExitDbMiners <- true + ServerCtx.ExitDbMinersStats <- true + + ServerCtx.ExitDbUser <- true + ServerCtx.ExitDbUserStats <- true + + ServerCtx.ExitDiffVar <- true + + ServerCtx.CoinCtx.Stop() + + time.Sleep(time.Second) + + if ServerCtx.Started == true { + var keys []interface{} + ServerCtx.MMhs.Range(func(k, v interface{}) bool { + m, ok := v.(*coin.MhsObj) + //_, ok := v.(*coin.MhsObj) + if ok { + m.Accepts = nil + m.Rejects = nil + } + keys = append(keys, k) + return true + }) + for _, key := range keys { + //ServerCtx.MMhs.Store(key, nil) + ServerCtx.MMhs.Delete(key) + } + + var keysUsers []interface{} + ServerCtx.CacheUsers.Range(func(k, v interface{}) bool { + keysUsers = append(keysUsers, k) + return true + }) + for _, key := range keysUsers { + //ServerCtx.CacheUsers.Store(key, nil) + ServerCtx.CacheUsers.Delete(key) + } + + var keysToDelete []interface{} + ServerCtx.Miners.Range(func(k, v interface{}) bool { + m, ok := v.(*coin.MinerObj) + if ok { + atomic.AddInt32(&ServerCtx.CurrentConns, -1) + IpRelease(&ServerCtx, m.FromIP) + m.Conn.Close() + //m.JobList.Init() + for elem := m.JobList.Front(); elem != nil; { + next := elem.Next() + m.JobList.Remove(elem) + elem.Value = nil + elem = next + } + var keysJobs []interface{} + m.Jobs.Range(func(k, v interface{}) bool { + keysJobs = append(keysJobs, k) + return true + }) + for _, key := range keysJobs { + //m.Jobs.Store(key, nil) + m.Jobs.Delete(key) + } + keysToDelete = append(keysToDelete, k) + } + return true + }) + for _, key := range keysToDelete { + //ServerCtx.Miners.Store(key, nil) + ServerCtx.Miners.Delete(key) + } + time.Sleep(time.Second) + } + ServerCtx.Started = false + + defer close(ServerCtx.SyncJobChan) + //defer close(ServerCtx.AlivingChan) + defer close(ServerCtx.ExitPingChan) + defer close(ServerCtx.ExitJobChan) + if ServerCtx.Listener != nil { + defer ServerCtx.Listener.Close() + } + if ServerCtx.PubCh != nil { + defer ServerCtx.PubCh.Destroy() + + } + if ServerCtx.SubCh != nil { + defer ServerCtx.SubCh.Destroy() + } + + defer ServerCtx.RedisClient.Close() + defer logg.Sync() + defer logr.Close() + + log.Println("Stopped") +} diff --git a/internal/server/sha3x/hash_sha3x.go b/internal/server/sha3x/hash_sha3x.go new file mode 100644 index 0000000..a2da950 --- /dev/null +++ b/internal/server/sha3x/hash_sha3x.go @@ -0,0 +1,39 @@ +// hash_sha3x.go +package sha3x + +/* +#cgo CFLAGS : -I../include +#cgo LDFLAGS: -L../lib -lsha3x + +#include +#include +#include "sha3xapi.h" +*/ +import "C" +import ( + //"encoding/hex" + //"log" + "unsafe" +) + +func BuildPowHash(h Sha3xBlockHeader) []byte { + outputs := make([]byte, 32) + inb := Sha3xBlockHeaderToBytes(h) + //log.Println("[sha3x]in", hex.EncodeToString(inb)) + in := (*C.uchar)(C.CBytes(inb)) + output := (*C.uchar)(C.malloc(32)) + C.sha3x_hash(output, in) + p := uintptr(unsafe.Pointer(output)) + for i := 0; i < 32; i++ { + j := *(*byte)(unsafe.Pointer(p)) + outputs[i] = j + p += unsafe.Sizeof(j) + } + C.free(unsafe.Pointer(output)) + C.free(unsafe.Pointer(in)) + outputs32 := make([]byte, 32) + for i := 0; i < 32; i++ { + outputs32[i] = outputs[i] + } + return outputs32 +} diff --git a/internal/server/sha3x/sha3x.go b/internal/server/sha3x/sha3x.go new file mode 100644 index 0000000..53313fd --- /dev/null +++ b/internal/server/sha3x/sha3x.go @@ -0,0 +1,761 @@ +// sha3x.go +package sha3x + +import ( + "strconv" + //"database/sql" + "encoding/binary" + "encoding/hex" + "encoding/json" + + //"log" + //"math" + "math/big" + //"strings" + + "fmt" + "pool/internal/msg" + "pool/internal/server/coin" + "pool/internal/server/dbif" + "pool/internal/stratum" + "pool/internal/utility" + "time" + + _ "github.com/mattn/go-sqlite3" + + "go.uber.org/zap" +) + +const SERVER_SHA3X_VERSION string = "sha3x v0.1a" + +type Sha3xBlockHeader struct { + Nonce [8]byte + Header [32]byte + Algo byte +} + +func Sha3xBlockHeaderToBytes(h Sha3xBlockHeader) []byte { + out := make([]byte, 8+32+1) + for i := 0; i < 8; i++ { + out[i] = h.Nonce[i] + } + for i := 0; i < 32; i++ { + out[8+i] = h.Header[i] + } + out[8+32] = h.Algo + + return out +} + +type ServerSha3xContext struct { + ServerCtx *coin.ServerContext + logg *zap.Logger + + Sha3xJob msg.Sha3xStratumJob +} + +var logg *zap.Logger +var ServerSha3xCtx ServerSha3xContext + +type Sha3xNotify_params_msg struct { + Algo string `json:"algo"` + Blob string `json:"blob"` + Height uint32 `json:"height"` + Job_id string `json:"job_id"` + Target string `json:"target"` +} + +type Sha3xNotify_msg struct { + Jsonrpc string `json:"jsonrpc"` + Method string `json:"method"` + Params Sha3xNotify_params_msg `json:"params"` +} + +func handle_submit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + var submit_item coin.BlockMsg + /*var user_blk_item coin.UserBlockMsg*/ + var pool_blk_item coin.PoolBlkMsg + + var blk_detail_height int64 + var blk_detail_hash string + var blk_detail_success bool + var blk_detail_miner_diff float64 + var blk_detail_pool_diff float64 + + if miner.Authorized != true { + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNAUTH_WORKER) + stratum.Send_reconnect_msg(miner) + return false, false, false + } + var new_found bool = false + var ack stratum.Submit_ack + ack.ID = id + ack.Result = true + //logg.Warn("[server]", zap.String("user", miner.User), zap.String("miner", miner.Miner)) + //logg.Debug("[server]", zap.Float64("id", id), zap.String("job_id", job_id)) + //logg.Debug("[server]", zap.String("nonce2", nonce2), zap.String("ntime", ntime), zap.String("nonce", nonce)) + //stratum.UpdateJobs(miner) + v, ok := miner.Jobs.Load(job_id) + if ok { + job := v.(msg.Sha3xStratumJob) + + if job.Height < miner.CurHeight-1 { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_STALED_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + //logg.Debug("[server]", zap.Uint64("ntime", nt), zap.Uint64("mintime", uint64(job.Mintime)), zap.Uint64("jobtime", jt_reverse)) + /*if nt < uint64(job.Mintime) { + ack.Result = false + util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_OLD) + } else if nt > jt_reverse+uint64(600) { + ack.Result = false + util.Handle_exception(miner, id, util.MINER_ERR_TIME_TOO_NEW) + } else */{ + if (miner.LastNonce != nonce) || (miner.LastHeader != job.Header) { + miner.LastHeader = job.Header + miner.LastNonce = nonce + job.Nonce = nonce + job.Extranonce2 = nonce2 + //logg.Debug("[server]", zap.Uint32("height", job.Height), zap.String("target", job.Target)) + if miner.ZlogInit { + miner.Zlog.Info().Msg("height " + string(job.Height) + " target " + job.Target + " " + miner.User + "." + miner.Miner) + } + + phb, _ := hex.DecodeString(job.Header) + + nb, _ := hex.DecodeString(nonce) + + var calc_hash []byte + + var header Sha3xBlockHeader + for i := 0; i < 8; i++ { + header.Nonce[i] = nb[i] + } + for i := 0; i < 32; i++ { + header.Header[i] = phb[i] + } + header.Algo = 1 + submit_item.Header = hex.EncodeToString(Sha3xBlockHeaderToBytes(header)) + calc_hash = BuildPowHash(header) + + //logg.Debug("[server]", zap.String("hash in", submit_item.Header)) + //calc_hash, header := util.BuildBlockHash(&(job), true, Build_PowHash) + //logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/) + if miner.ZlogInit { + miner.Zlog.Info().Msg("hash in " + submit_item.Header + " calc_hash " + hex.EncodeToString(calc_hash) + " " + miner.User + "." + miner.Miner) + } + submit_target := new(big.Int) + //submit_target.SetBytes(common.Reverse(calc_hash)) + + //hashs, _ := utility.ReverseS(hex.EncodeToString(calc_hash)) + + //hashb, _ := hex.DecodeString(hashs) + //submit_target.SetBytes(hashb) + submit_target.SetBytes(calc_hash) + /*logg.Debug("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.Target.Bytes()))) + if submit_target.Cmp(miner.Target) > 0 {*/ + calc_diff := utility.Target2Diff(utility.Reverse(calc_hash)) + //calc_diff := utility.Target2Diff(calc_hash) + //log.Printf("diff,calc_diff:%f difficulty:%f ", calc_diff, miner.Difficulty) + //logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff)) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " target diff " + fmt.Sprintf("%f", (miner.Difficulty)) + " submit diff " + fmt.Sprintf("%f", (calc_diff))) + } + //logg.Debug("[server]", zap.String("target", miner.Target.String()), zap.Any("bytes", miner.Target.Bytes())) + //logg.Info("[server]", zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff), zap.String("target", hex.EncodeToString(miner.Target.Bytes()))) + + //if calc_diff < miner.Difficulty { + if calc_diff < job.JobDifficulty { + //gpu protocol handler + /*for i := 0; i < 8; i++ { + temp_nonce := header.Nonce[8+i] + header.Nonce[8+i] = header.Nonce[i] + header.Nonce[i] = temp_nonce + } + submit_item.Header = hex.EncodeToString(Sha3xBlockHeaderToBytes(header)) + calc_hash = BuildPowHash(header) + logg.Debug("[server]", zap.String("hash in", hex.EncodeToString(Sha3xBlockHeaderToBytes(header))))*/ + //logg.Debug("[server]", zap.String("calc_hash", hex.EncodeToString(calc_hash)) /*, zap.String("merkle root", hex.EncodeToString(merkle_root))*/) + //submit_target = new(big.Int) + /*submit_target.SetBytes(calc_hash) + calc_diff = utility.Target2Diff(calc_hash) + logg.Warn("[server]", zap.String("user", miner.User+"."+miner.Miner), zap.Float64("target diff", miner.Difficulty), zap.Float64("submit diff", calc_diff)) + if calc_diff < miner.Difficulty { + */ + ack.Result = false + miner.ErrLowDiffs = miner.ErrLowDiffs + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_LOW_DIF_SHARE) + return false, false, false + //} + + } + //logg.Warn("[server]", zap.String("pow", hex.EncodeToString(submit_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes()))) + //submit_target.Text(16) + /*if submit_target.Cmp(miner.ServerTarget) <= 0 {*/ + //log.Println("[server]server_target", miner.ServerTargetS) + //stb, _ := hex.DecodeString(miner.ServerTargetS) + stb, _ := hex.DecodeString(job.Target) + //logg.Info("[server]", zap.String("target", job.Target)) + //server_diff := Target2Diff(common.Reverse(stb)) + server_diff := utility.Target2Diff(utility.Reverse(stb)) + //log.Printf("[server]server_diff %f", server_diff) + //logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff)) + //logg.Debug("[server]", zap.String("ServerTargetS", miner.ServerTargetS)) + network_target := new(big.Int) + network_target.SetBytes(stb) + //logg.Info("[server]", zap.Float64("calc_diff", calc_diff), zap.Float64("miner.Difficulty", miner.Difficulty), zap.Float64("server_diff", server_diff)) + //logg.Debug("[server]", zap.String("submit_target", hex.EncodeToString(submit_target.Bytes())), zap.String("network_target", hex.EncodeToString(network_target.Bytes())), zap.String("target", hex.EncodeToString(miner.ServerTarget.Bytes())), zap.Int("cmp", network_target.Cmp(submit_target))) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " calc_diff " + fmt.Sprintf("%f", (calc_diff)) + " miner.Difficulty " + fmt.Sprintf("%f", (miner.Difficulty)) + " server_diff " + fmt.Sprintf("%f", (server_diff))) + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " submit_target " + hex.EncodeToString(submit_target.Bytes()) + " network_target " + hex.EncodeToString(network_target.Bytes()) + " target " + hex.EncodeToString(miner.ServerTarget.Bytes()) + " cmp " + fmt.Sprintf("%d", (network_target.Cmp(submit_target)))) + } + + submit_item.Hash = hex.EncodeToString(calc_hash) + submit_item.Target = hex.EncodeToString(miner.Target.Bytes()) + submit_item.Submit_target = hex.EncodeToString(calc_hash) + submit_item.Height = int64(job.Height) + submit_item.Pow = hex.EncodeToString(calc_hash) + submit_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + /*user_blk_item.Height = int64(job.Height) + user_blk_item.Hash = hex.EncodeToString(calc_hash) + user_blk_item.Pow = hex.EncodeToString(calc_hash) + user_blk_item.Net_target = hex.EncodeToString(network_target.Bytes())*/ + + pool_blk_item.Height = int64(job.Height) + pool_blk_item.Hash = hex.EncodeToString(calc_hash) + pool_blk_item.Pow = hex.EncodeToString(calc_hash) + pool_blk_item.Net_target = hex.EncodeToString(network_target.Bytes()) + + blk_detail_height = int64(job.Height) + blk_detail_hash = hex.EncodeToString(calc_hash) + blk_detail_success = false + //blk_detail_miner_diff = miner.Difficulty + blk_detail_miner_diff = job.JobDifficulty + blk_detail_pool_diff = miner.Server.RefDifficulty + + if ack.Result == true { + /*if miner.CurHeight != 0 && miner.CurHeight == job.Height { + return + }*/ + + //if true { + if (calc_diff >= server_diff) || (network_target.Cmp(submit_target) >= 0) { + //if true { + miner.Server.SubIdx++ + Produce_block_submit(miner /*header,*/, &job, submit_item.Hash, miner.Server.SubIdx) + miner.SubmitIndex++ + miner.Submits = miner.Submits + 1 + //miner.CurHeight = job.Height + new_found = true + } + if new_found && float64(miner.Server.Sha3xJob.U64target) <= calc_diff { + pool_blk_item.Submit = "y" + pool_blk_item.Success = false + pool_blk_item.Accepts = miner.Accepts + pool_blk_item.Rejects = miner.Rejects + pool_blk_item.Reward = 0 + pool_blk_item.Fee = 0 + pool_blk_item.Nonce = nonce + pool_blk_item.SubIdx = miner.Server.SubIdx + dbif.NotifyPoolBlkStatsDb2(miner.Server, &pool_blk_item) + } + } + } else { + miner.LastHeader = job.Header + miner.LastNonce = nonce + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_DUP_SHARE) + miner.ErrDuplicates = miner.ErrDuplicates + 1 + return false, false, false + } + } + } else { + ack.Result = false + stratum.Handle_exception(miner, id, stratum.MINER_ERR_NOT_FOUND_JOB) + miner.ErrStaleds = miner.ErrStaleds + 1 + return false, false, false + } + + miner.LastJobId = job_id + + ack.Error = nil + body, err := json.Marshal(ack) + if err != nil { + //logg.Error("[server]", zap.String("Marshal", err.Error())) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit Marshal " + err.Error()) + } + miner.ErrOthers = miner.ErrOthers + 1 + stratum.Handle_exception(miner, id, stratum.MINER_ERR_UNKNOWN) + return false, false, false + } + + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //miner.Server.Miners.Delete(miner.MinerId) + } + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } + //logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Lock() + miner.Status = coin.MINER_STATUS_RUNNING + miner.TxLock.Unlock() + + if ack.Result { + + miner.Accepts += miner.Difficulty + miner.M5Accepts += miner.Difficulty + + miner.VarDiffOpt.SubmitShares += miner.Difficulty + + } else { + miner.Rejects += miner.Difficulty + + } + now := time.Now() + if miner.Server.Config.Diff.Filter == "kalman" { + if ack.Result { + share_interval := now.Sub(miner.LastSubmitime).Seconds() + mhs := miner.Difficulty * share_interval + diff_next, kalman_p := miner.DiffHandler.Handler(miner.Difficulty, share_interval) + mhs_est := diff_next * miner.Server.Config.Diff.DiffAdjustInterval + + ratio := diff_next / miner.Difficulty + if ratio > 0 { + if now.Sub(miner.StartSubmitTime).Seconds() > 180 { + if ratio >= 2 { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else if ratio <= 0.5 { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + } else { + } + } else { + //miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + miner.DifficultyNext = diff_next * 10000000 / 10000000 + /*if ratio >= 1.1 { + miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else if ratio <= 0.8 { + miner.DifficultyNext = math.Ceil(diff_next*100) / 100 + } else { + }*/ + } + } + if miner.DifficultyNext > 0.0 { + if miner.DifficultyNext < miner.VarDiffOpt.MinDiff { + miner.DifficultyNext = miner.VarDiffOpt.MinDiff + } else if miner.DifficultyNext > miner.VarDiffOpt.MaxDiff { + miner.DifficultyNext = miner.VarDiffOpt.MaxDiff + } + } + //miner.VarDiffOpt.LastCalcTime = now + + if miner.Server.Config.Diff.Dbg { + coin.New_diff_into_db(miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), miner.Difficulty, diff_next, kalman_p, share_interval, mhs, mhs_est) + } + + //log.Println("diff adjust", ratio, diff_next, miner.Difficulty, miner.DifficultyNext) + } + } else { + // submit time < DiffAdjustInterval,then up adjust diff + if now.Sub(miner.LastSubmitime).Seconds() < miner.Server.Config.Diff.DiffAdjustInterval { + if ack.Result { + if miner.VarDiffOpt.Uptimes++; miner.VarDiffOpt.Uptimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.UP_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Uptimes = 0 + } + + // submit time > 2 * DiffAdjustInterval,then down adjust diff + if now.Sub(miner.LastSubmitime).Seconds() > miner.Server.Config.Diff.DiffAdjustInterval*2 { + if ack.Result { + if miner.VarDiffOpt.Downtimes++; miner.VarDiffOpt.Downtimes >= coin.DIFFICULTY_WAIT_TIMES { + coin.VarAdjustDifficulty(miner, coin.DOWN_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + } else { + miner.VarDiffOpt.Downtimes = 0 + } + } + if ack.Result { + miner.LastSubmitime = now + miner.VarDiffOpt.LastSubmitTime = now + } + var duration float64 = float64(now.Sub(miner.StartSubmitTime)) / 1000000000 + + if duration < 1 { + duration = 1 + } + //diffOneShareHashesAvg := uint64(0x00000000FFFFFFFF) + diffOneShareHashesAvg := uint64(0xFFFFFFFFFFFFFFFF) + miner.AverageHashrate = miner.Accepts * float64(diffOneShareHashesAvg) / duration / 1000000 + var m5_duration float64 = float64(now.Sub(miner.M5SubmitTime)) / 1000000000 + if m5_duration >= float64(time.Minute*5)/1000000000 { + miner.M5SubmitTime = now + miner.M5Hashrate = miner.M5Accepts * float64(diffOneShareHashesAvg) / m5_duration / 1000000 + //logg.Info("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate)) + miner.M5Accepts = 0 + } + + //logg.Warn("[server]", zap.Float64("Accepts", miner.Accepts), zap.Float64("Rejects", miner.Rejects)) + //logg.Info("[server]", zap.Float64("TargetShares", miner.VarDiffOpt.TargetShares), zap.Float64("MinShares", miner.VarDiffOpt.MinShares), zap.Float64("MaxShares", miner.VarDiffOpt.MaxShares), zap.Float64("SubmitShares", miner.VarDiffOpt.SubmitShares)) + //logg.Warn("[server]", zap.Float64("reject rate", miner.Rejects/(miner.Accepts+miner.Rejects)), zap.Float64("Hashrate(MH/S)", miner.AverageHashrate)) + //logg.Warn("[server]", zap.Float64("M5Accepts", miner.M5Accepts), zap.Float64("M5Hashrate(MH/S)", miner.M5Hashrate)) + if miner.ZlogInit { + miner.Zlog.Info().Msg(miner.User + "." + miner.Miner + " handle_submit M5Accepts " + fmt.Sprintf("%f", (miner.M5Accepts)) + " M5Hashrate(MH/S) " + fmt.Sprintf("%f", (miner.M5Hashrate))) + } + + //logg.Info("[server]", zap.Float64("LastCalcTime", float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000)) + //calc acutal submit shares period of time, then compare with target shares and adjust diff + + if miner.Server.Config.Diff.Filter == "kalman" { + } else { + if float64(now.Sub(miner.VarDiffOpt.LastCalcTime))/1000000000 >= miner.VarDiffOpt.AdjustTime { + coin.VarAdjustDifficulty(miner, coin.UPDATE_DIFF) + miner.VarDiffOpt.LastCalcTime = now + } + } + + if ack.Result { + + submit_item.Success = false + if new_found { + submit_item.Submit = "y" + submit_item.SubIdx = miner.Server.SubIdx + } else { + submit_item.Submit = "n" + submit_item.SubIdx = -1 + } + + submit_item.Accepts = miner.Accepts + submit_item.Total_accepts = miner.Accepts + submit_item.Rejects = miner.Rejects + submit_item.Total_rejects = miner.Rejects + submit_item.Reward = 0 + submit_item.Fee = 0 + submit_item.Nonce = nonce + + //dbif.NotifyMinerDb2(miner, &submit_item) + + dbif.NotifyBlkDetailDb(miner, blk_detail_height, blk_detail_hash, blk_detail_success, blk_detail_miner_diff, blk_detail_pool_diff, nonce, submit_item.SubIdx) + return true, new_found, true + } + return false, false, true +} + +func Produce_block_submit(miner *coin.MinerObj /*header Sha3xBlockHeader,*/, job *msg.Sha3xStratumJob, PowHash string, SubIdx int64) { + var nm msg.BlockSha3xMsg + nm.Id = job.Id + nm.Header = job.Header + //nm.Nonce = job.Nonce + noncer, _ := stratum.ReverseHexStringByByte(job.Nonce) + nonce, err := strconv.ParseUint(noncer, 16, 64) + nm.Nonce = nonce + nm.Pow = PowHash + nm.SubIdx = SubIdx + nm.User = miner.User + nm.Miner = miner.Miner + nm.Index = fmt.Sprint(miner.MinerIndex) + body, err := json.Marshal(nm) + if err != nil { + logg.Error("[server]", zap.String("failed to Marshal job", err.Error())) + return + } + blk := string(body) + + //Add Height + /*heightb := utility.Uint32ToByte(job.Height) + heights := hex.EncodeToString(heightb) + blk += heights + var Height uint32 = utility.ByteToUint32(heightb)*/ + nm.Height = (uint64)(job.Height) + logg.Warn("[server]", zap.Uint32("Height", job.Height)) + + //Add SubmitIndex + /*indexb := utility.Uint32ToByte(miner.SubmitIndex) + indexs := hex.EncodeToString(indexb) + blk += indexs + var SubmitIndex uint32 = utility.ByteToUint32(indexb)*/ + nm.SubmitIdx = (uint64)(miner.SubmitIndex) + logg.Info("[server]", zap.Uint32("SubmitIndex", miner.SubmitIndex)) + logg.Info("[server]", zap.String("blk", blk)) + + if miner.Server.PubCh == nil { + miner.Server.PubCh = utility.InitZmqPub(miner.Server.Config.Zmq.Pub) + } + if miner.Server.PubCh != nil { + //miner.Server.PubCh.SendChan <- [][]byte{[]byte("blksha3x"), []byte(blk)} + err := miner.Server.PubCh.SendMessage([][]byte{[]byte("blksha3x"), []byte(blk)}) + if err != nil { + miner.Server.PubCh.Destroy() + miner.Server.PubCh = nil + logg.Info("[server]", zap.String("blk", err.Error())) + } else { + logg.Info("[server]", zap.String("blk", "sent")) + } + } +} + +// server-->miner +func sha3x_parse_miner_notify(miner *coin.MinerObj, msg msg.Sha3xStratumJob) int { + if miner.Sha3xJob.Height != msg.Height { + miner.Job.IsClean = true + } + miner.Sha3xJob = msg + miner.Sha3xJob.Extranonce1 = miner.Job.Extranonce1 + miner.Job.Extranonce2_size = msg.Extranonce2_size + + //miner.Server.Logg.Info("[server]", zap.Int32("miner.Version", miner.Version), zap.Int32("msg.Version", msg.Version)) + return 1 +} + +func Init(server *coin.ServerContext) { + ServerSha3xCtx.ServerCtx = server + logg = server.Logg + logg.Info("[server]", zap.String("server_sha3x_version", SERVER_SHA3X_VERSION)) + coin.Init_diff_db() +} + +func Start() { + +} + +func Stop() { + coin.DiffStop() +} + +func InitMiner(miner *coin.MinerObj) { + miner.Sha3xJob = miner.Server.Sha3xJob + miner.Sha3xJob.Extranonce1 = miner.Job.Extranonce1 + + server_target := new(big.Int) + t_bytes, err := hex.DecodeString(miner.NexaJob.Target) + if err != nil { + logg.Error("[server]", zap.String("DecodeString", err.Error())) + return + } + //server_target.SetBytes(common.Reverse(t_bytes)) + server_target.SetBytes(t_bytes) + miner.ServerTarget = server_target + miner.ServerTargetS = miner.Server.SJob.Target +} + +func Handle_subscribe_sha3x(miner *coin.MinerObj, id float64, extranonce1 string) { + +} + +func HandleMinerSubscribe(miner *coin.MinerObj, id float64, extranonce1 string, msg string) { + +} + +func HandleMinerAuth(miner *coin.MinerObj) { + +} + +func HandleMinerSubmit(miner *coin.MinerObj, id float64, miner_user string, job_id string, nonce2 string, ntime string, nonce string) (bool, bool, bool) { + //nonce_str, _ := stratum.ReverseHexStringByByte(nonce) + accept_ok, submit_ok, handle_ok := handle_submit(miner, id, miner_user, job_id, nonce2, ntime, nonce) + return accept_ok, submit_ok, handle_ok +} + +func SetDifficulty(miner *coin.MinerObj) { + stratum.Set_difficulty(miner) +} + +func Sha3xNotify(miner *coin.MinerObj) { + miner.TxLock.Lock() + if !((miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING)) { + miner.TxLock.Unlock() + return + } + miner.TxLock.Unlock() + if miner.DifficultyNext > -1 { + ratio := miner.DifficultyNext / miner.Difficulty + if ratio > 1.1 || ratio < 0.9 { + miner.Difficulty = miner.DifficultyNext + miner.DifficultyNext = -1 + stratum.Set_difficulty(miner) + //logg.Info("[gbt]", zap.Float64("update Diff", miner.Difficulty)) + } else { + miner.DifficultyNext = -1 + } + } + + miner.TxLock.Lock() + //log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId) + + var msg Sha3xNotify_msg + + idb := make([]byte, 4) + binary.BigEndian.PutUint32(idb, miner.JobId) + miner.Job.Job_id = hex.EncodeToString(idb) + + msg.Params.Algo = "sha3x" + msg.Params.Job_id = miner.Job.Job_id + msg.Params.Blob = miner.Sha3xJob.Header + msg.Params.Height = miner.Sha3xJob.Height + //target_s, _ := stratum.ReverseHexStringByByte(miner.Sha3xJob.Target) + //msg.Params.Target = target_s[48:] + target_new, _ := utility.DiffToTarget(miner.Difficulty) + target_str := fmt.Sprintf("%064x", target_new.Bytes()) + target_strr, strerr := stratum.ReverseHexStringByByte(target_str) + if strerr != nil { + println("ReverseHexStringByByte", strerr.Error()) + } + //println("target=", target_str, "r=", target_strr) + msg.Params.Target = target_strr[48:] + + miner.CurHeight = miner.Sha3xJob.Height + + miner.Sha3xJob.JobDifficulty = miner.Difficulty + + miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.Sha3xJob) + + /*var entry coin.JobListEntry + entry.Job_id = miner.Job.Job_id + entry.Ts = time.Now() + + miner.LockForJobs.Lock() + miner.JobList.PushFront(entry) + var removes string = "" + if miner.JobList.Len() > int(coin.LOCAL_JOBS_TOTAL_SIZE) { + e := miner.JobList.Back() + entry := e.Value.(coin.JobListEntry) + removes = entry.Job_id + miner.JobList.Remove(e) + } + miner.LockForJobs.Unlock() + + if len(removes) > 0 { + miner.Jobs.Delete(removes) + }*/ + stratum.AddAndUpdateJob(miner) + + stratum.UpdateJobs(miner) + + //miner.LastJobId = miner.Job.Job_id + miner.JobId++ + + var body []byte + var err error + + msg.Jsonrpc = "2.0" + msg.Method = "job" + + body, err = json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + + var body_string = string(body) + "\n" + err = stratum.Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Unlock() + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +func Notify(miner *coin.MinerObj) { + Sha3xNotify(miner) +} + +func formatUint64ToHexWithPadding(val uint64) string { + hexStr := fmt.Sprintf("%016x", val) + + if len(hexStr) < 64 { + paddingLen := 64 - len(hexStr) + hexStr += string(make([]byte, paddingLen)) + for i := len(hexStr) - paddingLen; i < 64; i++ { + hexStr = hexStr[:i] + "0" + hexStr[i+1:] + } + } + return hexStr +} + +func HandleJobMsg(server *coin.ServerContext, Msg []byte) { + var result msg.Sha3xStratumJob + server.Logg.Warn("[server]", zap.String("receive", "job")) + + if err := json.Unmarshal(Msg, &result); err != nil { + server.Logg.Error("[server]", zap.String("Unmarshal", err.Error())) + return + } + result.Target = formatUint64ToHexWithPadding(result.U64target) + + //target_new, _ := utility.DiffToTarget((float64)(result.U64target)) + //target_str := fmt.Sprintf("%064x", target_new.Bytes()) + //result.Target = target_str + + server.Sha3xJob = msg.Sha3xStratumJob(result) + logg.Debug("[gbt]", zap.String("Target", server.Sha3xJob.Target)) + + server.Sha3xJob.Extranonce2_size = 8 + server.SJob.Extranonce2_size = 8 + logg.Debug("[gbt]", zap.Uint32("Height", server.Sha3xJob.Height), zap.String("Target", server.Sha3xJob.Target), zap.String("Header", server.Sha3xJob.Header) /*, zap.Uint64("Timastamp", server.Sha3xJob.CurTime)*/) + targetb, _ := hex.DecodeString(server.Sha3xJob.Target) + logg.Debug("[gbt]", zap.Uint64("Id", server.Sha3xJob.Id), zap.Float64("network diff", utility.Target2Diff(utility.Reverse(targetb)))) + + server.NetHight = uint64(server.Sha3xJob.Height) + server.NetTarget = server.Sha3xJob.Target + server.Miners.Range(func(k, v interface{}) bool { + if v != nil { + m, ok := v.(*(coin.MinerObj)) + if ok { + if m != nil { + server.Logg.Info("[server]", zap.String("lock", "start")) + m.TxLock.Lock() + status := m.Status + cmd := sha3x_parse_miner_notify(m, server.Sha3xJob) + m.TxLock.Unlock() + server.Logg.Info("[server]", zap.String("lock", "end")) + var need_notify bool = true + if time.Now().Sub(m.ConnSetupTime) >= time.Duration(coin.CONN_EXPIRED_TIME)*time.Second { + if (status != coin.MINER_STATUS_RUNNING) && (status != coin.MINER_STATUS_AUTHORIZED) { + //m.Conn.Close() + need_notify = false + } + } + if need_notify { + switch cmd { + case 0: //extranonce 1 and extranonce2 size + //TODO + case 1: //notify + Sha3xNotify(m) + } + } + } + } + } + return true + }) +} + +func IsMhsLow(miner *coin.MinerObj) bool { + if miner.Mhs5M < 1 { + return true + } + return false +} + +func GetBlockInterval() int { + return 3600 +} diff --git a/internal/stratum/stratum.go b/internal/stratum/stratum.go new file mode 100644 index 0000000..a1a556d --- /dev/null +++ b/internal/stratum/stratum.go @@ -0,0 +1,1296 @@ +// stratum.go +package stratum + +import ( + "bufio" + + "encoding/binary" + "encoding/hex" + "encoding/json" + "fmt" + "strconv" + + "bytes" + + "net" + "pool/internal/cache" + "pool/internal/db" + "pool/internal/msg" + "pool/internal/server/coin" + "pool/internal/utility" + "regexp" + "strings" + "time" + + "github.com/google/uuid" + "github.com/rs/zerolog" + "gopkg.in/natefinch/lumberjack.v2" + + "sync/atomic" + + //"container/list" + + "sync" + + "go.uber.org/zap" + + "log" +) + +const STRATUM_PING_INTERVAL_CNT int = 3 + +// const STRATUM_PING_FAILED_MAX_CNT int = STRATUM_PING_INTERVAL_CNT * 4 +const STRATUM_PING_FAILED_MAX_CNT int = 70 + +// Exception Macro +const MINER_ERR_UNKNOWN int = 20 +const MINER_ERR_NOT_FOUND_JOB int = 21 +const MINER_ERR_DUP_SHARE int = 22 +const MINER_ERR_LOW_DIF_SHARE int = 23 +const MINER_ERR_UNAUTH_WORKER int = 24 +const MINER_ERR_NOT_SUBSCRIBED int = 25 +const MINER_ERR_ILLEGAL_METHOD int = 26 +const MINER_ERR_ILLEGAL_PARARMS int = 27 +const MINER_ERR_IP_BANNED int = 28 +const MINER_ERR_INVALID_USERNAME int = 29 +const MINER_ERR_INTERNAL_ERROR int = 30 +const MINER_ERR_TIME_TOO_OLD int = 31 +const MINER_ERR_TIME_TOO_NEW int = 32 +const MINER_ERR_ILLEGAL_VERMASK int = 33 +const MINER_ERR_STALED_JOB int = 34 + +type Exception_reply struct { + ID float64 `json:"id"` + Result interface{} `json:"result"` + Error [3]interface{} `json:"error"` +} + +type Exception_reply_str struct { + ID string `json:"id"` + Result interface{} `json:"result"` + Error [3]interface{} `json:"error"` +} + +type Subscribe_reply struct { + Result [3]interface{} `json:"result"` + ID float64 `json:"id"` + Error interface{} `json:"error"` +} + +type SubscribeGpu_reply struct { + Jsonrpc string `json:"jsonrpc"` + Result [3]interface{} `json:"result"` + ID float64 `json:"id"` + Error interface{} `json:"error"` +} + +type Subscribe_reply_str struct { + Result [3]interface{} `json:"result"` + ID string `json:"id"` + Error interface{} `json:"error"` +} + +type Notify_msg struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params [9]interface{} `json:"params"` +} + +type Difficulty_msg struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params [1]float64 `json:"params"` +} + +type DifficultyNexa_msg struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params [1]string `json:"params"` +} + +type DifficultyNexaGpu_msg struct { + Jsonrpc string `json:"jsonrpc"` + Method string `json:"method"` + Params [1]float64 `json:"params"` + ID interface{} `json:"id"` +} + +type ExtranonceSubscribeGpu_reply struct { + ID interface{} `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result bool `json:"result"` +} + +type Authorize_reply struct { + Result bool `json:"result"` + ID float64 `json:"id"` + Error interface{} `json:"error"` +} + +type Sha3xAuthorize_reply struct { + Jsonrpc string `json:"jsonrpc"` + Result Sha3xAuthorize_result_msg `json:"result"` + ID float64 `json:"id"` +} + +type Authorize_reply_str struct { + Result bool `json:"result"` + ID string `json:"id"` + Error interface{} `json:"error"` +} + +type Submit_nonce struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params []string `json:"params"` +} + +type Sha3xSubmit_params struct { + Id string `json:"id"` + Job_id string `json:"job_id"` + Nonce string `json:"nonce"` + Result string `json:"result"` +} + +type Sha3xSubmit_nonce struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params Sha3xSubmit_params `json:"params"` +} + +type Reconnect_msg struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params []string `json:"params"` +} + +type Ping_msg struct { + ID float64 `json:"id"` + Method string `json:"method"` + Params interface{} `json:"params"` +} + +type Authorize_msg struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params []string `json:"params"` +} + +type Sha3xAuthorize_params_msg struct { + Login string `json:"login"` + Pass string `json:"pass"` + Agent string `json:"agent"` +} + +type Sha3xAuthorize_msg struct { + ID interface{} `json:"id"` + Method string `json:"method"` + Params Sha3xAuthorize_params_msg `json:"params"` +} + +type Sha3xAuthorize_job_msg struct { + Algo string `json:"algo"` + Blob string `json:"blob"` + Height uint32 `json:"height"` + Job_id string `json:"job_id"` + Target string `json:"target"` + Xn string `json:"xn"` +} + +type Sha3xAuthorize_result_msg struct { + Id string `json:"id"` + Job Sha3xAuthorize_job_msg `json:"job"` + Status string `json:"status"` +} + +type MoneroAuthorize_reply struct { + ID float64 `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Error interface{} `json:"error"` + Result MoneroJob `json:"result"` +} + +type MoneroJob struct { + Id string `json:"id"` + Job struct { + Id string `json:"id"` + JobId string `json:"job_id"` + Blob string `json:"blob"` + Target string `json:"target"` + SeedHash string `json:"seed_hash"` + NextSeedHash string `json:"next_seed_hash"` + Algo string `json:"algo"` + Height uint64 `json:"height"` + } `json:"job"` + Status string `json:"status"` +} + +type KeepAlived_resp struct { + ID int `json:"id"` + Jsonrpc string `json:"jsonrpc"` + Result struct { + Status string `json:"status"` + } `json:"result"` +} + +func Conn_tx(conn net.Conn, body []byte) error { + _, err := conn.Write(body) + if err != nil { + conn.Close() + } + return err +} + +func Conn_rx(reader *bufio.Reader) (line string) { + line, err := reader.ReadString('\n') + if err != nil { + //if err != io.EOF { + //logg.Error("[server]", zap.String("ReadString", err.Error())) + return "" + //} + } + strings.TrimSpace(line) + return line +} + +// miner-->server +func Handle_subscribe(miner *coin.MinerObj, id float64, extranonce1 string) { + miner.TxLock.Lock() + var results [1][2]string + results[0][0] = "mining.notify" + results[0][1] = miner.MinerId + var result [3]interface{} + result[0] = results + //result[1] = miner.Job.Extranonce1 + /*be1 := make([]byte, 4) + binary.LittleEndian.PutUint32(be1, (miner.Server.Extranonce1 + 0x81000000)) + result[1] = "0000000000000000" + hex.EncodeToString(be1) + miner.Server.Extranonce1++*/ + result[1] = extranonce1 + //miner.Server.Logg.Debug("[server]", zap.Uint64("extra2", miner.Job.Extranonce2_size)) + if miner.Job.Extranonce2_size == 0 { + result[2] = 4 + } else { + result[2] = miner.Job.Extranonce2_size + } + var ack Subscribe_reply + ack.ID = id + ack.Result = result + ack.Error = nil + if extranonce1 == "" { + miner.TxLock.Unlock() + Handle_exception(miner, id, MINER_ERR_NOT_SUBSCRIBED) + return + } + body, err := json.Marshal(ack) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + var body_string = string(body) + "\n" + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + miner.Status = coin.MINER_STATUS_SUBSCRIBED + miner.TxLock.Unlock() +} + +// server-->miner +func Handle_exception(miner *coin.MinerObj, Id float64, errId int) { + miner.TxLock.Lock() + var errors [3]interface{} + errors[0] = errId + switch errId { + case MINER_ERR_UNKNOWN: + errors[1] = "Other/Unknown" + break + case MINER_ERR_NOT_FOUND_JOB: + errors[1] = "Job not found" + break + case MINER_ERR_STALED_JOB: + errors[1] = "Job staled" + break + case MINER_ERR_DUP_SHARE: + errors[1] = "Duplicate share" + break + case MINER_ERR_LOW_DIF_SHARE: + errors[1] = "Low difficulty share" + break + case MINER_ERR_UNAUTH_WORKER: + errors[1] = "Unauthorized worker" + break + case MINER_ERR_NOT_SUBSCRIBED: + errors[1] = "Not subscribed" + break + case MINER_ERR_ILLEGAL_METHOD: + errors[1] = "Illegal method" + break + case MINER_ERR_ILLEGAL_PARARMS: + errors[1] = "Illegal params" + break + case MINER_ERR_IP_BANNED: + errors[1] = "Ip banned" + break + case MINER_ERR_INVALID_USERNAME: + errors[1] = "Invalid username" + break + case MINER_ERR_INTERNAL_ERROR: + errors[1] = "Internal error" + break + case MINER_ERR_TIME_TOO_OLD: + errors[1] = "Time too old" + break + case MINER_ERR_TIME_TOO_NEW: + errors[1] = "Time too new" + break + case MINER_ERR_ILLEGAL_VERMASK: + errors[1] = "Invalid version mask" + break + } + errors[2] = nil + var ack Exception_reply + ack.ID = Id + ack.Result = nil + ack.Error = errors + body, err := json.Marshal(ack) + if err != nil { + miner.Server.Logg.Debug("[server]", zap.String("fail to handle_exception", err.Error())) + miner.TxLock.Unlock() + return + } + var body_string = string(body) + "\n" + + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + miner.Server.Logg.Debug("[server]", zap.String("fail to handle_exception", err.Error())) + //miner.Server.Miners.Delete(miner.MinerId) + miner.TxLock.Unlock() + return + } + miner.TxLock.Unlock() + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) +} +func Handle_exception_str(miner *coin.MinerObj, Id string, errId int) { + miner.TxLock.Lock() + var errors [3]interface{} + errors[0] = errId + switch errId { + case MINER_ERR_UNKNOWN: + errors[1] = "Other/Unknown" + break + case MINER_ERR_NOT_FOUND_JOB: + errors[1] = "Job not found" + break + case MINER_ERR_STALED_JOB: + errors[1] = "Job staled" + break + case MINER_ERR_DUP_SHARE: + errors[1] = "Duplicate share" + break + case MINER_ERR_LOW_DIF_SHARE: + errors[1] = "Low difficulty share" + break + case MINER_ERR_UNAUTH_WORKER: + errors[1] = "Unauthorized worker" + break + case MINER_ERR_NOT_SUBSCRIBED: + errors[1] = "Not subscribed" + break + case MINER_ERR_ILLEGAL_METHOD: + errors[1] = "Illegal method" + break + case MINER_ERR_ILLEGAL_PARARMS: + errors[1] = "Illegal params" + break + case MINER_ERR_IP_BANNED: + errors[1] = "Ip banned" + break + case MINER_ERR_INVALID_USERNAME: + errors[1] = "Invalid username" + break + case MINER_ERR_INTERNAL_ERROR: + errors[1] = "Internal error" + break + case MINER_ERR_TIME_TOO_OLD: + errors[1] = "Time too old" + break + case MINER_ERR_TIME_TOO_NEW: + errors[1] = "Time too new" + break + case MINER_ERR_ILLEGAL_VERMASK: + errors[1] = "Invalid version mask" + break + } + errors[2] = nil + var ack Exception_reply_str + ack.ID = Id + ack.Result = nil + ack.Error = errors + body, err := json.Marshal(ack) + if err != nil { + miner.Server.Logg.Debug("[server]", zap.String("fail to handle_exception", err.Error())) + miner.TxLock.Unlock() + return + } + var body_string = string(body) + "\n" + + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + miner.Server.Logg.Debug("[server]", zap.String("fail to handle_exception", err.Error())) + //miner.Server.Miners.Delete(miner.MinerId) + miner.TxLock.Unlock() + return + } + miner.TxLock.Unlock() + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) +} + +func InitMinerMhs(miner *coin.MinerObj, user string, minername string, minerindex string, miner_id string, status string, DbCtx *db.DbContext) { + var k string + + k = user + "." + minername + "_" + minerindex + + m, ok := miner.Server.MMhs.Load(k) + if ok { + var mhs *coin.MhsObj = m.(*coin.MhsObj) + mhs.StartSubmitTime = time.Now() + mhs.Status = status + mhs.MinerId = miner_id + //mhs.LockForMhs.Lock() + //mhs.Accepts = nil + //mhs.Rejects = nil + //mhs.LockForMhs.Unlock() + + miner.Server.MMhs.Store(k, mhs) + //miner.Server.Logg.Info("[server]", zap.String("exist mhs", k)) + } else { + var mhs coin.MhsObj + mhs.MinerId = miner_id + + mhs.StartSubmitTime = time.Now() + mhs.Status = status + mhs.Name = miner.Name + + mhs.User = user + + mhs.Miner = minername + mhs.Index = minerindex + + mhs.StartDayTime = time.Now() + + mhs.Algo = -1 + mhs.Release = false + + var mhs_lock sync.Mutex + mhs.LockForMhs = mhs_lock + + miner.Server.MMhs.Store(k, &mhs) + //miner.Server.Logg.Info("[server]", zap.String("new mhs", k)) + } +} + +func validateUsername(username string, min int, max int) bool { + // + if len(username) < min || len(username) > max { + return false + } + + // + /*allowedChars := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_" + for _, char := range username { + if !strings.ContainsRune(allowedChars, char) { + return false + } + }*/ + + // + //pattern := `^[a-zA-Z0-9_]{4,15}$` + pattern := fmt.Sprintf("^[a-zA-Z0-9_]{%d,%d}$", min, max) + match, err := regexp.MatchString(pattern, username) + if err != nil { + //fmt.Println("Error matching pattern:", err) + return false + } + return match +} + +func Handle_extranonce(miner *coin.MinerObj, id float64) { + miner.TxLock.Lock() + + var ack ExtranonceSubscribeGpu_reply + ack.ID = id + ack.Result = true + ack.Jsonrpc = "2.0" + + body, err := json.Marshal(ack) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + var body_string = string(body) + "\n" + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + + miner.TxLock.Unlock() + + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +func extractAndConvertDiff(password string) (float64, bool) { + index := strings.Index(password, "d=") + if index == -1 { + return 0, false + } + + valueStr := password[index+2:] + + value, err := strconv.ParseFloat(valueStr, 64) + if err != nil { + return 0, false + } + + return value, true +} + +// miner-->server +func Handle_authorize(miner *coin.MinerObj, id float64, auth_msg string, DbCtx *db.DbContext) bool { + + miner.TxLock.Lock() + var s Authorize_msg + var e error + var s_sha3x Sha3xAuthorize_msg + + if miner.Name == "nexa" { + if e = json.Unmarshal([]byte(auth_msg), &s); e != nil { + miner.Server.Logg.Error("[server]", zap.String("Unmarshal", e.Error())) + } + } else if miner.Name == "sha3x" || miner.Name == "monero" { + if e = json.Unmarshal([]byte(auth_msg), &s_sha3x); e != nil { + miner.Server.Logg.Error("[server]", zap.String("Unmarshal", e.Error())) + } + s.Params = append(s.Params, s_sha3x.Params.Login) + s.Params = append(s.Params, s_sha3x.Params.Pass) + } else { + + } + + if len(s.Params) < 2 { + miner.Server.Logg.Error("[server]", zap.String("Handle_authorize err", s.Params[0])) + miner.TxLock.Unlock() + return false + } + + if s.Params[0] == "" { + miner.Server.Logg.Error("[server]", zap.String("Handle_authorize err", s.Params[0])) + miner.TxLock.Unlock() + return false + } + + var strArr []string + + if strings.Index(s.Params[0], ".") == -1 { + miner.Server.Logg.Error("[server]", zap.String("user format err", s.Params[0])) + miner.TxLock.Unlock() + return false + } + + strArr = strings.Split(s.Params[0], ".") //jjyykk.4x251.dash(jjyykk:user 4x251:miner) + + if strArr[0] == "" || strArr[1] == "" { + miner.Server.Logg.Error("[server]", zap.String("user", strArr[0]), zap.String("miner", strArr[1])) + miner.TxLock.Unlock() + return false + } + + if (!validateUsername(strArr[0], 3, 15)) || (!validateUsername(strArr[1], 1, 15)) { + miner.TxLock.Unlock() + miner.Server.Logg.Error("[server]", zap.String("invalid user", strArr[0])) + Handle_exception(miner, id, MINER_ERR_INVALID_USERNAME) + return false + } + + miner.Server.Logg.Warn("[server]", zap.String("user", strArr[0]), zap.String("miner", strArr[1])) + + if miner.Server.Config.Host.Auth { + if !db.CheckUserIsPermitted(strArr[0], miner.Server.MinerType) { + _, ok := miner.Server.CacheUsers.Load(strArr[0]) + if ok { + } else { + miner.TxLock.Unlock() + miner.Server.Logg.Error("[server]", zap.String("not found user", strArr[0])) + Handle_exception(miner, id, MINER_ERR_INVALID_USERNAME) + return false + } + } else { + _, ok := miner.Server.CacheUsers.Load(strArr[0]) + if ok { + } else { + if atomic.LoadInt32(&(miner.Server.CacheUsersCnt)) < 1000 { + miner.Server.CacheUsers.Store(strArr[0], strArr[0]) + atomic.AddInt32(&(miner.Server.CacheUsersCnt), 1) + } + } + } + } + miner.Session = uuid.New().String() + prediff, ok := extractAndConvertDiff(s.Params[1]) + if ok { + if (prediff >= miner.Server.Config.Diff.DiffMin) && (prediff <= miner.Server.Config.Diff.DiffMax) { + miner.Difficulty = prediff + } + } + miner.User = strArr[0] + miner.Miner = strArr[1] + miner.Authorized = true + var body_string = "" + + if miner.Name == "nexa" { + var ack Authorize_reply + ack.ID = id + ack.Result = true + ack.Error = nil + body, err := json.Marshal(ack) + + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return false + } + + body_string = string(body) + "\n" + err = Conn_tx(miner.Conn, []byte(body_string)) + + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + } else if miner.Name == "sha3x" { + var sha3x_ack Sha3xAuthorize_reply + sha3x_ack.Jsonrpc = "2.0" + + idb := make([]byte, 4) + binary.BigEndian.PutUint32(idb, miner.JobId) + miner.Job.Job_id = hex.EncodeToString(idb) + + sha3x_ack.ID = id + sha3x_ack.Result.Status = "OK" + sha3x_ack.Result.Id = miner.Job.Job_id + sha3x_ack.Result.Job.Algo = "sha3x" + sha3x_ack.Result.Job.Blob = miner.Sha3xJob.Header + sha3x_ack.Result.Job.Height = miner.Sha3xJob.Height + sha3x_ack.Result.Job.Job_id = miner.Job.Job_id + //target_str, _ := ReverseHexStringByByte(miner.Sha3xJob.Target) + //sha3x_ack.Result.Job.Target = target_str[48:] + target_new, _ := utility.DiffToTarget(miner.Difficulty) + target_str := fmt.Sprintf("%064x", target_new.Bytes()) + target_strr, strerr := ReverseHexStringByByte(target_str) + if strerr != nil { + println("ReverseHexStringByByte", strerr.Error()) + } + //println("target=", target_str, "r=", target_strr) + sha3x_ack.Result.Job.Target = target_strr[48:] + sha3x_ack.Result.Job.Xn = miner.Sha3xJob.Extranonce1[:4] + + body, err := json.Marshal(sha3x_ack) + + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return false + } + + body_string = string(body) + "\n" + err = Conn_tx(miner.Conn, []byte(body_string)) + + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + } else if miner.Name == "monero" { + var monero_ack MoneroAuthorize_reply + monero_ack.Jsonrpc = "2.0" + monero_ack.ID = id + monero_ack.Result.Status = "OK" + monero_ack.Result.Id = miner.Session + monero_ack.Result.Job.Id = miner.Session + monero_ack.Result.Job.JobId = miner.MoneroJob.JobId + monero_ack.Result.Job.Algo = "rx/0" + target_new, _ := utility.MoneroDiffToTarget(miner.Difficulty) + target_str := fmt.Sprintf("%064x", target_new.Bytes()) + target_strr, strerr := ReverseHexStringByByte(target_str) + if strerr != nil { + println("ReverseHexStringByByte", strerr.Error()) + } + monero_ack.Result.Job.Target = target_strr[48:] + monero_ack.Result.Job.Blob = miner.MoneroJob.BlockhashingBlob + monero_ack.Result.Job.Height = miner.MoneroJob.Height + monero_ack.Result.Job.SeedHash = miner.MoneroJob.SeedHash + monero_ack.Result.Job.NextSeedHash = "" + body, err := json.Marshal(monero_ack) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return false + } + miner.Jobs.LoadOrStore(miner.MoneroJob.JobId, miner.MoneroJob) + body_string = string(body) + "\n" + // fmt.Println(body_string) + err = Conn_tx(miner.Conn, []byte(body_string)) + } else { + + } + + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.Status = coin.MINER_STATUS_AUTHORIZED + miner.TxLock.Unlock() + + mlogfile := "./logs/" + miner.Name + "/" + miner.User + "_" + miner.Miner + "_" + fmt.Sprint(miner.MinerIndex) + ".log" + logFile := &lumberjack.Logger{ + Filename: mlogfile, + MaxSize: 1, + MaxBackups: 3, + MaxAge: 31, + Compress: true, + } + miner.LogR = logFile + zerolog.TimeFieldFormat = time.RFC3339 + miner.Zlog = zerolog.New(logFile).With().Timestamp().Logger() + miner.ZlogInit = true + miner.Zlog.Info().Msg(auth_msg) + miner.Zlog.Info().Msg(body_string) + + return true + +} + +// server-->miner +func Set_difficulty(miner *coin.MinerObj) { + miner.TxLock.Lock() + var msg Difficulty_msg + msg.ID = nil + msg.Method = "mining.set_difficulty" + msg.Params[0] = miner.Difficulty + body, err := json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + + var body_string = string(body) + "\n" + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Unlock() + + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +/*func Set_difficulty_nexa(miner *coin.MinerObj) { + target_new, err_to := utility.DiffToTarget(miner.Difficulty) + if err_to != nil { + miner.Server.Logg.Error("[server]", zap.String("DiffToTarget", err_to.Error())) + return + } + miner.Target = target_new + miner.TxLock.Lock() + var msg DifficultyNexa_msg + msg.ID = nil + msg.Method = "mining.set_target" + target := fmt.Sprintf("%064x\n", miner.Target.Bytes()) + msg.Params[0] = target + body, err := json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + + var body_string = string(body) + "\n" + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Unlock() + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +}*/ + +func Set_difficulty_nexa(miner *coin.MinerObj) { + miner.TxLock.Lock() + var msg DifficultyNexaGpu_msg + msg.ID = nil + msg.Method = "mining.set_difficulty" + msg.Params[0] = miner.Difficulty + msg.Jsonrpc = "2.0" + body, err := json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + + var body_string = string(body) + "\n" + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Unlock() + + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +func removeExpiredJobs(miner *coin.MinerObj, checkExpiration bool) { + miner.LockForJobs.Lock() + defer miner.LockForJobs.Unlock() + if checkExpiration { + var removes []string + + for element := miner.JobList.Front(); element != nil; { + entry, isValidEntry := element.Value.(coin.JobListEntry) + next := element.Next() + + if isValidEntry { + //if checkExpiration { + if time.Since(entry.Ts) >= time.Duration(coin.LOCAL_JOBS_EXPIRED_TIME)*time.Second { + removes = append(removes, entry.Job_id) + miner.JobList.Remove(element) + element.Value = nil + } + //} else { + //removes = append(removes, entry.Job_id) + //miner.JobList.Remove(element) + //} + } + element = next + } + + for _, jobID := range removes { + //miner.Jobs.Store(jobID, nil) + miner.Jobs.Delete(jobID) + } + } else { + //miner.JobList.Init() + for elem := miner.JobList.Front(); elem != nil; { + next := elem.Next() + miner.JobList.Remove(elem) + elem.Value = nil + elem = next + } + //miner.Jobs = sync.Map{} + var keysJobs []interface{} + miner.Jobs.Range(func(k, v interface{}) bool { + keysJobs = append(keysJobs, k) + return true + }) + for _, key := range keysJobs { + //miner.Jobs.Store(key, nil) + miner.Jobs.Delete(key) + } + } + + var total_jobs int32 = 0 + miner.Jobs.Range(func(k, v interface{}) bool { + total_jobs += 1 + return true + }) + total_entries := 0 + for e := miner.JobList.Front(); e != nil; e = e.Next() { + total_entries++ + } + // log.Println("jobs: ", miner.User, miner.Miner, total_jobs, total_entries) +} + +func UpdateJobs(miner *coin.MinerObj) { + /*var removes []string + miner.LockForJobs.Lock() + defer miner.LockForJobs.Unlock() + //for e := miner.JobList.Front(); e != nil; e = e.Next() { + for e := miner.JobList.Front(); e != nil; { + entry, ok := e.Value.(coin.JobListEntry) + if ok { + //if time.Now().Sub(entry.Ts) >= time.Duration(coin.LOCAL_JOBS_EXPIRED_TIME)*time.Second { + if time.Since(entry.Ts) >= time.Duration(coin.LOCAL_JOBS_EXPIRED_TIME)*time.Second { + removes = append(removes, entry.Job_id) + next := e.Next() + miner.JobList.Remove(e) + e = next + continue + } + } + e = e.Next() + } + //miner.LockForJobs.Unlock() + for i := range removes { + miner.Jobs.Delete(removes[i]) + }*/ + removeExpiredJobs(miner, true) +} + +func StaleAllJobs(miner *coin.MinerObj) { + /*var removes []string + miner.LockForJobs.Lock() + defer miner.LockForJobs.Unlock() + //for e := miner.JobList.Front(); e != nil; e = e.Next() { + for e := miner.JobList.Front(); e != nil; { + entry, ok := e.Value.(coin.JobListEntry) + if ok { + removes = append(removes, entry.Job_id) + next := e.Next() + miner.JobList.Remove(e) + e = next + continue + } + e = e.Next() + } + //miner.LockForJobs.Unlock() + for i := range removes { + miner.Jobs.Delete(removes[i]) + }*/ + removeExpiredJobs(miner, false) +} + +func AddAndUpdateJob(miner *coin.MinerObj) { + + miner.LockForJobs.Lock() + defer miner.LockForJobs.Unlock() + + currentLen := miner.JobList.Len() + maxSize := int(coin.LOCAL_JOBS_TOTAL_SIZE) + needRemove := currentLen + 1 - maxSize + + for cnt := 0; cnt < needRemove; cnt++ { + //if miner.JobList.Len()+1 > int(coin.LOCAL_JOBS_TOTAL_SIZE) { + if e := miner.JobList.Back(); e != nil { + if oldestEntry, ok := e.Value.(coin.JobListEntry); ok { + miner.JobList.Remove(e) + e.Value = nil + //miner.Jobs.Store(oldestEntry.Job_id, nil) + miner.Jobs.Delete(oldestEntry.Job_id) + } else { + miner.JobList.Remove(e) + e.Value = nil + } + } + //} + } + + entry := coin.JobListEntry{ + Job_id: miner.Job.Job_id, + Ts: time.Now(), + } + miner.JobList.PushFront(entry) + +} + +func Notify(miner *coin.MinerObj) { + miner.TxLock.Lock() + if !((miner.Status == coin.MINER_STATUS_AUTHORIZED) || (miner.Status == coin.MINER_STATUS_RUNNING)) { + miner.TxLock.Unlock() + return + } + miner.TxLock.Unlock() + if miner.DifficultyNext > -1 { + ratio := miner.DifficultyNext / miner.Difficulty + if ratio > 1.1 || ratio < 0.9 { + miner.Difficulty = miner.DifficultyNext + miner.DifficultyNext = -1 + //Set_difficulty(miner) + miner.Server.CoinCtx.SetDifficulty(miner) + } else { + miner.DifficultyNext = -1 + } + } + miner.TxLock.Lock() + //log.Println("[server]extra1, id", miner.Job.Extranonce1, miner.Job.Job_id, miner.MinerId) + var params [9]interface{} + var tlist []string = make([]string, 0) + idb := make([]byte, 4) + binary.BigEndian.PutUint32(idb, miner.JobId) + miner.Job.Job_id = hex.EncodeToString(idb) + params[0] = miner.Job.Job_id + if len(miner.Job.PrevblockS) > 0 { + params[1] = miner.Job.PrevblockBig + } else { + p_big := utility.Convert_big_endian(miner.Job.Prevblock.CloneBytes()) + params[1] = hex.EncodeToString(p_big) + } + params[2] = miner.Job.Coinbase1 + params[3] = miner.Job.Coinbase2 + params[4] = tlist + + miner.CurHeight = miner.Job.Height + + if miner.Job.Transactions != nil { + if len(*miner.Job.Transactions) > 0 { + params[4] = miner.Job.Transactions + + /*miner.Server.Logg.Error("[notify]", zap.String("coinbase1", miner.Job.Coinbase1), zap.String("coinbase2", miner.Job.Coinbase2), zap.Uint32("height", miner.Job.Height)) + for i := 0; i < len(*miner.Job.Transactions); i++ { + miner.Server.Logg.Error("[notify]", zap.String("trans", (*miner.Job.Transactions)[i])) + }*/ + + } + } + vb := make([]byte, 4) + binary.LittleEndian.PutUint32(vb, uint32(miner.Job.Version)) + params[5] = hex.EncodeToString(vb) + bb := make([]byte, 4) + binary.LittleEndian.PutUint32(bb, miner.Job.Bits) + params[6] = hex.EncodeToString(bb) + t := miner.Job.Timestamp.Unix() + if t > int64(^uint32(0)) { + tb := make([]byte, 8) + binary.LittleEndian.PutUint64(tb, uint64(t)) + params[7] = hex.EncodeToString(tb) + } else { + tb := make([]byte, 4) + binary.LittleEndian.PutUint32(tb, uint32(t)) + params[7] = hex.EncodeToString(tb) + } + if miner.Reconnect { + params[8] = true + miner.Reconnect = false + } else { + params[8] = miner.Job.IsClean + } + miner.Job.JobDifficulty = miner.Difficulty + + //miner.Jobs[miner.Job.Job_id] = miner.Job + miner.Jobs.LoadOrStore(miner.Job.Job_id, miner.Job) + + /*var entry coin.JobListEntry + entry.Job_id = miner.Job.Job_id + entry.Ts = time.Now() + + miner.LockForJobs.Lock() + miner.JobList.PushFront(entry) + var removes string = "" + if miner.JobList.Len() > int(coin.LOCAL_JOBS_TOTAL_SIZE) { + e := miner.JobList.Back() + entry := e.Value.(coin.JobListEntry) + removes = entry.Job_id + miner.JobList.Remove(e) + } + miner.LockForJobs.Unlock() + if len(removes) > 0 { + miner.Jobs.Delete(removes) + }*/ + AddAndUpdateJob(miner) + UpdateJobs(miner) + + //miner.LastJobId = miner.Job.Job_id + miner.JobId++ + + var msg Notify_msg + msg.ID = nil + msg.Method = "mining.notify" + msg.Params = params + body, err := json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("Marshal", err.Error())) + miner.TxLock.Unlock() + return + } + var body_string = string(body) + "\n" + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + //delete(miner.Server.Miners, miner.MinerId) + //miner.Server.Miners.Delete(miner.MinerId) + } + //miner.Server.Logg.Debug("[server]", zap.String("tx", body_string)) + miner.TxLock.Unlock() + + if miner.ZlogInit { + miner.Zlog.Info().Msg(body_string) + } +} + +type Submit_ack struct { + Result bool `json:"result"` + ID float64 `json:"id"` + Error interface{} `json:"error"` +} + +type Submit_ack_str struct { + Result bool `json:"result"` + ID string `json:"id"` + Error interface{} `json:"error"` +} + +// server-->miner +func parse_miner_notify(miner *coin.MinerObj, msg msg.StratumJob) int { + miner.Job.Version = msg.Version + miner.Job.Prevblock = msg.Prevblock + miner.Job.Coinbase1 = msg.Coinbase1 + miner.Job.Coinbase2 = msg.Coinbase2 + miner.Job.Bits = msg.Bits + miner.Job.Timestamp = msg.Timestamp + miner.Job.Target = msg.Target + miner.Job.PrevblockS = msg.PrevblockS + miner.Job.PrevblockBig = msg.PrevblockBig + miner.Job.Transactions = msg.Transactions + miner.Job.BitsS = msg.BitsS + miner.Job.Height = msg.Height + miner.Job.Extranonce2_size = msg.Extranonce2_size + miner.Job.TransData = msg.TransData + miner.Job.Payloadstart = msg.Payloadstart + miner.Job.Segwit = msg.Segwit + miner.Job.IsClean = msg.IsClean + miner.Job.Mintime = msg.Mintime + miner.ServerTargetS = msg.Target + vb := make([]byte, 4) + binary.LittleEndian.PutUint32(vb, uint32(msg.Version)) + vBuffer := bytes.NewBuffer(vb) + binary.Read(vBuffer, binary.BigEndian, &(miner.Version)) + //log.Printf("version %04x, %04x", miner.Version, msg.Version) + //miner.Server.Logg.Info("[server]", zap.Int32("miner.Version", miner.Version), zap.Int32("msg.Version", msg.Version)) + return 1 +} + +func Send_reconnect_msg(miner *coin.MinerObj) bool { + var msg Reconnect_msg + msg.ID = nil + msg.Method = "client.reconnect" + msg.Params = nil + body, err := json.Marshal(msg) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("failed to Send_reconnect_msg", err.Error()), zap.String("user", miner.User), zap.String("miner", miner.Miner)) + return false + } + body_string := string(body) + "\n" + err = Conn_tx(miner.Conn, []byte(body_string)) + if err != nil { + miner.Server.Logg.Error("[server]", zap.String("failed to Send_reconnect_msg", err.Error()), zap.String("user", miner.User), zap.String("miner", miner.Miner)) + return false + } + return true +} + +func UpdateMhs(miner *coin.MinerObj, accept bool, diff float64, algo int, DbCtx *db.DbContext) { + var k string + + k = miner.User + "." + miner.Miner + "_" + fmt.Sprint(miner.MinerIndex) + + v, ok := miner.Server.MMhs.Load(k) + if ok { + if v != nil { + var m *coin.MhsObj = v.(*coin.MhsObj) + if m != nil { + var item coin.MhsItem + item.Tt = time.Now() + item.Diff = diff + m.LockForMhs.Lock() + if accept { + m.Accepts = append(m.Accepts, item) + } else { + m.Rejects = append(m.Rejects, item) + } + m.LockForMhs.Unlock() + m.Status = miner.Status + m.MinerId = miner.MinerId + if m.Algo < 0 { + m.Algo = algo + } + log.Println("miner:", k, len(m.Accepts), len(m.Rejects)) + miner.Server.MMhs.Store(k, m) + var mhsItem cache.CacheMhsItem + mhsItem.Tt = item.Tt.Format(time.RFC3339) + mhsItem.Diff = item.Diff + if accept { + //cache.StoreMhsCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "accepts", mhsItem) + } else { + //cache.StoreMhsCache(miner.Server.RedisClient, miner.Server.MinerType, miner.User, miner.Miner, fmt.Sprint(miner.MinerIndex), "rejects", mhsItem) + } + //miner.Server.Logg.Info("[mhs]", zap.String("UpdateMhs", k), zap.Int("accepts", len(m.Accepts)), zap.Int("rejects", len(m.Rejects)), zap.Int("algo", m.Algo)) + } + } + } +} + +func UpdateMhsStatus(miner *coin.MinerObj, DbCtx *db.DbContext) { + var k string + + k = miner.User + "." + miner.Miner + "_" + fmt.Sprint(miner.MinerIndex) + + v, ok := miner.Server.MMhs.Load(k) + if ok { + if v != nil { + var m *coin.MhsObj = v.(*coin.MhsObj) + if m != nil { + m.Status = miner.Status + m.MinerId = miner.MinerId + miner.Server.MMhs.Store(k, m) + //miner.Server.Logg.Info("[mhs]", zap.String("UpdateMhsStatus", k), zap.String("update status", m.Status)) + } + } + } +} + +func SetMhsRelease(miner *coin.MinerObj) { + var k string + + k = miner.User + "." + miner.Miner + "_" + fmt.Sprint(miner.MinerIndex) + + v, ok := miner.Server.MMhs.Load(k) + if ok { + if v != nil { + var m *coin.MhsObj = v.(*coin.MhsObj) + if m != nil { + //if m.Status == coin.MINER_STATUS_DISCONNECTED { + //m.Release = true + m.LockForMhs.Lock() + m.Accepts = nil + m.Rejects = nil + m.LockForMhs.Unlock() + miner.Server.MMhs.Store(k, m) + //} + } + } + } + //miner.Server.MMhs.Store(k, nil) + miner.Server.MMhs.Delete(k) +} + +func ReverseHexStringByByte(hexStr string) (string, error) { + + bytes, err := hex.DecodeString(hexStr) + if err != nil { + return "", err + } + + for i, j := 0, len(bytes)-1; i < j; i, j = i+1, j-1 { + bytes[i], bytes[j] = bytes[j], bytes[i] + } + + return hex.EncodeToString(bytes), nil +} diff --git a/internal/utility/utility.go b/internal/utility/utility.go new file mode 100644 index 0000000..e4c7267 --- /dev/null +++ b/internal/utility/utility.go @@ -0,0 +1,367 @@ +// utility.go +package utility + +import ( + "encoding/binary" + "encoding/json" + "fmt" + "io/ioutil" + + "bytes" + "log" + "math" + "math/big" + "os" + "os/exec" + "strings" + + "time" + + "github.com/zeromq/goczmq" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" +) + +const BITCOIND_ZMQ_HASHBLOCK string = "hashblock" + +type CoinConfig struct { + Coin string `json:"coin"` + Pprof string `json:"pprof,omitempty"` +} + +type ZmqConfig struct { + Pub string `json:"pub"` + Sub string `json:"sub"` +} + +type RedisConfig struct { + Addr string `json:"addr"` + Password string `json:"password"` + DB int `json:"db"` +} + +type LogRotateConfig struct { + MaxSize int `json:"maxsize"` + MaxBackups int `json:"maxbackups"` + MaxAge int `json:"maxage"` + Compress bool `json:"compress"` +} + +func InitLogg(zaplog *zap.Config, rotate *LogRotateConfig, coinname string, modulename string) (*zap.Logger, *lumberjack.Logger, error) { + os.MkdirAll("logs/"+coinname, os.ModePerm) + logfile := "./logs/" + coinname + "/" + modulename + ".log" + + logRotate := &lumberjack.Logger{ + Filename: logfile, + MaxSize: rotate.MaxSize, + MaxBackups: rotate.MaxBackups, + MaxAge: rotate.MaxAge, + Compress: rotate.Compress, + } + + zaplog.EncoderConfig = zap.NewProductionEncoderConfig() + zaplog.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + + opath := []string{"", ""} + opath[0] = zaplog.OutputPaths[0] + opath[1] = logfile + zaplog.OutputPaths = opath + + l, err := zaplog.Build( + zap.WrapCore(func(core zapcore.Core) zapcore.Core { + return zapcore.NewCore( + zapcore.NewJSONEncoder(zaplog.EncoderConfig), + zapcore.AddSync(logRotate), + zaplog.Level, + ) + }), + ) + if err != nil { + log.Fatal("[gbt]", err.Error()) + return nil, nil, err + } + return l, logRotate, nil +} + +func GetCoin(config_file string) (string, string) { + var config CoinConfig + data, err := ioutil.ReadFile(config_file) + if err != nil { + panic(err.Error()) + } + if err = json.Unmarshal(data, &config); err != nil { + panic(err.Error()) + } + + return config.Coin, config.Pprof +} + +func confirmXPubSubscriptions(pub *goczmq.Channeler, count int) { + for i := 0; i < count; i++ { + select { + case <-pub.RecvChan: + case <-time.After(time.Second * 2): + log.Println("confirmXPubSubscriptions, timeout") + } + } +} + +func InitZmqPub(pub_host string) *goczmq.Sock { + pub_ch, err := goczmq.NewXPub(pub_host) + if err != nil { + log.Fatal("[server]", zap.String("NewXPub", "zmq pub create failed!")) + } + return pub_ch +} + +func InitZmqSub(sub_to string, topic string) *goczmq.Sock { + + sub_ch, err := goczmq.NewSub(sub_to, topic) + if err != nil { + log.Fatal("[server]", zap.String("NewSub", "zmq sub connect failed!")) + } + return sub_ch + +} + +func InitZmqPush(sub_to string) *goczmq.Sock { + push_ch, err := goczmq.NewPush(sub_to) + if err != nil { + log.Fatal("[server]", zap.String("NewPushChanneler", "zmq push connect failed!")) + } + //push_ch.Bind(sub_to) + + return push_ch +} + +func InitZmqPull(sub_to string) *goczmq.Sock { + pull_ch, err := goczmq.NewPull(sub_to) + if err != nil { + log.Fatal("[server]", zap.String("InitZmqPull", "zmq pull connect failed! "+err.Error())) + } + + return pull_ch +} + +func Int32ToString(n uint32) string { + buf := [11]byte{} + pos := len(buf) + i := int64(n) + signed := i < 0 + if signed { + i = -i + } + for { + pos-- + buf[pos], i = '0'+byte(i%10), i/10 + if i == 0 { + if signed { + pos-- + buf[pos] = '-' + } + return string(buf[pos:]) + } + } +} + +func ByteToUint32(bytes []byte) uint32 { + return binary.LittleEndian.Uint32(bytes) +} + +func Reverse_string(instr string) string { + var outstr string = "" + for i := 0; i < len(instr)/2; i++ { + outstr = outstr + instr[len(instr)-i*2-2:len(instr)-i*2] + } + return outstr +} + +// CompactToBig converts a compact representation of a whole number N to an +// unsigned 32-bit number. The representation is similar to IEEE754 floating +// point numbers. +// +// Like IEEE754 floating point, there are three basic components: the sign, +// the exponent, and the mantissa. They are broken out as follows: +// +// - the most significant 8 bits represent the unsigned base 256 exponent +// - bit 23 (the 24th bit) represents the sign bit +// - the least significant 23 bits represent the mantissa +// +// ------------------------------------------------- +// | Exponent | Sign | Mantissa | +// ------------------------------------------------- +// | 8 bits [31-24] | 1 bit [23] | 23 bits [22-00] | +// ------------------------------------------------- +// +// The formula to calculate N is: +// +// N = (-1^sign) * mantissa * 256^(exponent-3) +// +// This compact form is only used in bitcoin to encode unsigned 256-bit numbers +// which represent difficulty targets, thus there really is not a need for a +// sign bit, but it is implemented here to stay consistent with bitcoind. +func CompactToBig(compact uint32) *big.Int { + // Extract the mantissa, sign bit, and exponent. + mantissa := compact & 0x007fffff + isNegative := compact&0x00800000 != 0 + exponent := uint(compact >> 24) + + // Since the base for the exponent is 256, the exponent can be treated + // as the number of bytes to represent the full 256-bit number. So, + // treat the exponent as the number of bytes and shift the mantissa + // right or left accordingly. This is equivalent to: + // N = mantissa * 256^(exponent-3) + var bn *big.Int + if exponent <= 3 { + mantissa >>= 8 * (3 - exponent) + bn = big.NewInt(int64(mantissa)) + } else { + bn = big.NewInt(int64(mantissa)) + bn.Lsh(bn, 8*(exponent-3)) + } + + // Make it negative if the sign bit is set. + if isNegative { + bn = bn.Neg(bn) + } + + return bn +} + +const truediffone float64 = 26959535291011309493156476344723991336010898738574164086137773096960.0 +const bits192 float64 = 6277101735386680763835789423207666416102355444464034512896.0 +const bits128 float64 = 340282366920938463463374607431768211456.0 +const bits64 float64 = 18446744073709551616.0 + +func target2float(target []byte) float64 { + var b64 float64 = float64(binary.LittleEndian.Uint64(target[24:32])) * bits192 + b64 += (float64(binary.LittleEndian.Uint64(target[16:24])) * bits128) + b64 += (float64(binary.LittleEndian.Uint64(target[8:16])) * bits64) + b64 += (float64(binary.LittleEndian.Uint64(target[0:8]))) + return b64 +} + +func Target2Diff(target []byte) float64 { + //var f64 float64 = truediffone + //max, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + max, _ := new(big.Int).SetString("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + maxf, _ := new(big.Float).SetString(max.String()) + f64, _ := maxf.Float64() + var fcut64 float64 = target2float(target) + //log.Println("diff", f64, fcut64, f64/fcut64) + return f64 / fcut64 +} + +func MoneroTarget2Diff(target []byte) float64 { + //var f64 float64 = truediffone + // max, _ := new(big.Int).SetString("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + max, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + maxf, _ := new(big.Float).SetString(max.String()) + f64, _ := maxf.Float64() + var fcut64 float64 = target2float(target) + //log.Println("diff", f64, fcut64, f64/fcut64) + return f64 / fcut64 +} + +func DiffToTarget(diff float64 /*, powLimit *big.Int*/) (*big.Int, error) { + if diff <= 0 { + return nil, fmt.Errorf("invalid pool difficulty %v (0 or less than "+ + "zero passed)", diff) + } + + // Round down in the case of a non-integer diff since we only support + // ints (unless diff < 1 since we don't allow 0).. + if diff <= 1 { + diff = 1 + } else { + diff = math.Floor(diff) + } + divisor := new(big.Int).SetInt64(int64(diff)) + //max, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + max, _ := new(big.Int).SetString("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + target := new(big.Int) + //log.Println("target calc", hex.EncodeToString(max.Bytes()), hex.EncodeToString(divisor.Bytes())) + target.Div(max, divisor) + + return target, nil +} + +func MoneroDiffToTarget(diff float64 /*, powLimit *big.Int*/) (*big.Int, error) { + if diff <= 0 { + return nil, fmt.Errorf("invalid pool difficulty %v (0 or less than "+ + "zero passed)", diff) + } + + // Round down in the case of a non-integer diff since we only support + // ints (unless diff < 1 since we don't allow 0).. + if diff <= 1 { + diff = 1 + } else { + diff = math.Floor(diff) + } + divisor := new(big.Int).SetInt64(int64(diff)) + // max, _ := new(big.Int).SetString("00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + max, _ := new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16) + target := new(big.Int) + //log.Println("target calc", hex.EncodeToString(max.Bytes()), hex.EncodeToString(divisor.Bytes())) + target.Div(max, divisor) + + return target, nil +} + +func Convert_big_endian(src []byte) []byte { + var dst []byte = make([]byte, 32) + for i := 0; i < 8; i++ { + dst[0+4*i] = src[3+4*i] + dst[1+4*i] = src[2+4*i] + dst[2+4*i] = src[1+4*i] + dst[3+4*i] = src[0+4*i] + } + return dst +} + +func ReverseS(s string) (string, error) { + a := strings.Split(s, "") + sRev := "" + if len(a)%2 != 0 { + return "", fmt.Errorf("Incorrect input length") + } + for i := 0; i < len(a); i += 2 { + tmp := []string{a[i], a[i+1], sRev} + sRev = strings.Join(tmp, "") + } + return sRev, nil +} + +func Reverse(src []byte) []byte { + dst := make([]byte, len(src)) + for i := len(src); i > 0; i-- { + dst[len(src)-i] = src[i-1] + } + return dst +} + +func Uint32ToByte(targetu uint32) []byte { + bytes := make([]byte, 4) + binary.LittleEndian.PutUint32(bytes, targetu) + return bytes +} + +func Uint32ToByteBig(targetu uint32) []byte { + bytes := make([]byte, 4) + binary.BigEndian.PutUint32(bytes, targetu) + return bytes +} + +func ExecShellCmd(s string) (string, error) { + cmd := exec.Command("/bin/bash", "-c", s) + var out bytes.Buffer + cmd.Stdout = &out + err := cmd.Run() + if err != nil { + fmt.Println(err) + } + //fmt.Println(out.String(), s) + return out.String(), err +}