1. 程式人生 > >生成比特幣創世塊C/C++原始碼

生成比特幣創世塊C/C++原始碼


#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <inttypes.h>
#include <ctype.h>
#include <string.h>
#include <time.h>
#include <openssl/sha.h>

//Copied from Bitcoin source
const uint64_t COIN = 100000000;
const uint64_t CENT = 1000000;

uint32_t OP_CHECKSIG = 172
; // This is expressed as 0xAC bool generateBlock = false; uint32_t startNonce = 0; uint32_t unixtime = 0; typedef struct { /* Hash of Tx */ uint8_t merkleHash[32]; /* Tx serialization before hashing */ uint8_t *serializedData; /* Tx version */ uint32_t version; /* Input */ uint8_t numInputs; // Program assumes one input
uint8_t prevOutput[32]; uint32_t prevoutIndex; uint8_t *scriptSig;// nBitsLen + nBits + 0x01 + 0x04 + ScriptSig_len + timestamp uint32_t sequence; /* Output */ uint8_t numOutputs; // Program assumes one output uint64_t outValue; uint8_t *pubkeyScript;//0x41 + pubkey + OP_CHECKSIG
/* Final */ uint32_t locktime; } Transaction; // Got this off the internet. Am not sure if it can fail in some circumstances void byteswap(uint8_t *buf, int length) { int i; uint8_t temp; for (i = 0; i < length / 2; i++) { temp = buf[i]; buf[i] = buf[length - i - 1]; buf[length - i - 1] = temp; } } // Following two functions are borrowed from cgminer. char *bin2hex(const unsigned char *p, size_t len) { char *s = (char*)malloc((len * 2) + 1); unsigned int i; if (!s) return NULL; for (i = 0; i < len; i++) sprintf_s(s + (i * 2), 3, "%02x", (unsigned int)p[i]); return s; } size_t hex2bin(unsigned char *p, const char *hexstr, size_t len) { int ret = 0; size_t retlen = len; while (*hexstr && len) { char hex_byte[4]; unsigned int v; if (!hexstr[1]) { return ret; } memset(hex_byte, 0, 4); hex_byte[0] = hexstr[0]; hex_byte[1] = hexstr[1]; if (sscanf_s(hex_byte, "%x", &v) != 1) { return ret; } *p = (unsigned char)v; p++; hexstr += 2; len--; } if (len == 0 && *hexstr == 0) ret = retlen; return ret; } Transaction *InitTransaction() { Transaction *transaction; transaction = (Transaction *)calloc(1, sizeof(*transaction)); if (!transaction) { return NULL; } // Set some initial data that will remain constant throughout the program transaction->version = 1; transaction->numInputs = 1; transaction->numOutputs = 1; transaction->locktime = 0; transaction->prevoutIndex = 0xFFFFFFFF; transaction->sequence = 0xFFFFFFFF; transaction->outValue = 50 * COIN; // We initialize the previous output to 0 as there is none memset(transaction->prevOutput, 0, 32); return transaction; } //執行命令:./genesisgen [PubKey] [TimeStamp] [nBits] int main(int argc, char *argv[]) { Transaction *transaction; unsigned char hash1[32], hash2[32]; char timestamp[255], pubkey[132]; uint32_t timestamp_len = 0, scriptSig_len = 0, pubkey_len = 0, pubkeyScript_len = 0; uint32_t nBits = 0; if ((argc - 1) < 3) { fprintf(stderr, "Usage: genesisgen [options] <pubkey> \"<timestamp>\" <nBits>\n"); return 0; } pubkey_len = strlen(argv[1]) / 2; // One byte is represented as two hex characters, thus we divide by two to get real length. timestamp_len = strlen(argv[2]); if (pubkey_len != 65) { fprintf(stderr, "Invalid public key length! %s\n", argv[1]); return 0; } if (timestamp_len > 254 || timestamp_len <= 0) { fprintf(stderr, "Size of timestamp is 0 or exceeds maximum length of 254 characters!\n"); return 0; } transaction = InitTransaction(); if (!transaction) { fprintf(stderr, "Could not allocate memory! Exiting...\n"); return 0; } strncpy_s(pubkey, argv[1], sizeof(pubkey)); strncpy_s(timestamp, argv[2], sizeof(timestamp)); sscanf_s(argv[3], "%lu", (long unsigned int *)&nBits); pubkey_len = strlen(pubkey) >> 1; scriptSig_len = timestamp_len; // Encode pubkey to binary and prepend pubkey size, then append the OP_CHECKSIG byte transaction->pubkeyScript = (uint8_t*)malloc((pubkey_len + 2) * sizeof(uint8_t)); pubkeyScript_len = hex2bin(transaction->pubkeyScript + 1, pubkey, pubkey_len); // No error checking, yeah. transaction->pubkeyScript[0] = 0x41; // A public key is 32 bytes X coordinate, 32 bytes Y coordinate and one byte 0x04, so 65 bytes i.e 0x41 in Hex. pubkeyScript_len += 1; transaction->pubkeyScript[pubkeyScript_len++] = OP_CHECKSIG; // Encode timestamp to binary transaction->scriptSig = (uint8_t*)malloc(scriptSig_len * sizeof(uint8_t)); uint32_t scriptSig_pos = 0; // This is basically how I believe the size of the nBits is calculated if (nBits <= 255) { transaction->scriptSig[scriptSig_pos++] = 0x01; transaction->scriptSig[scriptSig_pos++] = (uint8_t)nBits; } else if (nBits <= 65535) { transaction->scriptSig[scriptSig_pos++] = 0x02; memcpy(transaction->scriptSig + scriptSig_pos, &nBits, 2); scriptSig_pos += 2; } else if (nBits <= 16777215) { transaction->scriptSig[scriptSig_pos++] = 0x03; memcpy(transaction->scriptSig + scriptSig_pos, &nBits, 3); scriptSig_pos += 3; } else //else if(nBits <= 4294967296LL) { transaction->scriptSig[scriptSig_pos++] = 0x04; memcpy(transaction->scriptSig + scriptSig_pos, &nBits, 4); scriptSig_pos += 4; } // Important! In the Bitcoin code there is a statement 'CBigNum(4)' // i've been wondering for a while what it is but // seeing as alt-coins keep it the same, we'll do it here as well // It should essentially mean PUSH 1 byte on the stack which in this case is 0x04 or just 4 transaction->scriptSig[scriptSig_pos++] = 0x01; transaction->scriptSig[scriptSig_pos++] = 0x04; transaction->scriptSig[scriptSig_pos++] = (uint8_t)scriptSig_len; scriptSig_len += scriptSig_pos; transaction->scriptSig = (uint8_t*)realloc(transaction->scriptSig, scriptSig_len * sizeof(uint8_t)); memcpy(transaction->scriptSig + scriptSig_pos, (const unsigned char *)timestamp, timestamp_len); // Here we are asuming some values will have the same size uint32_t serializedLen = 4 // tx version + 1 // number of inputs + 32 // hash of previous output + 4 // previous output's index + 1 // 1 byte for the size of scriptSig + scriptSig_len + 4 // size of sequence + 1 // number of outputs + 8 // 8 bytes for coin value + 1 // 1 byte to represent size of the pubkey Script + pubkeyScript_len + 4; // 4 bytes for lock time // Now let's serialize the data uint32_t serializedData_pos = 0; transaction->serializedData = (uint8_t*)malloc(serializedLen * sizeof(uint8_t)); memcpy(transaction->serializedData + serializedData_pos, &transaction->version, 4); serializedData_pos += 4; memcpy(transaction->serializedData + serializedData_pos, &transaction->numInputs, 1); serializedData_pos += 1; memcpy(transaction->serializedData + serializedData_pos, transaction->prevOutput, 32); serializedData_pos += 32; memcpy(transaction->serializedData + serializedData_pos, &transaction->prevoutIndex, 4); serializedData_pos += 4; memcpy(transaction->serializedData + serializedData_pos, &scriptSig_len, 1); serializedData_pos += 1; memcpy(transaction->serializedData + serializedData_pos, transaction->scriptSig, scriptSig_len); serializedData_pos += scriptSig_len; memcpy(transaction->serializedData + serializedData_pos, &transaction->sequence, 4); serializedData_pos += 4; memcpy(transaction->serializedData + serializedData_pos, &transaction->numOutputs, 1); serializedData_pos += 1; memcpy(transaction->serializedData + serializedData_pos, &transaction->outValue, 8); serializedData_pos += 8; memcpy(transaction->serializedData + serializedData_pos, &pubkeyScript_len, 1); serializedData_pos += 1; memcpy(transaction->serializedData + serializedData_pos, transaction->pubkeyScript, pubkeyScript_len); serializedData_pos += pubkeyScript_len; memcpy(transaction->serializedData + serializedData_pos, &transaction->locktime, 4); serializedData_pos += 4; // Now that the data is serialized // we hash it with SHA256 and then hash that result to get merkle hash SHA256(transaction->serializedData, serializedLen, hash1); SHA256(hash1, 32, hash2); // This copy isn't necessary imo, but here for clarity memcpy(transaction->merkleHash, hash2, 32); char *merkleHash = bin2hex(transaction->merkleHash, 32); byteswap(transaction->merkleHash, 32); char *merkleHashSwapped = bin2hex(transaction->merkleHash, 32); char *txScriptSig = bin2hex(transaction->scriptSig, scriptSig_len); char *pubScriptSig = bin2hex(transaction->pubkeyScript, pubkeyScript_len); printf("\nCoinbase: %s\n\nPubkeyScript: %s\n\nMerkle Hash: %s\nByteswapped: %s\n", txScriptSig, pubScriptSig, merkleHash, merkleHashSwapped); //if(generateBlock) { printf("Generating block...\n"); if (!unixtime) { unixtime = time(NULL); } unsigned char block_header[80], block_hash1[32], block_hash2[32]; uint32_t blockversion = 1; memcpy(block_header, &blockversion, 4); memset(block_header + 4, 0, 32); byteswap(transaction->merkleHash, 32); // We swapped it before, so do it again now. memcpy(block_header + 36, transaction->merkleHash, 32); memcpy(block_header + 68, &unixtime, 4); memcpy(block_header + 72, &nBits, 4); memcpy(block_header + 76, &startNonce, 4); uint32_t *pNonce = (uint32_t *)(block_header + 76); uint32_t *pUnixtime = (uint32_t *)(block_header + 68); unsigned int counter = 0, start = time(NULL); while (1) { SHA256(block_header, 80, block_hash1); SHA256(block_hash1, 32, block_hash2); unsigned int check = *((uint32_t *)(block_hash2 + 28)); // The hash is in little-endian, so we check the last 4 bytes. if (check == 0) // \x00\x00\x00\x00 { byteswap(block_hash2, 32); char *blockHash = bin2hex(block_hash2, 32); printf("\nBlock found!\nHash: %s\nNonce: %u\nUnix time: %u", blockHash, startNonce, unixtime); free(blockHash); break; } startNonce++; counter += 1; if (time(NULL) - start >= 1) { printf("\r%d Hashes/s, Nonce %u\r", counter, startNonce); counter = 0; start = time(NULL); } *pNonce = startNonce; if (startNonce > 4294967294LL) { //printf("\nBlock found!\nHash: %s\nNonce: %u\nUnix time: %u", blockHash, startNonce, unixtime); unixtime++; *pUnixtime = unixtime; startNonce = 0; } } } // Lots of cleanup free(merkleHash); free(merkleHashSwapped); free(txScriptSig); free(pubScriptSig); free(transaction->serializedData); free(transaction->scriptSig); free(transaction->pubkeyScript); free(transaction); getchar(); return 0; }

