本系列博文對理論性的東西叙述的不多,主要是以代碼為主,本例是模仿比特币實作的一個電子貨币記賬系統。
雖然不打算介紹理論性的東西,但交易流程還是要說一下的,畢竟所有的代碼都是為這個交易流程服務的。
- 交易流程
- 程式設計
- Cryptography
- P2PNode
- BlockChain
- 完整代碼
交易流程
當發起一個交易的時候,交易發起方先準備一條“位址a要向位址b轉賬n個币”的消息,然後用位址a的私鑰進行數字簽名,用以表明發起方對位址a的所有權,最後再把該消息和簽名資訊在P2P網絡上對其他節點進行廣播。
其他節點收到廣播後,先對消息的數字簽名進行驗證,驗證通過後再檢查餘額是否夠用。全部驗證通過後将該交易記在自己的交易清單上。至此,交易流程結束。
雖然交易流程結束了,但還沒有記到區塊鍊上,那怎麼記到區塊鍊上呢?挖礦啊。當一個節點找到了一個工作量證明,就将自己記錄的交易清單打包記到一個區塊上,然後再向所有的節點進行廣播,告訴其他人。
其他節點收到區塊後,對工作量證明進行驗證,驗證後将區塊挂在區塊鍊上,再将該區塊上的交易清單和自己的交易清單進行比對,将自己交易清單中已經在區塊上記錄的消息删除。
當然,比特币中的交易流程要比這複雜的多,我們隻為學習,把流程進行簡化了。
程式設計
綜上所述,可以看出應該有三個主要子產品:數字簽名,P2P網絡和區塊鍊邏輯。以下是對三個子產品的定義:
Cryptography
該類主要用于處理數字簽名,編碼解碼等數學和密碼相關功能。
typedef struct __keydata
{
size_t len;
unsigned char key[];
} KeyData;
typedef struct __KeyPair
{
KeyData pubKey;
KeyData priKey;
} KeyPair;
class Cryptography
{
public:
static std::string GetHash(void const* buffer, std::size_t len);
static std::string Base64Encode(const void*buff, int len);
static void Base64Decode(const std::string &str64, void *outbuff, size_t outsize, size_t *outlen);
static void Createkey(KeyPair &keyPair);
static bool Signature(const KeyData &priKey, const void *data, int datalen, unsigned char *sign, size_t signszie, unsigned int *signlen);
static int Verify(const KeyData &pubkey, const char *data, int datalen, const unsigned char *sign, size_t signszie, unsigned int signlen);
static std::string StringToLower(const std::string &str);
static bool CompareNoCase(const std::string &strA, const std::string &strB);
static std::vector<std::string> StringSplit(const std::string &str, const char sep);
protected:
Cryptography();
virtual ~Cryptography();
private:
};
P2PNode
該類主要處理網絡通信相關功能
typedef enum
{
p2p_transaction = ,
p2p_bookkeeping,
p2p_result,
p2p_merge,
p2p_blockchain,
p2p_max
} P2PCommand;
typedef struct st_broadcast
{
KeyData pubkey;
char json[];
unsigned int signlen;
unsigned char sign[];
} __attribute__((packed))
BroadcastMessage;
typedef struct st_p2pMessage
{
int index;
int total;
char messHash[];
P2PCommand cmd;
size_t length;
char mess[MAX_P2P_SIZE];
} __attribute__((packed))
P2PMessage;
typedef struct st_p2pResult
{
int index;
char messHash[];
bool operator == (const struct st_p2pResult & value) const
{
return
this->index == value.index &&
!strcmp(this->messHash, value.messHash);
}
} __attribute__((packed))
P2PResult;
class P2PNode
{
public:
static P2PNode *Instance(const char *if_name);
void Listen();
void Broadcast(P2PCommand cmd, const BroadcastMessage &bm);
void MergeChain();
protected:
P2PNode(const char *if_name);
virtual ~P2PNode();
private:
int m_sock;
Node m_selfNode;
Node m_otherNode;
char *m_otherIP;
int m_otherPort;
pthread_t m_tid;
pthread_mutex_t m_mutexPack;
pthread_mutex_t m_mutexResult;
struct sockaddr_in m_serverAddr;
struct sockaddr_in m_localAddr;
struct sockaddr_in m_recvAddr;
typedef struct st_package
{
int total;
char messHash[];
P2PCommand cmd;
std::map<int, std::string> mapMess;
bool operator == (const struct st_package & value) const
{
return
this->total == value.total &&
this->cmd == value.cmd &&
!strcmp(this->messHash, value.messHash);
}
} Package;
std::list<Package> m_lstPackage;
std::list<P2PResult> m_lstResult;
static void *threadFunc(void *arg);
void threadHandler();
void combinationPackage(P2PMessage &mess);
int get_local_ip(const char *ifname, char *ip);
void sendMessage(P2PMessage &mess);
void sendBlockChain();
};
BlockChain
該類處理區塊鍊相關業務邏輯
typedef struct __transactions
{
std::string sender;
std::string recipient;
float amount;
bool operator == (const struct __transactions & value) const
{
return
this->sender == value.sender &&
this->recipient == value.recipient &&
this->amount == value.amount;
}
}Transactions;
typedef struct __block
{
int index;
time_t timestamp;
std::list<Transactions> lst_ts;
long int proof;
std::string previous_hash;
bool operator == (const struct __block & value) const
{
return
this->index == value.index &&
this->timestamp == value.timestamp &&
this->previous_hash == value.previous_hash &&
this->lst_ts == value.lst_ts &&
this->proof == value.proof;
}
} Block;
class BlockChain
{
public:
static BlockChain *Instance();
std::string GetJsonFromBlock(Block &block);
std::string GetJsonFromTransactions(Transactions &ts);
Block GetBlockFromJson(const std::string &json);
Transactions GetTransactionsFromJson(const std::string &json);
std::string GetJsonFromBlockList();
std::string GetJsonFromTransactionsList();
std::list<Block> GetBlockListFromJson(const std::string &json);
void GetTransactionsListFromJson(const std::string &json);
std::string CreateNewAddress(const KeyPair &keyPair);
Transactions CreateTransactions(const std::string &sender, const std::string &recipient, float amount);
Block CreateBlock(int index, time_t timestamp, long int proof);
int WorkloadProof(int last_proof);
bool WorkloadVerification(int proof);
std::string Mining(const std::string &addr);
int CheckBalances(const std::string &addr);
void DeleteDuplicateTransactions(const Block &block);
void MergeBlockChain(const std::string &json);
inline void InsertBlock(const Block &block)
{
pthread_mutex_lock(&m_mutexBlock);
if (m_lst_block.end() == std::find(m_lst_block.begin(), m_lst_block.end(), block))
{
m_lst_block.push_back(block);
}
pthread_mutex_unlock(&m_mutexBlock);
}
inline void InsertTransactions(const Transactions &ts)
{
pthread_mutex_lock(&m_mutexTs);
if (m_lst_ts.end() == std::find(m_lst_ts.begin(), m_lst_ts.end(), ts))
{
m_lst_ts.push_back(ts);
}
pthread_mutex_unlock(&m_mutexTs);
}
inline Block GetLastBlock()
{
Block block;
pthread_mutex_lock(&m_mutexBlock);
block = m_lst_block.back();
pthread_mutex_unlock(&m_mutexBlock);
return block;
}
protected:
BlockChain();
virtual ~BlockChain();
private:
std::list<Transactions> m_lst_ts;
std::list<Block> m_lst_block;
pthread_mutex_t m_mutexTs;
pthread_mutex_t m_mutexBlock;
};
具體實作後面會細講。
完整代碼
完整代碼戳這裡。