生成比特幣創世塊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雜湊,生成一個