Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 749c7ee3ce | |||
| c668992623 | |||
| 7428b5849f | |||
| e88c5865e6 | |||
|
|
89270dadcd | ||
|
|
51d7a66c56 | ||
|
|
e10f3e5b37 | ||
|
|
b18c672d60 |
@@ -9,7 +9,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
DOCKER_BUILDKIT: "1"
|
DOCKER_BUILDKIT: "1"
|
||||||
PRODUCT_NAME: "xxxigcc-proxy"
|
PRODUCT_NAME: "xxxigcc-proxy"
|
||||||
PACKAGE_VERSION: "3.4.6-xg1"
|
PACKAGE_VERSION: "3.4.6-xg2"
|
||||||
BUILDX_NO_DEFAULT_ATTESTATIONS: "1"
|
BUILDX_NO_DEFAULT_ATTESTATIONS: "1"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -134,40 +134,39 @@ jobs:
|
|||||||
}
|
}
|
||||||
done
|
done
|
||||||
|
|
||||||
# 上传 Debian 包到 Debian Package Registry
|
# 上传 Debian 包到 Debian Package Registry (支持多个发行版)
|
||||||
echo ""
|
echo ""
|
||||||
echo "📦 上传 Debian 包到 Debian Package Registry..."
|
echo "📦 上传 Debian 包到 Debian Package Registry..."
|
||||||
for file in *.deb; do
|
for file in *.deb; do
|
||||||
[ ! -f "$file" ] && continue
|
[ ! -f "$file" ] && continue
|
||||||
echo " ⬆️ $file"
|
|
||||||
|
# 上传到 bookworm (Debian 12)
|
||||||
|
echo " ⬆️ $file → bookworm"
|
||||||
curl -fsSL -X PUT \
|
curl -fsSL -X PUT \
|
||||||
-H "Authorization: token ${TOKEN}" \
|
-H "Authorization: token ${TOKEN}" \
|
||||||
--upload-file "$file" \
|
--upload-file "$file" \
|
||||||
"https://${REGISTRY}/api/packages/${OWNER}/debian/pool/bookworm/main/upload" || {
|
"https://${REGISTRY}/api/packages/${OWNER}/debian/pool/bookworm/main/upload" || {
|
||||||
echo "❌ Debian 包上传失败: $file"
|
echo "❌ Debian 包上传失败: $file (bookworm)"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# 上传到 trixie (Debian 13)
|
||||||
|
echo " ⬆️ $file → trixie"
|
||||||
|
curl -fsSL -X PUT \
|
||||||
|
-H "Authorization: token ${TOKEN}" \
|
||||||
|
--upload-file "$file" \
|
||||||
|
"https://${REGISTRY}/api/packages/${OWNER}/debian/pool/trixie/main/upload" || {
|
||||||
|
echo "❌ Debian 包上传失败: $file (trixie)"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
done
|
done
|
||||||
|
|
||||||
# 生成 Release 描述(包含 Package Registry 和 Release 附件两种下载方式)
|
# 生成 Release JSON payload
|
||||||
echo ""
|
echo ""
|
||||||
echo "📝 生成 Release 描述..."
|
echo "📝 生成 Release..."
|
||||||
BODY="## Release ${TAG}\n\n"
|
|
||||||
BODY="${BODY}### 📥 下载方式\n\n"
|
export REGISTRY OWNER TAG
|
||||||
BODY="${BODY}#### 方式 1: 直接下载(推荐)\n\n"
|
RELEASE_DATA=$(python3 -c 'import json,glob,os;r=os.environ["REGISTRY"];o=os.environ["OWNER"];p=os.environ["PRODUCT_NAME"];t=os.environ["TAG"];b=["## Release "+t,"","### 📥 下载方式","","#### 方式 1: 直接下载(推荐)","","点击下面 **Assets** 部分的文件名直接下载。","","#### 方式 2: Generic Package Registry",""]+[f"- [`{f}`](https://{r}/api/packages/{o}/generic/{p}/{t}/{f})" for f in sorted(glob.glob("*.tar.gz"))]+["","#### 方式 3: Debian Repository","","**Debian 12 (bookworm):**","","```bash","# Download GPG key",f"sudo curl https://{r}/api/packages/{o}/debian/repository.key -o /etc/apt/keyrings/gitea-{o}.asc","","# Add repository",f"echo \"deb [signed-by=/etc/apt/keyrings/gitea-{o}.asc] https://{r}/api/packages/{o}/debian bookworm main\" | sudo tee -a /etc/apt/sources.list.d/{o}.list","","# Update and install","sudo apt-get update","sudo apt-get install xxxigcc-proxy","```","","**Debian 13 (trixie):**","","```bash","# Download GPG key",f"sudo curl https://{r}/api/packages/{o}/debian/repository.key -o /etc/apt/keyrings/gitea-{o}.asc","","# Add repository",f"echo \"deb [signed-by=/etc/apt/keyrings/gitea-{o}.asc] https://{r}/api/packages/{o}/debian trixie main\" | sudo tee -a /etc/apt/sources.list.d/{o}.list","","# Update and install","sudo apt-get update","sudo apt-get install xxxigcc-proxy","```"];print(json.dumps({"tag_name":t,"name":f"Release {t}","body":"\n".join(b),"draft":False,"prerelease":False}))')
|
||||||
BODY="${BODY}点击下面 **Assets** 部分的文件名直接下载。\n\n"
|
|
||||||
BODY="${BODY}#### 方式 2: Generic Package Registry\n\n"
|
|
||||||
for file in *.tar.gz; do
|
|
||||||
[ -f "$file" ] && BODY="${BODY}- [\`${file}\`](https://${REGISTRY}/api/packages/${OWNER}/generic/${PRODUCT_NAME}/${TAG}/${file})\n"
|
|
||||||
done
|
|
||||||
BODY="${BODY}\n#### 方式 3: Debian Repository\n\n"
|
|
||||||
BODY="${BODY}\`\`\`bash\n"
|
|
||||||
BODY="${BODY}# Add repository\n"
|
|
||||||
BODY="${BODY}echo \"deb https://${REGISTRY}/api/packages/${OWNER}/debian bookworm main\" | sudo tee /etc/apt/sources.list.d/xxxigcc-proxy.list\n\n"
|
|
||||||
BODY="${BODY}# Update and install\n"
|
|
||||||
BODY="${BODY}sudo apt-get update\n"
|
|
||||||
BODY="${BODY}sudo apt-get install xxxigcc-proxy\n"
|
|
||||||
BODY="${BODY}\`\`\`\n"
|
|
||||||
|
|
||||||
# 创建 Release
|
# 创建 Release
|
||||||
echo ""
|
echo ""
|
||||||
@@ -176,16 +175,7 @@ jobs:
|
|||||||
-H "Authorization: token ${TOKEN}" \
|
-H "Authorization: token ${TOKEN}" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
"https://${REGISTRY}/api/v1/repos/${{ gitea.repository }}/releases" \
|
"https://${REGISTRY}/api/v1/repos/${{ gitea.repository }}/releases" \
|
||||||
-d @- << EOF
|
-d "${RELEASE_DATA}")
|
||||||
{
|
|
||||||
"tag_name": "${TAG}",
|
|
||||||
"name": "Release ${TAG}",
|
|
||||||
"body": "${BODY}",
|
|
||||||
"draft": false,
|
|
||||||
"prerelease": false
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
)
|
|
||||||
|
|
||||||
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||||
RESPONSE_BODY=$(echo "$RESPONSE" | head -n-1)
|
RESPONSE_BODY=$(echo "$RESPONSE" | head -n-1)
|
||||||
@@ -226,3 +216,6 @@ jobs:
|
|||||||
echo ""
|
echo ""
|
||||||
echo "✅ Release 创建完成!"
|
echo "✅ Release 创建完成!"
|
||||||
echo "🔗 访问: https://${REGISTRY}/${{ gitea.repository }}/releases/tag/${TAG}"
|
echo "🔗 访问: https://${REGISTRY}/${{ gitea.repository }}/releases/tag/${TAG}"
|
||||||
|
|
||||||
|
# 清理临时文件
|
||||||
|
rm -f release_body.md
|
||||||
|
|||||||
106
README.md
Normal file
106
README.md
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
# XXXigCC Proxy
|
||||||
|
|
||||||
|
> 禁用捐赠功能的 XMRigCC Proxy 修改版本。
|
||||||
|
|
||||||
|
[](LICENSE)
|
||||||
|
[](.gitea/workflows/ci.yaml)
|
||||||
|
|
||||||
|
## 🎯 主要特性
|
||||||
|
|
||||||
|
- 🚫 **零捐赠**:捐赠等级设为 0,所有捐赠端点已禁用
|
||||||
|
- 🏗️ **多架构**:原生支持 AMD64 和 ARM64 架构
|
||||||
|
- 📦 **多种格式**:提供二进制包 (.tar.gz) 和 Debian 软件包 (.deb)
|
||||||
|
- 🐧 **多发行版**:支持 Ubuntu 和 Alpine Linux
|
||||||
|
- 🔄 **自动更新**:可通过 Debian 仓库安装 (bookworm/trixie)
|
||||||
|
|
||||||
|
## 🚀 快速开始
|
||||||
|
|
||||||
|
### Debian/Ubuntu(推荐)
|
||||||
|
|
||||||
|
**Debian 12 (bookworm):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo curl https://gitea.bcde.io/api/packages/wangdefa/debian/repository.key -o /etc/apt/keyrings/gitea-wangdefa.asc
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/gitea-wangdefa.asc] https://gitea.bcde.io/api/packages/wangdefa/debian bookworm main" | sudo tee -a /etc/apt/sources.list.d/wangdefa.list
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install xxxigcc-proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
**Debian 13 (trixie):**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo curl https://gitea.bcde.io/api/packages/wangdefa/debian/repository.key -o /etc/apt/keyrings/gitea-wangdefa.asc
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/gitea-wangdefa.asc] https://gitea.bcde.io/api/packages/wangdefa/debian trixie main" | sudo tee -a /etc/apt/sources.list.d/wangdefa.list
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install xxxigcc-proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
### 二进制下载
|
||||||
|
|
||||||
|
从 [Releases](https://gitea.bcde.io/wangdefa/xxxigcc-proxy/releases) 下载:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 下载并解压
|
||||||
|
wget https://gitea.bcde.io/api/packages/wangdefa/generic/xxxigcc-proxy/3.4.6-xg1/xxxigcc-proxy-amd64-ubuntu-3.4.6-xg1.tar.gz
|
||||||
|
tar -xzf xxxigcc-proxy-amd64-ubuntu-3.4.6-xg1.tar.gz
|
||||||
|
|
||||||
|
# 运行
|
||||||
|
./xxxigcc-proxy --config=config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📋 基本使用
|
||||||
|
|
||||||
|
通过 Debian 软件包安装后:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 编辑配置文件
|
||||||
|
sudo nano /etc/xxxigcc-proxy/config.json
|
||||||
|
|
||||||
|
# 重启服务
|
||||||
|
sudo systemctl restart xxxigcc-proxy
|
||||||
|
|
||||||
|
# 查看状态
|
||||||
|
sudo systemctl status xxxigcc-proxy
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
sudo journalctl -u xxxigcc-proxy -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## ⚙️ 配置说明
|
||||||
|
|
||||||
|
默认配置文件位置:
|
||||||
|
- Debian 软件包:`/etc/xxxigcc-proxy/config.json`
|
||||||
|
- 二进制版本:`./config.json`(与程序同目录)
|
||||||
|
|
||||||
|
主要配置选项:
|
||||||
|
- `bind`:监听地址和端口(默认:`0.0.0.0:3333`)
|
||||||
|
- `pools`:上游矿池连接配置
|
||||||
|
- `access-log-file`:访问日志文件路径
|
||||||
|
- `log-file`:常规日志文件路径
|
||||||
|
|
||||||
|
## 🔄 修改内容
|
||||||
|
|
||||||
|
本项目基于 [Bendr0id/XMRigCC Proxy](https://github.com/Bendr0id/XMRigCC-Proxy) 进行以下修改:
|
||||||
|
|
||||||
|
1. **禁用捐赠**:`kDefaultDonateLevel` 设为 0
|
||||||
|
2. **捐赠端点**:重定向到本地 (127.0.0.1)
|
||||||
|
3. **详细日志**:默认启用详细日志模式
|
||||||
|
4. **项目重命名**:"xmrigcc" → "xxxigcc"
|
||||||
|
|
||||||
|
所有修改通过 [init.sh](init.sh) 在构建过程中自动应用。
|
||||||
|
|
||||||
|
## 📝 许可证
|
||||||
|
|
||||||
|
本项目基于 GPL-3.0 许可证开源。
|
||||||
|
|
||||||
|
- 原始项目:[XMRigCC proxy](https://github.com/Bendr0id/XMRigcc-Proxy) (GPL-3.0)
|
||||||
|
- 修改内容:详见 [init.sh](init.sh)
|
||||||
|
|
||||||
|
## 🙏 致谢
|
||||||
|
|
||||||
|
- [XMRigCC Proxy](https://github.com/Bendr0id/XMRigcc-Proxy) - 原始项目
|
||||||
|
- [XMRig Proxy](https://github.com/xmrig/xmrig-proxy) - 核心挖矿引擎
|
||||||
|
|
||||||
|
## ⚠️ 免责声明
|
||||||
|
|
||||||
|
本软件仅供学习和研究使用。使用本软件进行挖矿活动请遵守当地法律法规。作者不对使用本软件造成的任何损失或法律问题负责。
|
||||||
2
debian/build-deb.sh
vendored
2
debian/build-deb.sh
vendored
@@ -4,7 +4,7 @@ set -e
|
|||||||
# 参数检查
|
# 参数检查
|
||||||
if [ $# -ne 3 ]; then
|
if [ $# -ne 3 ]; then
|
||||||
echo "Usage: $0 <ARCH> <VERSION> <TARGZ_FILE>"
|
echo "Usage: $0 <ARCH> <VERSION> <TARGZ_FILE>"
|
||||||
echo "Example: $0 amd64 3.4.6-xg1 xxxigcc-proxy-amd64-ubuntu-3.4.6-xg1.tar.gz"
|
echo "Example: $0 amd64 3.4.6-xg2 xxxigcc-proxy-amd64-ubuntu-3.4.6-xg2.tar.gz"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,9 @@ RUN git clone --recursive https://github.com/Bendr0id/xmrigcc-proxy.git && \
|
|||||||
|
|
||||||
WORKDIR /xxxigcc-proxy
|
WORKDIR /xxxigcc-proxy
|
||||||
|
|
||||||
|
RUN rm -rf ./src/base/tools/cryptonote/BlockTemplate.cpp
|
||||||
|
COPY ./templates/BlockTemplate.cpp ./src/base/tools/cryptonote/BlockTemplate.cpp
|
||||||
|
|
||||||
COPY ./init.sh ./init.sh
|
COPY ./init.sh ./init.sh
|
||||||
|
|
||||||
# 根据目标架构优化编译
|
# 根据目标架构优化编译
|
||||||
|
|||||||
@@ -31,6 +31,9 @@ RUN git clone --recursive https://github.com/Bendr0id/xmrigcc-proxy.git && \
|
|||||||
|
|
||||||
WORKDIR /xxxigcc-proxy
|
WORKDIR /xxxigcc-proxy
|
||||||
|
|
||||||
|
RUN rm -rf ./src/base/tools/cryptonote/BlockTemplate.cpp
|
||||||
|
COPY ./templates/BlockTemplate.cpp ./src/base/tools/cryptonote/BlockTemplate.cpp
|
||||||
|
|
||||||
COPY ./init.sh ./init.sh
|
COPY ./init.sh ./init.sh
|
||||||
|
|
||||||
# 根据目标架构优化编译
|
# 根据目标架构优化编译
|
||||||
|
|||||||
3
init.sh
3
init.sh
@@ -14,5 +14,8 @@ sed -i 's/"donate-level": 2/"donate-level": 0/' src/config.json
|
|||||||
sed -i 's/xmrigcc/xxxigcc/' src/version.h
|
sed -i 's/xmrigcc/xxxigcc/' src/version.h
|
||||||
sed -i 's/XMRigCC/XXXigCC/' src/version.h
|
sed -i 's/XMRigCC/XXXigCC/' src/version.h
|
||||||
|
|
||||||
|
# Add Tari Solo support information to APP_DESC for --version output
|
||||||
|
sed -i 's/\(#define APP_DESC .*\)"/\1 (with Tari Solo Mining Support)"/' src/version.h
|
||||||
|
|
||||||
# Modify the config.json to set verbose to true
|
# Modify the config.json to set verbose to true
|
||||||
sed -i 's/"verbose": false/"verbose": true/' src/config.json
|
sed -i 's/"verbose": false/"verbose": true/' src/config.json
|
||||||
406
templates/BlockTemplate.cpp
Normal file
406
templates/BlockTemplate.cpp
Normal file
@@ -0,0 +1,406 @@
|
|||||||
|
/* XMRig
|
||||||
|
* Copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
* Copyright (c) 2014-2021 The Monero Project
|
||||||
|
* Copyright (c) 2018-2023 SChernykh <https://github.com/SChernykh>
|
||||||
|
* Copyright (c) 2016-2023 XMRig <https://github.com/xmrig>, <support@xmrig.com>
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "base/tools/cryptonote/BlockTemplate.h"
|
||||||
|
#include "3rdparty/rapidjson/document.h"
|
||||||
|
#include "base/crypto/keccak.h"
|
||||||
|
#include "base/tools/cryptonote/BlobReader.h"
|
||||||
|
#include "base/tools/Cvt.h"
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::BlockTemplate::calculateMinerTxHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, uint8_t *hash)
|
||||||
|
{
|
||||||
|
uint8_t hashes[kHashSize * 3];
|
||||||
|
|
||||||
|
// Calculate 3 partial hashes
|
||||||
|
|
||||||
|
// 1. Prefix
|
||||||
|
keccak(prefix_begin, static_cast<int>(prefix_end - prefix_begin), hashes, kHashSize);
|
||||||
|
|
||||||
|
// 2. Base RCT, single 0 byte in miner tx
|
||||||
|
static const uint8_t known_second_hash[kHashSize] = {
|
||||||
|
188,54,120,158,122,30,40,20,54,70,66,41,130,143,129,125,102,18,247,180,119,214,101,145,255,150,169,224,100,188,201,138
|
||||||
|
};
|
||||||
|
memcpy(hashes + kHashSize, known_second_hash, kHashSize);
|
||||||
|
|
||||||
|
// 3. Prunable RCT, empty in miner tx
|
||||||
|
memset(hashes + kHashSize * 2, 0, kHashSize);
|
||||||
|
|
||||||
|
// Calculate miner transaction hash
|
||||||
|
keccak(hashes, sizeof(hashes), hash, kHashSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::BlockTemplate::calculateRootHash(const uint8_t *prefix_begin, const uint8_t *prefix_end, const Buffer &miner_tx_merkle_tree_branch, uint8_t *root_hash)
|
||||||
|
{
|
||||||
|
calculateMinerTxHash(prefix_begin, prefix_end, root_hash);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < miner_tx_merkle_tree_branch.size(); i += kHashSize) {
|
||||||
|
uint8_t h[kHashSize * 2];
|
||||||
|
|
||||||
|
memcpy(h, root_hash, kHashSize);
|
||||||
|
memcpy(h + kHashSize, miner_tx_merkle_tree_branch.data() + i, kHashSize);
|
||||||
|
|
||||||
|
keccak(h, kHashSize * 2, root_hash, kHashSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::BlockTemplate::calculateMerkleTreeHash()
|
||||||
|
{
|
||||||
|
m_minerTxMerkleTreeBranch.clear();
|
||||||
|
|
||||||
|
const uint64_t count = m_numHashes + 1;
|
||||||
|
const uint8_t *h = m_hashes.data();
|
||||||
|
|
||||||
|
if (count == 1) {
|
||||||
|
memcpy(m_rootHash, h, kHashSize);
|
||||||
|
}
|
||||||
|
else if (count == 2) {
|
||||||
|
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize, h + kHashSize * 2);
|
||||||
|
keccak(h, kHashSize * 2, m_rootHash, kHashSize);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t i = 0;
|
||||||
|
size_t j = 0;
|
||||||
|
size_t cnt = 0;
|
||||||
|
|
||||||
|
for (i = 0, cnt = 1; cnt <= count; ++i, cnt <<= 1) {}
|
||||||
|
|
||||||
|
cnt >>= 1;
|
||||||
|
|
||||||
|
m_minerTxMerkleTreeBranch.reserve(kHashSize * (i - 1));
|
||||||
|
|
||||||
|
Buffer ints(cnt * kHashSize);
|
||||||
|
memcpy(ints.data(), h, (cnt * 2 - count) * kHashSize);
|
||||||
|
|
||||||
|
for (i = cnt * 2 - count, j = cnt * 2 - count; j < cnt; i += 2, ++j) {
|
||||||
|
if (i == 0) {
|
||||||
|
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), h + kHashSize, h + kHashSize * 2);
|
||||||
|
}
|
||||||
|
keccak(h + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (cnt > 2) {
|
||||||
|
cnt >>= 1;
|
||||||
|
for (i = 0, j = 0; j < cnt; i += 2, ++j) {
|
||||||
|
if (i == 0) {
|
||||||
|
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize, ints.data() + kHashSize * 2);
|
||||||
|
}
|
||||||
|
keccak(ints.data() + i * kHashSize, kHashSize * 2, ints.data() + j * kHashSize, kHashSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_minerTxMerkleTreeBranch.insert(m_minerTxMerkleTreeBranch.end(), ints.data() + kHashSize, ints.data() + kHashSize * 2);
|
||||||
|
keccak(ints.data(), kHashSize * 2, m_rootHash, kHashSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::BlockTemplate::parse(const Buffer &blocktemplate, const Coin &coin, bool hashes)
|
||||||
|
{
|
||||||
|
if (blocktemplate.size() < kMinSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_blob = blocktemplate;
|
||||||
|
m_coin = coin;
|
||||||
|
bool rc = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
rc = parse(hashes);
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::BlockTemplate::parse(const char *blocktemplate, size_t size, const Coin &coin, bool hashes)
|
||||||
|
{
|
||||||
|
if (size < (kMinSize * 2) || !Cvt::fromHex(m_blob, blocktemplate, size)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_coin = coin;
|
||||||
|
bool rc = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
rc = parse(hashes);
|
||||||
|
} catch (...) {}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::BlockTemplate::parse(const rapidjson::Value &blocktemplate, const Coin &coin, bool hashes)
|
||||||
|
{
|
||||||
|
return blocktemplate.IsString() && parse(blocktemplate.GetString(), blocktemplate.GetStringLength(), coin, hashes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::BlockTemplate::parse(const String &blocktemplate, const Coin &coin, bool hashes)
|
||||||
|
{
|
||||||
|
return parse(blocktemplate.data(), blocktemplate.size(), coin, hashes);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void xmrig::BlockTemplate::generateHashingBlob(Buffer &out) const
|
||||||
|
{
|
||||||
|
out.clear();
|
||||||
|
out.reserve(offset(MINER_TX_PREFIX_OFFSET) + kHashSize + 3);
|
||||||
|
|
||||||
|
out.assign(m_blob.begin(), m_blob.begin() + offset(MINER_TX_PREFIX_OFFSET));
|
||||||
|
out.insert(out.end(), m_rootHash, m_rootHash + kHashSize);
|
||||||
|
|
||||||
|
uint64_t k = m_numHashes + 1;
|
||||||
|
while (k >= 0x80) {
|
||||||
|
out.emplace_back((static_cast<uint8_t>(k) & 0x7F) | 0x80);
|
||||||
|
k >>= 7;
|
||||||
|
}
|
||||||
|
out.emplace_back(static_cast<uint8_t>(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool xmrig::BlockTemplate::parse(bool hashes)
|
||||||
|
{
|
||||||
|
// Detect Tari solo mining format (76 bytes)
|
||||||
|
// Format: 3 bytes header + 32 bytes mining_hash + 8 bytes nonce + 33 bytes pow
|
||||||
|
if (m_blob.size() == 76) {
|
||||||
|
// Tari solo mining format - use fixed-size parsing (no varint)
|
||||||
|
BlobReader<false> ar(m_blob.data(), m_blob.size());
|
||||||
|
|
||||||
|
// Skip 3-byte header (major_version, minor_version, timestamp - all 0 for Tari)
|
||||||
|
ar.skip(3);
|
||||||
|
|
||||||
|
// Skip 32-byte mining_hash
|
||||||
|
ar.skip(32);
|
||||||
|
|
||||||
|
// Nonce is at offset 35 (3 + 32)
|
||||||
|
setOffset(NONCE_OFFSET, 35);
|
||||||
|
ar.skip(8); // Skip nonce (8 bytes, big-endian)
|
||||||
|
|
||||||
|
// Skip 33-byte PoW data
|
||||||
|
ar.skip(33);
|
||||||
|
|
||||||
|
// For Tari, we don't need to parse miner tx or other Monero-specific fields
|
||||||
|
// Just accept the template and let XMRig modify the nonce
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Original Monero varint parsing for non-Tari formats
|
||||||
|
BlobReader<true> ar(m_blob.data(), m_blob.size());
|
||||||
|
|
||||||
|
// Block header
|
||||||
|
ar(m_version.first);
|
||||||
|
ar(m_version.second);
|
||||||
|
ar(m_timestamp);
|
||||||
|
ar(m_prevId, kHashSize);
|
||||||
|
|
||||||
|
setOffset(NONCE_OFFSET, ar.index());
|
||||||
|
ar.skip(kNonceSize);
|
||||||
|
|
||||||
|
// Wownero block template has miner signature starting from version 18
|
||||||
|
if (m_coin == Coin::WOWNERO && majorVersion() >= 18) {
|
||||||
|
ar(m_minerSignature, kSignatureSize);
|
||||||
|
ar(m_vote);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_coin == Coin::ZEPHYR) {
|
||||||
|
uint8_t pricing_record[120];
|
||||||
|
ar(pricing_record);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Miner transaction begin
|
||||||
|
// Prefix begin
|
||||||
|
setOffset(MINER_TX_PREFIX_OFFSET, ar.index());
|
||||||
|
|
||||||
|
ar(m_txVersion);
|
||||||
|
|
||||||
|
if (m_coin != Coin::TOWNFORGE) {
|
||||||
|
ar(m_unlockTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
ar(m_numInputs);
|
||||||
|
|
||||||
|
// must be 1 input
|
||||||
|
if (m_numInputs != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ar(m_inputType);
|
||||||
|
|
||||||
|
// input type must be txin_gen (0xFF)
|
||||||
|
if (m_inputType != 0xFF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ar(m_height);
|
||||||
|
ar(m_numOutputs);
|
||||||
|
|
||||||
|
if (m_coin == Coin::ZEPHYR) {
|
||||||
|
if (m_numOutputs < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_numOutputs != 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ar(m_amount);
|
||||||
|
ar(m_outputType);
|
||||||
|
|
||||||
|
// output type must be txout_to_key (2) or txout_to_tagged_key (3)
|
||||||
|
if ((m_outputType != 2) && (m_outputType != 3)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setOffset(EPH_PUBLIC_KEY_OFFSET, ar.index());
|
||||||
|
|
||||||
|
ar(m_ephPublicKey, kKeySize);
|
||||||
|
|
||||||
|
if (m_coin == Coin::ZEPHYR) {
|
||||||
|
if (m_outputType != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t asset_type_len;
|
||||||
|
ar(asset_type_len);
|
||||||
|
ar.skip(asset_type_len);
|
||||||
|
ar(m_viewTag);
|
||||||
|
|
||||||
|
for (uint64_t k = 1; k < m_numOutputs; ++k) {
|
||||||
|
uint64_t amount2;
|
||||||
|
ar(amount2);
|
||||||
|
|
||||||
|
uint8_t output_type2;
|
||||||
|
ar(output_type2);
|
||||||
|
if (output_type2 != 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Span key2;
|
||||||
|
ar(key2, kKeySize);
|
||||||
|
|
||||||
|
ar(asset_type_len);
|
||||||
|
ar.skip(asset_type_len);
|
||||||
|
|
||||||
|
uint8_t view_tag2;
|
||||||
|
ar(view_tag2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_outputType == 3) {
|
||||||
|
ar(m_viewTag);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_coin == Coin::TOWNFORGE) {
|
||||||
|
ar(m_unlockTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
ar(m_extraSize);
|
||||||
|
|
||||||
|
setOffset(TX_EXTRA_OFFSET, ar.index());
|
||||||
|
|
||||||
|
BlobReader<true> ar_extra(blob(TX_EXTRA_OFFSET), m_extraSize);
|
||||||
|
ar.skip(m_extraSize);
|
||||||
|
|
||||||
|
bool pubkey_offset_first = true;
|
||||||
|
|
||||||
|
while (ar_extra.index() < m_extraSize) {
|
||||||
|
uint64_t extra_tag = 0;
|
||||||
|
uint64_t size = 0;
|
||||||
|
|
||||||
|
ar_extra(extra_tag);
|
||||||
|
|
||||||
|
switch (extra_tag) {
|
||||||
|
case 0x01: // TX_EXTRA_TAG_PUBKEY
|
||||||
|
if (pubkey_offset_first) {
|
||||||
|
pubkey_offset_first = false;
|
||||||
|
setOffset(TX_PUBKEY_OFFSET, offset(TX_EXTRA_OFFSET) + ar_extra.index());
|
||||||
|
}
|
||||||
|
ar_extra.skip(kKeySize);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x02: // TX_EXTRA_NONCE
|
||||||
|
ar_extra(size);
|
||||||
|
setOffset(TX_EXTRA_NONCE_OFFSET, offset(TX_EXTRA_OFFSET) + ar_extra.index());
|
||||||
|
ar_extra(m_txExtraNonce, size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x03: // TX_EXTRA_MERGE_MINING_TAG
|
||||||
|
ar_extra(size);
|
||||||
|
setOffset(TX_EXTRA_MERGE_MINING_TAG_OFFSET, offset(TX_EXTRA_OFFSET) + ar_extra.index());
|
||||||
|
ar_extra(m_txMergeMiningTag, size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false; // TODO(SChernykh): handle other tags
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_coin == Coin::ZEPHYR) {
|
||||||
|
uint64_t pricing_record_height, amount_burnt, amount_minted;
|
||||||
|
ar(pricing_record_height);
|
||||||
|
ar(amount_burnt);
|
||||||
|
ar(amount_minted);
|
||||||
|
}
|
||||||
|
|
||||||
|
setOffset(MINER_TX_PREFIX_END_OFFSET, ar.index());
|
||||||
|
// Prefix end
|
||||||
|
|
||||||
|
// RCT signatures (empty in miner transaction)
|
||||||
|
uint8_t vin_rct_type = 0;
|
||||||
|
ar(vin_rct_type);
|
||||||
|
|
||||||
|
// no way I'm parsing a full game update here
|
||||||
|
if (m_coin == Coin::TOWNFORGE && m_height % 720 == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// must be RCTTypeNull (0)
|
||||||
|
if (vin_rct_type != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t miner_tx_end = ar.index();
|
||||||
|
// Miner transaction end
|
||||||
|
|
||||||
|
// Miner transaction must have exactly 1 byte with value 0 after the prefix
|
||||||
|
if ((miner_tx_end != offset(MINER_TX_PREFIX_END_OFFSET) + 1) || (*blob(MINER_TX_PREFIX_END_OFFSET) != 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other transaction hashes
|
||||||
|
ar(m_numHashes);
|
||||||
|
|
||||||
|
if (hashes) {
|
||||||
|
m_hashes.resize((m_numHashes + 1) * kHashSize);
|
||||||
|
calculateMinerTxHash(blob(MINER_TX_PREFIX_OFFSET), blob(MINER_TX_PREFIX_END_OFFSET), m_hashes.data());
|
||||||
|
|
||||||
|
for (uint64_t i = 1; i <= m_numHashes; ++i) {
|
||||||
|
Span h;
|
||||||
|
ar(h, kHashSize);
|
||||||
|
memcpy(m_hashes.data() + i * kHashSize, h.data(), kHashSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
calculateMerkleTreeHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user