Base58Check Encode/Decode Destination 示例

本文提供了一个Base58Check编码和解码比特币目的地的示例,详细介绍了编码解码过程,并展示了使用CChainParams和CMainParams进行主网参数选择的测试程序及其输出结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Base58Check Encode/Decode Destination 示例

Bitcoin(0.16.0)编码/解码地址定义如下:

// 编码
std::string EncodeDestination(const CTxDestination& dest)
{
    return boost::apply_visitor(DestinationEncoder(Params()), dest);
}
// 解码
CTxDestination DecodeDestination(const std::string& str)
{
    return DecodeDestination(str, Params());
}
namespace
{
class DestinationEncoder : public boost::static_visitor<std::string>
{
private:
    const CChainParams& m_params;

public:
    DestinationEncoder(const CChainParams& params) : m_params(params) {}
	// P2PK
    std::string operator()(const CKeyID& id) const
    {
        std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
        data.insert(data.end(), id.begin(), id.end());
        return EncodeBase58Check(data);
    }
	// P2SH
    std::string operator()(const CScriptID& id) const
    {
        std::vector<unsigned char> data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
        data.insert(data.end(), id.begin(), id.end());
        return EncodeBase58Check(data);
    }

    std::string operator()(const WitnessV0KeyHash& id) const
    {
        std::vector<unsigned char> data = {0};
        ConvertBits<8, 5, true>(data, id.begin(), id.end());
        return bech32::Encode(m_params.Bech32HRP(), data);
    }

    std::string operator()(const WitnessV0ScriptHash& id) const
    {
        std::vector<unsigned char> data = {0};
        ConvertBits<8, 5, true>(data, id.begin(), id.end());
        return bech32::Encode(m_params.Bech32HRP(), data);
    }

    std::string operator()(const WitnessUnknown& id) const
    {
        if (id.version < 1 || id.version > 16 || id.length < 2 || id.length > 40) {
            return {};
        }
        std::vector<unsigned char> data = {(unsigned char)id.version};
        ConvertBits<8, 5, true>(data, id.program, id.program + id.length);
        return bech32::Encode(m_params.Bech32HRP(), data);
    }

    std::string operator()(const CNoDestination& no) const { return {}; }
};

CTxDestination DecodeDestination(const std::string& str, const CChainParams& params)
{
    std::vector<unsigned char> data;
    uint160 hash;
    if (DecodeBase58Check(str, data)) {
        // base58-encoded Bitcoin addresses.
        // Public-key-hash-addresses have version 0 (or 111 testnet).
        // The data vector contains RIPEMD160(SHA256(pubkey)), where pubkey is the serialized public key.
        const std::vector<unsigned char>& pubkey_prefix = params.Base58Prefix(CChainParams::PUBKEY_ADDRESS);
        if (data.size() == hash.size() + pubkey_prefix.size() && std::equal(pubkey_prefix.begin(), pubkey_prefix.end(), data.begin())) {
            std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin());
            return CKeyID(hash);
        }
        // Script-hash-addresses have version 5 (or 196 testnet).
        // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script.
        const std::vector<unsigned char>& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
        if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) {
            std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin());
            return CScriptID(hash);
        }
    }
    data.clear();
    auto bech = bech32::Decode(str);
    if (bech.second.size() > 0 && bech.first == params.Bech32HRP()) {
        // Bech32 decoding
        int version = bech.second[0]; // The first 5 bit symbol is the witness version (0-16)
        // The rest of the symbols are converted witness program bytes.
        if (ConvertBits<5, 8, false>(data, bech.second.begin() + 1, bech.second.end())) {
            if (version == 0) {
                {
                    WitnessV0KeyHash keyid;
                    if (data.size() == keyid.size()) {
                        std::copy(data.begin(), data.end(), keyid.begin());
                        return keyid;
                    }
                }
                {
                    WitnessV0ScriptHash scriptid;
                    if (data.size() == scriptid.size()) {
                        std::copy(data.begin(), data.end(), scriptid.begin());
                        return scriptid;
                    }
                }
                return CNoDestination();
            }
            if (version > 16 || data.size() < 2 || data.size() > 40) {
                return CNoDestination();
            }
            WitnessUnknown unk;
            unk.version = version;
            std::copy(data.begin(), data.end(), unk.program);
            unk.length = data.size();
            return unk;
        }
    }
    return CNoDestination();
}
} // namespace

