create git
This commit is contained in:
5
.gitignore
vendored
Normal file
5
.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
rel
|
||||
config
|
||||
*.json
|
||||
*.conf
|
||||
/*.go
|
||||
146
README.md
Normal file
146
README.md
Normal file
@@ -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/<coin>/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://<ip>:<port>`)。
|
||||
- 账户名与 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://<ip>:<pprof_port>/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 并注明授权条款。
|
||||
33
cmd/gbt/gbt.go
Normal file
33
cmd/gbt/gbt.go
Normal file
@@ -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)
|
||||
}
|
||||
41
cmd/server/server.go
Normal file
41
cmd/server/server.go
Normal file
@@ -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)
|
||||
}
|
||||
46
go.mod
Normal file
46
go.mod
Normal file
@@ -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
|
||||
)
|
||||
194
go.sum
Normal file
194
go.sum
Normal file
@@ -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=
|
||||
548
internal/cache/cache.go
vendored
Normal file
548
internal/cache/cache.go
vendored
Normal file
@@ -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
|
||||
}
|
||||
*/
|
||||
2996
internal/db/db.go
Normal file
2996
internal/db/db.go
Normal file
File diff suppressed because it is too large
Load Diff
85
internal/gbt/coin/coin.go
Normal file
85
internal/gbt/coin/coin.go
Normal file
@@ -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*/
|
||||
}
|
||||
198
internal/gbt/dbif/dbif.go
Normal file
198
internal/gbt/dbif/dbif.go
Normal file
@@ -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
|
||||
}*/
|
||||
300
internal/gbt/gbt.go
Normal file
300
internal/gbt/gbt.go
Normal file
@@ -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()
|
||||
}
|
||||
495
internal/gbt/monero/monore.go
Normal file
495
internal/gbt/monero/monore.go
Normal file
@@ -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
|
||||
}
|
||||
179
internal/gbt/monero/rpc/rpc.go
Normal file
179
internal/gbt/monero/rpc/rpc.go
Normal file
@@ -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
|
||||
}
|
||||
627
internal/gbt/nexa/nexa.go
Normal file
627
internal/gbt/nexa/nexa.go
Normal file
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
4609
internal/gbt/tari/proto/base_node.pb.go
Normal file
4609
internal/gbt/tari/proto/base_node.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
600
internal/gbt/tari/proto/base_node.proto
Normal file
600
internal/gbt/tari/proto/base_node.proto
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
1666
internal/gbt/tari/proto/base_node_grpc.pb.go
Normal file
1666
internal/gbt/tari/proto/base_node_grpc.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
142
internal/gbt/tari/proto/block.proto
Normal file
142
internal/gbt/tari/proto/block.proto
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
783
internal/gbt/tari/proto/block/block.pb.go
Normal file
783
internal/gbt/tari/proto/block/block.pb.go
Normal file
@@ -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
|
||||
}
|
||||
790
internal/gbt/tari/proto/net_work/network.pb.go
Normal file
790
internal/gbt/tari/proto/net_work/network.pb.go
Normal file
@@ -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
|
||||
}
|
||||
97
internal/gbt/tari/proto/network.proto
Normal file
97
internal/gbt/tari/proto/network.proto
Normal file
@@ -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;
|
||||
}
|
||||
61
internal/gbt/tari/proto/p2pool.proto
Normal file
61
internal/gbt/tari/proto/p2pool.proto
Normal file
@@ -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;
|
||||
}
|
||||
77
internal/gbt/tari/proto/sidechain_types.proto
Normal file
77
internal/gbt/tari/proto/sidechain_types.proto
Normal file
@@ -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;
|
||||
}
|
||||
727
internal/gbt/tari/proto/sidechain_types/sidechain_types.pb.go
Normal file
727
internal/gbt/tari/proto/sidechain_types/sidechain_types.pb.go
Normal file
@@ -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
|
||||
}
|
||||
188
internal/gbt/tari/proto/transaction.proto
Normal file
188
internal/gbt/tari/proto/transaction.proto
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
1012
internal/gbt/tari/proto/transaction/transaction.pb.go
Normal file
1012
internal/gbt/tari/proto/transaction/transaction.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
147
internal/gbt/tari/proto/types.proto
Normal file
147
internal/gbt/tari/proto/types.proto
Normal file
@@ -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<uint32, PowAlgorithmConstants> proof_of_work = 23;
|
||||
WeightParams transaction_weight = 24;
|
||||
Range input_version_range = 26;
|
||||
OutputsVersion output_version_range = 27;
|
||||
Range kernel_version_range = 28;
|
||||
repeated OutputType permitted_output_types = 29;
|
||||
uint64 epoch_length = 30;
|
||||
uint64 validator_node_registration_min_deposit_amount = 31;
|
||||
uint64 validator_node_registration_min_lock_height = 32;
|
||||
uint64 validator_node_registration_shuffle_interval_epoch = 33;
|
||||
repeated PermittedRangeProofs permitted_range_proof_types = 34;
|
||||
uint64 inflation_bips = 35;
|
||||
uint64 tail_epoch_length = 36;
|
||||
uint64 max_block_coinbase_count = 37;
|
||||
}
|
||||
1239
internal/gbt/tari/proto/types/types.pb.go
Normal file
1239
internal/gbt/tari/proto/types/types.pb.go
Normal file
File diff suppressed because it is too large
Load Diff
132
internal/gbt/tari/proto/validator_node.proto
Normal file
132
internal/gbt/tari/proto/validator_node.proto
Normal file
@@ -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;
|
||||
}
|
||||
1582
internal/gbt/tari/proto/wallet.proto
Normal file
1582
internal/gbt/tari/proto/wallet.proto
Normal file
File diff suppressed because it is too large
Load Diff
385
internal/gbt/tari/sha3x/sha3x.go
Normal file
385
internal/gbt/tari/sha3x/sha3x.go
Normal file
@@ -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
|
||||
}
|
||||
120
internal/gbt/tari/tari.go
Normal file
120
internal/gbt/tari/tari.go
Normal file
@@ -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
|
||||
}
|
||||
165
internal/msg/msg.go
Normal file
165
internal/msg/msg.go
Normal file
@@ -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"`
|
||||
}
|
||||
681
internal/server/coin/coin.go
Normal file
681
internal/server/coin/coin.go
Normal file
@@ -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()
|
||||
}
|
||||
}
|
||||
1224
internal/server/dbif/dbif.go
Normal file
1224
internal/server/dbif/dbif.go
Normal file
File diff suppressed because it is too large
Load Diff
170
internal/server/diff/diff.go
Normal file
170
internal/server/diff/diff.go
Normal file
@@ -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
|
||||
}
|
||||
14
internal/server/include/nexaapi.h
Normal file
14
internal/server/include/nexaapi.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef NEXAAPI_H
|
||||
#define NEXAAPI_H
|
||||
#include <stdbool.h>
|
||||
#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
|
||||
288
internal/server/include/randomx.h
Normal file
288
internal/server/include/randomx.h
Normal file
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
Copyright (c) 2018-2019, tevador <tevador@gmail.com>
|
||||
|
||||
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 <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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<randomx_flags>(static_cast<int>(a) | static_cast<int>(b));
|
||||
}
|
||||
inline CONSTEXPR randomx_flags operator &(randomx_flags a, randomx_flags b) {
|
||||
return static_cast<randomx_flags>(static_cast<int>(a) & static_cast<int>(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
|
||||
4
internal/server/include/sha3xapi.h
Normal file
4
internal/server/include/sha3xapi.h
Normal file
@@ -0,0 +1,4 @@
|
||||
#ifndef SHA3X_API_H
|
||||
#define SHA3X_API_H
|
||||
void sha3x_hash(unsigned char * out, unsigned char * in);
|
||||
#endif
|
||||
BIN
internal/server/lib/libnexa.so
Normal file
BIN
internal/server/lib/libnexa.so
Normal file
Binary file not shown.
BIN
internal/server/lib/libnexa12B.so
Normal file
BIN
internal/server/lib/libnexa12B.so
Normal file
Binary file not shown.
BIN
internal/server/lib/libnexa16B.so
Normal file
BIN
internal/server/lib/libnexa16B.so
Normal file
Binary file not shown.
BIN
internal/server/lib/librandomx.so
Normal file
BIN
internal/server/lib/librandomx.so
Normal file
Binary file not shown.
BIN
internal/server/lib/libsha3x.a
Normal file
BIN
internal/server/lib/libsha3x.a
Normal file
Binary file not shown.
117
internal/server/monero/hash_randomx.go
Normal file
117
internal/server/monero/hash_randomx.go
Normal file
@@ -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 <randomx.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
*/
|
||||
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
|
||||
}
|
||||
756
internal/server/monero/monero.go
Normal file
756
internal/server/monero/monero.go
Normal file
@@ -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
|
||||
}
|
||||
61
internal/server/nexa/hash_nexa.go
Normal file
61
internal/server/nexa/hash_nexa.go
Normal file
@@ -0,0 +1,61 @@
|
||||
// hash_nexa.go
|
||||
package nexa
|
||||
|
||||
/*
|
||||
#cgo CFLAGS : -I../include
|
||||
#cgo LDFLAGS: -L../lib -lnexa
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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
|
||||
}
|
||||
943
internal/server/nexa/nexa.go
Normal file
943
internal/server/nexa/nexa.go
Normal file
@@ -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
|
||||
}
|
||||
117
internal/server/randomxT/hash_randomx.go
Normal file
117
internal/server/randomxT/hash_randomx.go
Normal file
@@ -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 <randomx.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
*/
|
||||
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
|
||||
}
|
||||
761
internal/server/randomxT/randomxT.go
Normal file
761
internal/server/randomxT/randomxT.go
Normal file
@@ -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
|
||||
}
|
||||
1865
internal/server/server.go
Normal file
1865
internal/server/server.go
Normal file
File diff suppressed because it is too large
Load Diff
39
internal/server/sha3x/hash_sha3x.go
Normal file
39
internal/server/sha3x/hash_sha3x.go
Normal file
@@ -0,0 +1,39 @@
|
||||
// hash_sha3x.go
|
||||
package sha3x
|
||||
|
||||
/*
|
||||
#cgo CFLAGS : -I../include
|
||||
#cgo LDFLAGS: -L../lib -lsha3x
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#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
|
||||
}
|
||||
761
internal/server/sha3x/sha3x.go
Normal file
761
internal/server/sha3x/sha3x.go
Normal file
@@ -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
|
||||
}
|
||||
1296
internal/stratum/stratum.go
Normal file
1296
internal/stratum/stratum.go
Normal file
File diff suppressed because it is too large
Load Diff
367
internal/utility/utility.go
Normal file
367
internal/utility/utility.go
Normal file
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user