相關推薦

生成創世C/C++原始碼

#include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <inttypes.h> #include <ctype.h>

使用PHP從擴充套件公鑰生成錢包地址

重複使用相同的比特幣錢包地址是一個很大的隱私問題。如果你有一個簡單的電子商店或要求捐贈的網站,你可能需要考慮為每筆交易生成唯一的地址。 有很多支付系統,如Bitpay,為你完成所有艱苦的工作。缺點是他們需要使用你的私鑰。但是,你可以使用來自分級確定性(hierarchically det

golang[38]-區塊鏈- 生成地址

生成比特幣地址 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707

如何在Java中生成錢包地址

讓我們通過學習比特幣(Bitcoin)如何實施該技術的各個方面來工作,好嗎?該技術包括以下幾個方面: 交易transaction是比特幣從一個地址轉移到另一個地址。 幾個交易被分組成一個區塊block。一個區塊被處理,因此它可以被提交到比特幣網路中。這個過程被稱為挖礦

go實現橢圓曲線加解密、簽名驗證演算法(go ecdsa庫的運用),及生成地址過程講解、base58實現

go實現橢圓曲線加解密、簽名驗證演算法(go ecdsa庫的運用),及生成比特幣地址過程講解、BASE58實現 前言 本文主要講解使用Go的ecdsa庫實現橢圓曲線加解密、簽名、驗證演算法,同時通過公鑰生成比特幣地址,具體程式碼邏輯參考bitcoin0

使用Java生成錢包地址的過程

比特幣錢包地址的生成過程第一步,通過OpenSSL命令隨機生成金鑰對生成橢圓曲線的私鑰opens

Openssl實現生成地址的base58編碼

比特幣協議中比特幣地址的生成演算法如下: 比特幣地址(Bitcoin Address)是ECDSA公鑰(public key)的雜湊,它是這樣計算出來的: Version = 1 個位元組 0

創世-GenesisBlock

// HarryWu, generate genesis block by genesis.py as following: // // genesis # python genesis.py \ //   -t $(date +%s) \ //   -z "shangha

原始碼閱讀筆記-創世的產生

const char*pszTimestamp = "2014/5/11 Write by Andy,Email:[email protected]";//我的創世區塊 CTransaction txNew; txNew.vin.resize(1);txNew.vout.resize(1); txN

C#網格交易策略實現及回測分析-基於OKex交易所

網格交易法或者網格交易策略,網上有很多的介紹,這裡是利用C#實現了比特幣網格交易的策略及程式化交易,並利用OKex上的K線資料進行了回測驗證,同時也進行視覺化的K線展示。對於網格交易策略簡單的說就是低買高賣策略,網格的含義是指對買賣區間和買賣倉位的控制手段。比如這裡我有8萬的

C#開發詳解

浪費了“黃金五年”的Java程式設計師,還有救嗎? >>>   

私鑰生成

hle cpu .html byte first 然而 lin ref bsp 比特幣突破4萬人民幣一個了,於是下了份源碼來研究研究。 重點分析下比特幣私鑰生成的原理,看能否重現私鑰的,只要有私鑰這個隨機數就相當於擁有了整個賬戶,然而看到了這一句: 根據CPU當前性能來生成

從零開始學習開發(七)-P2P網路建立流程之生成地址對並連線到指定地址

本節繼續講解比特幣P2P網路建立流程,這節講解的執行緒為’ThreadOpenAddedConnections’,它的作用是生成地址對並連線到指定地址。 本文可以結合比特幣系統啟動的的第12步的講解來看,可以更加系統的瞭解比特幣系統啟動的過程。 P2P 網路的建立是在比特幣系統啟動的第

真的安全嗎?我居然生成了一個和別人一樣的私鑰

比特幣的私鑰長度為256位,理論上有2的256次方種情況,這是一個非常龐大的數字,科學研究宇宙中的原子個數大約為10的80次方,2的256次方大約等於10的77次方。所以隨機生成一個私鑰,出現重複的概率是相當小的,這也是比特幣安全性的保障。概率雖小但還是會出現,今天就被我遇到了。 今天用程式隨機生成了一個私

13歲創業,3錢賣掉大把,基金會創始主席有著怎樣的開掛人生?|人物誌...

13歲時,為了實現“只為自己打工”的夢想,他開始了自己的第一份創業。比特幣基金會是他的第12個創業專案。 他是第一批比特幣礦工,當時每天可以挖出150個,曾經以每個6美分的價格將手中的比特幣一一賣出了。 他因收養了一個南非兒童和其他原因,退出了比特幣

地址生成過程 go語言版本

比特幣地址結構: 【版本 + 公鑰雜湊 + 驗證碼】 版本:預設0x00, 即可空白的一位元組。 公鑰:由非對稱加密演算法得出。 公鑰雜湊:就是給公鑰做雜湊演算法得出的結果。 驗證碼:給 [版本 + 公鑰雜湊],sha256兩次,取頭4個字元作為驗證碼。 package main

BTC原始碼分析(1):地址生成過程

一、生成一個比特幣錢地址 二、根據原始碼整理比特幣地址生成過程 1、取得公鑰PubKey 2、使用 RIPEMD160(SHA256(PubKey)) 雜湊演算法,取公鑰並對其雜湊兩次 3、給雜湊加上地址生成演算法版本的字首 4、對於第二步生成的結果,使用SHA256(SHA256

主網地址生成和簽名

一.地址生成 var bip39 = require('bip39') const bip32 = require('bip32') const bitcoin = require('bitcoinjs-lib') const baddress = require('bitcoinj

地址生成演算法詳解

1 生成過程 比特幣地址生成流程如下圖所示:   第一步,隨機選取一個32位元組的數,大小介於1~0xFFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFE BAAE DCE6 AF48 A03B BFD2 5E8C D036 4141之間,作為私鑰 18e14a7b6a307

地址生成過程以及如何判斷一個地址是否有效

(一)比特幣地址生成過程 1.由私鑰通過橢圓曲線加密演算法生成公鑰,公鑰實際就是一串位元組陣列。私鑰是由一個隨機產生的數字串經過雜湊的十六進位制字串。 2.有了公鑰以後,通過下圖步驟生成比特幣地址: 具體過程: 1.將公鑰進行256雜湊,再進行160雜湊,生成一個