其中Params的定义如下:

static std::unique_ptr<CChainParams> globalChainParams;

const CChainParams &Params() {
    assert(globalChainParams);
    return *globalChainParams;
}

在编码/解码前,需要选择CChainParams,如选择主网参数:

SelectParams(CBaseChainParams::MAIN);

主网参数CMainParams的定义如下:

/**
 * Main network
 */
/**
 * What makes a good checkpoint block?
 * + Is surrounded by blocks with reasonable timestamps
 *   (no blocks before with a timestamp after, none after with
 *    timestamp before)
 * + Contains no strange transactions
 */

class CMainParams : public CChainParams {
public:
    CMainParams() {
        strNetworkID = "main";
        consensus.nSubsidyHalvingInterval = 210000;
        consensus.BIP16Height = 173805; // 00000000000000ce80a7e057163a4db1d5ad7b20fb6f598c9597b9665c8fb0d4 - April 1, 2012
        consensus.BIP34Height = 227931;
        consensus.BIP34Hash = uint256S("0x000000000000024b89b42a942fe0d9fea3bb44ab7bd1b19115dd6a759c0808b8");
        consensus.BIP65Height = 388381; // 000000000000000004c2b624ed5d7756c508d90fd0da2c7c679febfa6c4735f0
        consensus.BIP66Height = 363725; // 00000000000000000379eaa19dce8c9b722d46ae6a57c2f1a988119488b50931
        consensus.powLimit = uint256S("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
        consensus.nPowTargetTimespan = 14 * 24 * 60 * 60; // two weeks
        consensus.nPowTargetSpacing = 10 * 60;
        consensus.fPowAllowMinDifficultyBlocks = false;
        consensus.fPowNoRetargeting = false;
        consensus.nRuleChangeActivationThreshold = 1916; // 95% of 2016
        consensus.nMinerConfirmationWindow = 2016; // nPowTargetTimespan / nPowTargetSpacing
        consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].bit = 28;
        consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nStartTime = 1199145601; // January 1, 2008
        consensus.vDeployments[Consensus::DEPLOYMENT_TESTDUMMY].nTimeout = 1230767999; // December 31, 2008

        // Deployment of BIP68, BIP112, and BIP113.
        consensus.vDeployments[Consensus::DEPLOYMENT_CSV].bit = 0;
        consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nStartTime = 1462060800; // May 1st, 2016
        consensus.vDeployments[Consensus::DEPLOYMENT_CSV].nTimeout = 1493596800; // May 1st, 2017

        // Deployment of SegWit (BIP141, BIP143, and BIP147)
        consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].bit = 1;
        consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nStartTime = 1479168000; // November 15th, 2016.
        consensus.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout = 1510704000; // November 15th, 2017.

        // The best chain should have at least this much work.
        consensus.nMinimumChainWork = uint256S("0x000000000000000000000000000000000000000000f91c579d57cad4bc5278cc");

        // By default assume that the signatures in ancestors of this block are valid.
        consensus.defaultAssumeValid = uint256S("0x0000000000000000005214481d2d96f898e3d5416e43359c145944a909d242e0"); //506067

        /**
         * The message start string is designed to be unlikely to occur in normal data.
         * The characters are rarely used upper ASCII, not valid as UTF-8, and produce
         * a large 32-bit integer with any alignment.
         */
        pchMessageStart[0] = 0xf9;
        pchMessageStart[1] = 0xbe;
        pchMessageStart[2] = 0xb4;
        pchMessageStart[3] = 0xd9;
        nDefaultPort = 8333;
        nPruneAfterHeight = 100000;

