BTC RPC节点部署
October 22nd, 2022

RPC节点参与网络的同步,主要用于查询区块链数据,广播交易等作用;不会参与共识,挖矿。

阅读者建议

  • 有一定的linux基础

  • 熟悉docker

安装前置条件

  • linux系统

  • 机器上有docker服务

部署脚本

Dockerfile

FROM ubuntu:20.04

ARG VERSION=22.0

RUN apt-get update \
  && apt-get install -y net-tools curl \
  && curl -o /tmp/bitcoin.tar.gz https://bitcoincore.org/bin/bitcoin-core-${VERSION}/bitcoin-${VERSION}-x86_64-linux-gnu.tar.gz \
  && tar -zxvf /tmp/bitcoin.tar.gz -C /opt \
  && mv /opt/bitcoin-* /opt/bitcoin \
  && ln -s /opt/bitcoin/bin/* /usr/local/bin \
  && rm -f /tmp/bitcoin.tar.gz

WORKDIR /btc

EXPOSE 8332

ENTRYPOINT ["sh", "-c", "bitcoind -datadir=/btc -rpcbind=0.0.0.0 -rpcallowip=0.0.0.0/0 -txindex -rpcworkqueue=1000 -rpcuser=$RPC_USER -rpcpassword=$RPC_PWD"]

run.sh 脚本

#!/bin/bash

# 如果需要升级版本,修改这里的版本号后,执行一下run.sh脚本即可。
VERSION=22.0

docker build --build-arg VERSION=$VERSION -t btc:$VERSION .
docker stop btc
docker rm btc
docker run -d --name btc -p 8332:8332 -v /data/btc:/btc -e RPC_USER="test" -e RPC_PWD="test" --restart=always btc:$VERSION

对run.sh赋予执行权限,运行脚本

查看日志

docker logs -f --tail 20 btc
节点日志,经过一段时间,追赶上最新区块
节点日志,经过一段时间,追赶上最新区块

RPC接口

常用方法:

  • getblockchaininfo 获取最新区块

  • getblockhash 获取区块高度hash值

  • getblock 获取区块详情

  • getrawtransaction 获取交易详情

参考文档: BTC官方RPC接口

获取最新区块高度

curl -X POST -u test:test -d '{"jsonrpc": "2.0", "method": 
"getblockchaininfo", "params": [], "id": 1}' http://localhost:8332
{
  "result": {
    "chain": "main",
    "blocks": 759822,
    "headers": 759822,
    "bestblockhash": "0000000000000000000096b2e9a0db174eeb7a4c15e8a38398593f36032cfb09",
    "difficulty": 35610794164371.65,
    "time": 1666441676,
    "mediantime": 1666438889,
    "verificationprogress": 0.9999988460882687,
    "initialblockdownload": false,
    "chainwork": "000000000000000000000000000000000000000037b5d76943db7b147d7b83e6",
    "size_on_disk": 492851010520,
    "pruned": false,
    "warnings": ""
  },
  "error": null,
  "id": 1
}
# "blocks": 759822 此字段为当前区块高度

获取区块高度的hash值

curl -X POST -u test:test -d '{"jsonrpc": "2.0", "method": "getblockhash", "params": [759822], "id": 1}' http://localhost:8332 
{
  "result": "0000000000000000000096b2e9a0db174eeb7a4c15e8a38398593f36032cfb09",
  "error": null,
  "id": 1
}

其余接口建议大家自己去尝试

题外话

安全: RPC节点主要会被Wallet, Dapp, Cex等应用使用。自建RPC节点使用起来也会更安全,放心,不用担心你的请求会被他人拦截导致私密信息的泄漏。

地址: 类BTC,ETH的地址都是使用椭圆曲线算法生成,支持离线生成。

离线生成地址Python代码样例

import ecdsa
import base58
import hashlib
import binascii

class Wallet:
    def __init__(self, network='mainnet'):
        # 版本前缀
        self.__pubkey_version_byte = '00' if network == 'mainnet' else '6F'
        self.__wif_version_byte = '80' if network == 'mainnet' else 'ef'

    @property
    def pubkey_version_byte(self):
        return self.__pubkey_version_byte

    @pubkey_version_byte.setter
    def pubkey_version_byte(self, v):
        if isinstance(v, str):
            raise ValueError
        self.__pubkey_version_byte = v
    
    @property
    def wif_version_byte(self):
        return self.__wif_version_byte
    
    @wif_version_byte.setter
    def wif_version_byte(self, v):
        if isinstance(v, str):
            raise ValueError
        self.__wif_version_byte = v

    def __generate_privkey(self):
        privkey = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
        return privkey

    def get_pubkey(self, compress=False, privkey=None):
        if not privkey:
            privkey = self.__generate_privkey()
        # 是否压缩,压缩格式的公钥前缀是0x02或0x03,不压缩格式的公钥前缀是0x04
        s = '02' if compress else '04'
        pubkey = s + privkey.get_verifying_key().to_string().hex()
        return pubkey

    def get_address(self, pubkey):
        """根据公钥获取地址"""
        # 1.处理传入公钥格式
        sha256Key = hashlib.sha256(binascii.unhexlify(pubkey)).hexdigest()
        ridemp160FromHash256 = hashlib.new('ripemd160', binascii.unhexlify(pubkey))
        # 2.将 00 作为网络字节添加ripemd160公钥
        prepend_network_byte = self.__pubkey_version_byte + ridemp160FromHash256.hexdigest()
        # 3.将双重 SHA256 应用于prepend_network_byte以校验和
        hash = prepend_network_byte
        for x in range(1,3):
            hash = hashlib.sha256(binascii.unhexlify(hash)).hexdigest()
        checksum = hash[:8]
        # 4.附加值
        append_checksum = prepend_network_byte + checksum
        # 5.base58编码
        address = base58.b58encode(binascii.unhexlify(append_checksum))
        return address.decode('utf8')

    def generate(self):
        """生成地址"""
        privkey = self.__generate_privkey()
        pubkey = self.get_pubkey(privkey)
        address = self.get_address(pubkey)
        self.privkey = privkey.to_string().hex()
        self.pubkey = pubkey
        self.address = address
        return address

    def privkey_to_wif(self, privkey):
        """私钥格式转钱包导入格式"""
        prepend_network_byte = self.__wif_version_byte + privkey
        hash = prepend_network_byte
        for x in range(1,3):
            hash = hashlib.sha256(binascii.unhexlify(hash)).hexdigest()
        checksum = hash[:8]
        append_checksum = prepend_network_byte + checksum
        privkey = base58.b58encode(binascii.unhexlify(append_checksum))
        return privkey.decode('utf8')

if __name__ == '__main__':
    wallet = Wallet()
    wallet.generate()
    print(wallet.address, wallet.privkey)
Subscribe to junjie9021.eth
Receive the latest updates directly to your inbox.
Nft graphic
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.
More from junjie9021.eth

Skeleton

Skeleton

Skeleton