        genesis = CreateGenesisBlock(1231006505, 2083236893, 0x1d00ffff, 1, 50 * COIN);
        consensus.hashGenesisBlock = genesis.GetHash();
        assert(consensus.hashGenesisBlock == uint256S("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"));
        assert(genesis.hashMerkleRoot == uint256S("0x4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"));

        // Note that of those which support the service bits prefix, most only support a subset of
        // possible options.
        // This is fine at runtime as we'll fall back to using them as a oneshot if they dont support the
        // service bits we want, but we should get them updated to support all service bits wanted by any
        // release ASAP to avoid it where possible.
        vSeeds.emplace_back("seed.bitcoin.sipa.be"); // Pieter Wuille, only supports x1, x5, x9, and xd
        vSeeds.emplace_back("dnsseed.bluematt.me"); // Matt Corallo, only supports x9
        vSeeds.emplace_back("dnsseed.bitcoin.dashjr.org"); // Luke Dashjr
        vSeeds.emplace_back("seed.bitcoinstats.com"); // Christian Decker, supports x1 - xf
        vSeeds.emplace_back("seed.bitcoin.jonasschnelli.ch"); // Jonas Schnelli, only supports x1, x5, x9, and xd
        vSeeds.emplace_back("seed.btc.petertodd.org"); // Peter Todd, only supports x1, x5, x9, and xd

        base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,0);
        base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,5);
        base58Prefixes[SECRET_KEY] =     std::vector<unsigned char>(1,128);
        base58Prefixes[EXT_PUBLIC_KEY] = {0x04, 0x88, 0xB2, 0x1E};
        base58Prefixes[EXT_SECRET_KEY] = {0x04, 0x88, 0xAD, 0xE4};

        bech32_hrp = "bc";

        vFixedSeeds = std::vector<SeedSpec6>(pnSeed6_main, pnSeed6_main + ARRAYLEN(pnSeed6_main));

        fDefaultConsistencyChecks = false;
        fRequireStandard = true;
        fMineBlocksOnDemand = false;

        checkpointData = {
            {
                { 11111, uint256S("0x0000000069e244f73d78e8fd29ba2fd2ed618bd6fa2ee92559f542fdb26e7c1d")},
                { 33333, uint256S("0x000000002dd5588a74784eaa7ab0507a18ad16a236e7b1ce69f00d7ddfb5d0a6")},
                { 74000, uint256S("0x0000000000573993a3c9e41ce34471c079dcf5f52a0e824a81e7f953b8661a20")},
                {105000, uint256S("0x00000000000291ce28027faea320c8d2b054b2e0fe44a773f3eefb151d6bdc97")},
                {134444, uint256S("0x00000000000005b12ffd4cd315cd34ffd4a594f430ac814c91184a0d42d2b0fe")},
                {168000, uint256S("0x000000000000099e61ea72015e79632f216fe6cb33d7899acb35b75c8303b763")},
                {193000, uint256S("0x000000000000059f452a5f7340de6682a977387c17010ff6e6c3bd83ca8b1317")},
                {210000, uint256S("0x000000000000048b95347e83192f69cf0366076336c639f9b7228e9ba171342e")},
                {216116, uint256S("0x00000000000001b4f4b433e81ee46494af945cf96014816a4e2370f11b23df4e")},
                {225430, uint256S("0x00000000000001c108384350f74090433e7fcf79a606b8e797f065b130575932")},
                {250000, uint256S("0x000000000000003887df1f29024b06fc2200b55f8af8f35453d7be294df2d214")},
                {279000, uint256S("0x0000000000000001ae8c72a0b0c301f67e3afca10e819efa9041e458e9bd7e40")},
                {295000, uint256S("0x00000000000000004d9b4ef50f0f9d686fd69db2e03af35a100370c64632a983")},
            }
        };

        chainTxData = ChainTxData{
            // Data as of block 0000000000000000002d6cca6761c99b3c2e936f9a0e304b7c7651a993f461de (height 506081).
            1516903077, // * UNIX timestamp of last known number of transactions
            295363220,  // * total number of transactions between genesis and that timestamp
                        //   (the tx=... number in the SetBestChain debug.log lines)
            3.5         // * estimated number of transactions per second after that timestamp
        };
    }
};

测试程序如下:

// Base58Check Encode/Decode Destination
int main_bs58check(){
	// 选择主网参数 
	SelectParams(CBaseChainParams::MAIN);
	// 设置测试密钥
	CKey priKey;
	CPubKey pubKey;
	priKey.Set(TestPriKey.begin(), TestPriKey.end(), true);
	pubKey.Set(TestPubKey.begin(), TestPubKey.end());
	CKeyID address = pubKey.GetID(); 
	// 打印公钥ID
	std::cout<<"**** Pubkey ID:";
	print_vector(address.begin(), address.size());
	// 打印编码的比特币地址 
	std::cout<<"**** Encode Destination ****"<<std::endl; 
	std::string destPubKey = EncodeDestination(address);
	std::cout<<"****   P2PK Address: ";
	std::cout<<destPubKey<<std::endl;
	CScript P2WPKH = GetScriptForDestination(WitnessV0KeyHash(address)); 
	std::string destP2WPKH = EncodeDestination(P2WPKH);
	std::cout<<"**** P2WPKH Address: ";
	std::cout<<destP2WPKH<<std::endl; 
	std::string bech32P2WPKH = EncodeDestination(WitnessV0KeyHash(address));
	std::cout<<"**** Bech32 P2WPKH Address: ";
	std::cout<<bech32P2WPKH<<std::endl; 	
	uint256 hash;
    CSHA256().Write(&P2WPKH[0], P2WPKH.size()).Finalize(hash.begin());
	std::string bech32P2WSH = EncodeDestination(WitnessV0ScriptHash(hash));
	std::cout<<"****  Bech32 P2WSH Address: ";
	std::cout<<bech32P2WSH<<std::endl; 
	print_line(100, '=');
	std::cout<<"**** Decode Destination ****"<<std::endl; 
	// 解码P2PK地址 
	if(IsValidDestinationString(destPubKey)){
		CTxDestination ctxDest = DecodeDestination(destPubKey);
		CScript scriptPubKey = GetScriptForDestination(ctxDest);
		std::cout<<"****   P2PK scriptPubKey: ";
		print_vector(scriptPubKey, scriptPubKey.size());
	}
	// 解码P2WPK地址 
	CChainParams params = *CreateChainParams(CBaseChainParams::MAIN);
	if(IsValidDestinationString(destP2WPKH, params)){
		CTxDestination ctxDest = DecodeDestination(destP2WPKH);
		CScript scriptPubKey = GetScriptForDestination(ctxDest);
		std::cout<<"**** P2WPKH scriptPubKey: ";
		print_vector(scriptPubKey, scriptPubKey.size());
	}
	// 解码bech32格式地址 
	if(IsValidDestinationString(bech32P2WPKH)){
		CTxDestination ctxDest = DecodeDestination(bech32P2WPKH);
		CScript scriptPubKey = GetScriptForDestination(ctxDest);
		std::cout<<"**** Bech32 P2WPKH scriptPubKey: ";
		print_vector(scriptPubKey, scriptPubKey.size());
	}
	if(IsValidDestinationString(bech32P2WSH)){
		CTxDestination ctxDest = DecodeDestination(bech32P2WSH);
		CScript scriptPubKey = GetScriptForDestination(ctxDest);
		std::cout<<"****  Bech32 P2WSH scriptPubKey: ";
		print_vector(scriptPubKey, scriptPubKey.size());
	}
	
	return 0;
}
/** Base58Check Encode/Decode Destination 结束*/

程序输出:

=================================================================================================== 
Base58Check Encode/Decode Destination
=================================================================================================== 
**** Pubkey ID:154de7cabbb5822075e92c57a27ca3ef3e8be50c
------------------- 
**** Encode Destination ****
****   P2PK Address: 12weWzbq5jT7c3MHbHD2WP2uLXEUtaGLXZ
**** P2WPKH Address: 3KhmQic5wmCxDN5hHDr4TnGQu3S5LcKXTV
**** Bech32 P2WPKH Address: bc1qz4x70j4mkkpzqa0f93t6yl9raulghegv2mr2g8
****  Bech32 P2WSH Address: bc1qe228dz8w82e2fsv96je8pzh2edx36fahgezxfha73czm48rf677seq6q7h

=================================================================================================== 
**** Decode Destination ****
****   P2PK scriptPubKey: 76a914154de7cabbb5822075e92c57a27ca3ef3e8be50c88ac
------------------- 
**** P2WPKH scriptPubKey: a914c596906f342478ca56707f7bb1bda659cb3cef9887
------------------- 
**** Bech32 P2WPKH scriptPubKey: 0014154de7cabbb5822075e92c57a27ca3ef3e8be50c
------------------- 
****  Bech32 P2WSH scriptPubKey: 0020ca947688ee3ab2a4c185d4b2708aeacb4d1d27b7464464dfbe8e05ba9c69d7bd
------------------- 

===================================================================================================

源码下载:

https://github.com/babylco0/bitcoin_code_examples/tree/master/TestKey-1.2.0

from paramiko import SSHClient,AutoAddPolicy from ncclient import manager from time import sleep from datetime import datetime,timedelta device_ip='10.1.0.6' username='python' password='Huawei@123' device_name='X_T1_AGG1' nc_username='huawei' nc_password='Huawei@123' log_server='10.1.60.2' class Datacom(): def __init__(self,server,username,password): self.server=server self.username=username self.password=password self.client=self._get_client() self.cli=self.client.invoke_shell() self.cli.send('screen-length 0 temporary\n') self.cli.recv(9999) def _get_client(self): client=SSHClient() client.set_missing_host_key_policy(AutoAddPolicy) client.connect(self.server,username=self.username,password=self.password) return client def command(self,cmd): self.cli.send('{}\n'.format(cmd)) sleep(10) return self.cli.recv(9999).decode() def check_fan_fault(self): fan_info=self.command('display fan\n') return fan_info.find('Normal')==-1 def download_config(self,target,config_path='/vrpcfg.zip'): print('copy config file with sftp') client=self._get_client() sftp=client.open_sftp() sftp.get(config_path,target) client.close() def close(self): self.client.close() def datacom_loop(device_ip,username,password,device_name): while True: datacom=Datacom(device_ip,username,password) with open('command.txt') as f: for cmd in f: print(datacom.command(cmd)) if datacom.check_fan_fault(): print('All fans are faulty') datacom.close() try: if datetime.now()-last_downloadtime>=timedelta(days=1): last_downloadtime=datetime.now() datacom.download_config('{}_{}_{}_{}_vrpcfg.zip'.format( last_downloadtime.year, last_downloadtime.month, last_downloadtime.day, device_name )) except: last_downloadtime = datetime.now() datacom.download_config('{}_{}_{}_{}_vrpcfg.zip'.format( last_downloadtime.year, last_downloadtime.month, last_downloadtime.day, device_name )) datacom.close() sleep(5*60) def netconfig_set_logserver(device_ip,username,password,log_name,log_server): with manager.connect( host=device_ip, port=830, username=username, password=password, hostkey_verify=False, device_params={'name':'huaweiyang'} ) as m: config = ''' <config> <syslog:syslog xmlns:syslog="urn:ietf:params:xml:ns:yang:ietf-syslog"> <syslog:log-actions> <syslog:remote> <syslog:destination> <syslog:name>{}</syslog:name> <syslog:udp> <syslog:address xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0" xc:operation="replace">{}</syslog:address> </syslog:udp> </syslog:destination> </syslog:remote> </syslog:log-actions> </syslog:syslog> </config>'''.format(log_name,log_server) m.edit_config(config=config,target='running') if __name__ == '__main__': try: netconfig_set_logserver(device_ip,nc_username,nc_password,log_name='log_center',log_server=log_server) datacom_loop(device_ip,username,password,device_name) except KeyboardInterrupt: print('Monitoring has stopped!')
最新发布
06-18
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值