欧美性猛交xxxx免费看_牛牛在线视频国产免费_天堂草原电视剧在线观看免费_国产粉嫩高清在线观看_国产欧美日本亚洲精品一5区

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

比特幣源碼技術(shù)分析

C語言專家集中營 ? 來源:未知 ? 作者:李建兵 ? 2018-03-16 17:19 ? 次閱讀

比特幣客戶端所有的序列化函數(shù)均在seriliaze.h中實現(xiàn)。其中,CDataStream類是數(shù)據(jù)序列化的核心結(jié)構(gòu)。

CDataStream

CDataStream擁有一個字符類容器用來存放序列化之后的數(shù)據(jù)。它結(jié)合一個容器類型和一個流(stream)界面以處理數(shù)據(jù)。它使用6個成員函數(shù)實現(xiàn)這一功能:

[cpp]view plaincopy

classCDataStream

{

protected:

typedefvector>vector_type;

vector_typevch;

unsignedintnReadPos;

shortstate;

shortexceptmask;

public:

intnType;

intnVersion;

//......

}

vch存有序列化后的數(shù)據(jù)。它是一個擁有自定義內(nèi)存分配器的字符容器類型。該內(nèi)存分配器將由該容器的實現(xiàn)在需要分配/釋放內(nèi)存時調(diào)用。該內(nèi)存分配器會在向操作系統(tǒng)釋放內(nèi)存前清空內(nèi)存中的數(shù)據(jù)以防止本機的其他進程訪問此數(shù)據(jù),從而保證數(shù)據(jù)存儲的安全性。該內(nèi)存分配器的實現(xiàn)在此不進行討論,讀者可于serialize.h自行查找。

nReadPos是vch讀取數(shù)據(jù)的起始位置。

state是錯誤標(biāo)識。該變量用于指示在序列化/反序列化當(dāng)中可能出現(xiàn)的錯誤。

exceptmask是錯誤掩碼。它初始化為ios::badbit | ios::failbit。與state類似,它被用于指示錯誤種類。

nType的取值為SER_NETWORK,SER_DISK,SER_GETHASH,SER_SKIPSIG,SER_BLOCKHEADERONLY之一,其作用為通知CDataStream進行具體某種序列化操作。這5個符號被定義在一個枚舉類型enum里。每個符號均為一個int類型(4字節(jié)),并且其值為2的次方。

[cpp]view plaincopy

enum

{

//primaryactions

SER_NETWORK=(1<

SER_DISK=(1<

SER_GETHASH=(1<

//modifiers

SER_SKIPSIG=(1<

SER_BLOCKHEADERONLY=(1<

};

nVersion是版本號。

CDataStream::read()與CDataStream::write()

成員函數(shù)CDataStream::read()和CDataStream::write()是用于執(zhí)行序列化/反序列化CDataStream對象的低級函數(shù)。

[cpp]view plaincopy

CDataStream&read(char*pch,intnSize)

{

//Readfromthebeginningofthebuffer

assert(nSize>=0);

unsignedintnReadPosNext=nReadPos+nSize;

if(nReadPosNext>=vch.size())

{

if(nReadPosNext>vch.size())

{

setstate(ios::failbit,"CDataStream::read():endofdata");

memset(pch,0,nSize);

nSize=vch.size()-nReadPos;

}

memcpy(pch,&vch[nReadPos],nSize);

nReadPos=0;

vch.clear();

return(*this);

}

memcpy(pch,&vch[nReadPos],nSize);

nReadPos=nReadPosNext;

return(*this);

}

CDataStream&write(constchar*pch,intnSize)

{

//Writetotheendofthebuffer

assert(nSize>=0);

vch.insert(vch.end(),pch,pch+nSize);

return(*this);

}

CDataStream::read()從CDataStream復(fù)制nSize個字符到一個由char* pch所指向的內(nèi)存空間。以下是它的實現(xiàn)過程:

計算將要從vch讀取的數(shù)據(jù)的結(jié)束位置,unsigned int nReadPosNext = nReadPos + nSize。

如果結(jié)束位置比vch的大小更大,則當(dāng)前沒有足夠的數(shù)據(jù)供讀取。在這種情況下,通過調(diào)用函數(shù)setState()將state設(shè)為ios::failbit,并將所有的零復(fù)制到pch。

否則,調(diào)用memcpy(pch, &vch[nReadPos], nSize)復(fù)制nSize個字符,從vch的nReadPos位置開始,到由pch指向的一段預(yù)先分配的內(nèi)存。接著從nReadPos向前移至下一個起始位置nReadPosNext(第22行)。

該實現(xiàn)表明1)當(dāng)一段數(shù)據(jù)被從流中讀取之后,該段數(shù)據(jù)無法被再次讀取;2)nReadPos是第一個有效數(shù)據(jù)的讀取位置。

CDataStream::write()非常簡單。它將由pch指向的nSize個字符附加到vch的結(jié)尾。

宏READDATA()和WRITEDATA()

函數(shù)CDataStream::read()與CDataStream::write()的作用是序列化/反序列化原始類型(int,bool,unsigned long等)。為了序列化這些數(shù)據(jù)類型,這些類型的指針將被轉(zhuǎn)換為char*。由于這些類型的大小目前已知,它們可以從CDataStream中讀取或者寫入至字符緩沖。兩個用于引用這些函數(shù)的宏被定義為助手。

[cpp]view plaincopy

#defineWRITEDATA(s,obj)s.write((char*)&(obj),sizeof(obj))

#defineREADDATA(s,obj)s.read((char*)&(obj),sizeof(obj))

這里是如何使用這些宏的例子。下面的函數(shù)將序列化一個unsigned long類型。

[cpp]view plaincopy

[cpp]view plaincopy

templateinlinevoidSerialize(Stream&s,unsignedlonga,int,int=0){WRITEDATA(s,a);}

把WRITEDATA(s, a)用自身的定義取代,以下是展開以后的函數(shù):

[cpp]view plaincopy

templateinlinevoidSerialize(Stream&s,unsignedlonga,int,int=0){s.write((char*)&(a),sizeof(a));}

該函數(shù)接受一個unsigned long參數(shù)a,獲取它的內(nèi)存地址,轉(zhuǎn)換指針為char*并調(diào)用函數(shù)s.write()。

CDataStream中的操作符 << 和 >>

CDataStream重載了操作符<< 和 >>用于序列化和反序列化。

[cpp]view plaincopy

template

CDataStream&operator<<(const?T&?obj)??

{

//Serializetothisstream

::Serialize(*this,obj,nType,nVersion);

return(*this);

}

template

CDataStream&operator>>(T&obj)

{

//Unserializefromthisstream

::Unserialize(*this,obj,nType,nVersion);

return(*this);

}

頭文件serialize.h包含了14個重載后的這兩個全局函數(shù)給14個原始類型(signed和unsigned版本char,short,int,long和long long,以及char,float,double和bool)以及6個重載版本的6個復(fù)合類型(string,vector,pair,map,set和CScript)。因此,對于這些類型,你可以簡單地使用以下代碼來序列化/反序列化數(shù)據(jù):

[cpp]view plaincopy

CDataStreamss(SER_GETHASH);

ss<

ss>>obj3>>obj4;//反序列化

如果沒有任何實現(xiàn)的類型符合第二個參數(shù)obj,則以下泛型T全局函數(shù)將會被調(diào)用。

[cpp]view plaincopy

template

inlinevoidSerialize(Stream&os,constT&a,longnType,intnVersion=VERSION)

{

a.Serialize(os,(int)nType,nVersion);

}

對于該泛型版本,類型T應(yīng)該用于實現(xiàn)一個成員函數(shù)和簽名T::Serialize(Stream, int, int)。它將通過a.Serialize()被調(diào)用。

怎樣實現(xiàn)一個類型的序列化

在之前的介紹當(dāng)中,泛型T需要實現(xiàn)以下三個成員函數(shù)進行序列化。

[cpp]view plaincopy

unsignedintGetSerializeSize(intnType=0,intnVersion=VERSION)const;

voidSerialize(Stream&s,intnType=0,intnVersion=VERSION)const;

voidUnserialize(Stream&s,intnType=0,intnVersion=VERSION);

這三個函數(shù)將由它們相對應(yīng)的帶泛型T的全局函數(shù)調(diào)用。這些全局函數(shù)則由CDataStream中重載的操作符<<和>>調(diào)用。

一個宏IMPLEMENT_SERIALIZE(statements)用于定義任意類型的這三個函數(shù)的實現(xiàn)。

[cpp]view plaincopy

#defineIMPLEMENT_SERIALIZE(statements)\

unsignedintGetSerializeSize(intnType=0,intnVersion=VERSION)const\

{\

CSerActionGetSerializeSizeser_action;\

constboolfGetSize=true;\

constboolfWrite=false;\

constboolfRead=false;\

unsignedintnSerSize=0;\

ser_streamplaceholders;\

s.nType=nType;\

s.nVersion=nVersion;\

{statements}\

returnnSerSize;\

}\

template\

voidSerialize(Stream&s,intnType=0,intnVersion=VERSION)const\

{\

CSerActionSerializeser_action;\

constboolfGetSize=false;\

constboolfWrite=true;\

constboolfRead=false;\

unsignedintnSerSize=0;\

{statements}\

}\

template\

voidUnserialize(Stream&s,intnType=0,intnVersion=VERSION)\

{\

CSerActionUnserializeser_action;\

constboolfGetSize=false;\

constboolfWrite=false;\

constboolfRead=true;\

unsignedintnSerSize=0;\

{statements}\

}

以下例子示范怎樣使用該宏。

[cpp]view plaincopy

#include

#include"serialize.h"

usingnamespacestd;

classAClass{

public:

AClass(intxin):x(xin){};

intx;

IMPLEMENT_SERIALIZE(READWRITE(this->x);)

}

intmain(){

CDataStreamastream2;

AClassaObj(200);//一個x為200的AClass類型對象

cout<<"aObj="<>endl;

asream2<

AClassa2(1);//另一個x為1的對象

astream2>>a2

cout<<"a2="<

return0;

}

這段程序序列化/反序列化AClass對象。它將在屏幕上輸出下面的結(jié)果。

[cpp]view plaincopy

aObj=200

a2=200

AClass的這三個序列化/反序列化成員函數(shù)可以在一行代碼中實現(xiàn):

IMPLEMENT_SERIALIZE(READWRITE(this->x);)

宏READWRITE()的定義如下

[cpp]view plaincopy

#defineREADWRITE(obj)(nSerSize+=::SerReadWrite(s,(obj),nType,nVersion,ser_action))

該宏的展開被放在宏IMPLEMENT_SERIALIZE(statements)的全部三個函數(shù)里。因此,它一次需要完成三件事情:1)返回序列化后數(shù)據(jù)的大小,2)序列化(寫入)數(shù)據(jù)至流;3)從流中反序列化(讀取)數(shù)據(jù)。參考宏IMPLEMENT_SERIALIZE(statements)中對這三個函數(shù)的定義。

想要了解宏READWRITE(obj)怎樣工作,你首先需要明白它的完整形式當(dāng)中的nSerSize,s,

nType,nVersion和ser_action是怎么來的。它們?nèi)縼碜院?/p>

IMPLEMENT_SERIALIZE(statements)的三個函數(shù)主體部分:

nSerSize是一個unsigned int,在三個函數(shù)當(dāng)中初始化為0;

ser_action是一個對象在三個函數(shù)當(dāng)中均有聲明,但為三種不同類型。它在三個函數(shù)當(dāng)中

分別為CSerActionGetSerializeSize、CSerActionSerialize和

CSerActionUnserialize;

s在第一個函數(shù)中定義為ser_streamplaceholder類型。它是第一個傳入至另外兩個函數(shù)

的參數(shù),擁有參數(shù)類型Stream;

nType和nVersion在三個函數(shù)中均為傳入?yún)?shù)。

因此,一旦宏READWRITE()擴展至宏IMPLEMENT_SERIALIZE(),所有它的符號都將被計算,

因為它們已經(jīng)存在于宏IMPLEMENT_SERIALIZE()的主體中。READWRITE(obj)的擴展調(diào)用

一個全局函數(shù)::SerReadWrite(s, (obj), nType, nVersion, ser_action)。

這里是這個函數(shù)的全部三種版本。

[cpp]view plaincopy

template

inlineunsignedintSerReadWrite(Stream&s,constT&obj,intnType,intnVersion,CSerActionGetSerializeSizeser_action)

{

return::GetSerializeSize(obj,nType,nVersion);

}

template

inlineunsignedintSerReadWrite(Stream&s,constT&obj,intnType,intnVersion,CSerActionSerializeser_action)

{

::Serialize(s,obj,nType,nVersion);

return0;

}

template

inlineunsignedintSerReadWrite(Stream&s,T&obj,intnType,intnVersion,CSerActionUnserializeser_action)

{

::Unserialize(s,obj,nType,nVersion);

return0;

}

如你所見,函數(shù)::SerReadWrite()被重載為三種版本。取決于最后一個參數(shù),它將會調(diào)分別用全局函數(shù)::GetSerialize(),::Serialize()和::Unserialize();這三個函數(shù)在前面章節(jié)已經(jīng)介紹。

如果你檢查三種不同版本的::SerReadWrite()的最后一個參數(shù),你會發(fā)現(xiàn)它們?nèi)繛榭疹愋汀?/p>

這三種類型的唯一用途是區(qū)別::SerReadWrite()的三個版本,

繼而被宏IMPLEMENT_SERIALIZE()定義的所有函數(shù)使用。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 比特幣
    +關(guān)注

    關(guān)注

    57

    文章

    7006

    瀏覽量

    141309

原文標(biāo)題:比特幣源碼技術(shù)分析-2

文章出處:【微信號:C_Expert,微信公眾號:C語言專家集中營】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    #硬聲創(chuàng)作季 區(qū)塊鏈:1.1認識比特

    區(qū)塊鏈比特
    Mr_haohao
    發(fā)布于 :2022年10月16日 23:44:12

    #硬聲創(chuàng)作季 區(qū)塊鏈:1.6比特的分叉

    區(qū)塊鏈比特
    Mr_haohao
    發(fā)布于 :2022年10月16日 23:48:32

    #硬聲創(chuàng)作季 區(qū)塊鏈與加:1.2比特的來源

    區(qū)塊鏈比特
    Mr_haohao
    發(fā)布于 :2022年10月17日 09:42:07

    #硬聲創(chuàng)作季 區(qū)塊鏈與加:1.3比特是什么

    區(qū)塊鏈比特
    Mr_haohao
    發(fā)布于 :2022年10月17日 09:42:44

    #硬聲創(chuàng)作季 區(qū)塊鏈與加:1.6比特分叉

    區(qū)塊鏈比特
    Mr_haohao
    發(fā)布于 :2022年10月17日 09:44:29

    #硬聲創(chuàng)作季 區(qū)塊鏈與加:2.4比特回顧

    區(qū)塊鏈比特
    Mr_haohao
    發(fā)布于 :2022年10月17日 09:47:11

    究竟比特是什么

    ?! ∪欢?,比特卻在大洋彼岸贏得了肯定,華爾街最大的機構(gòu)之一——美銀美林宣布其研究范圍正式覆蓋比特,并對比特
    發(fā)表于 12-15 11:17

    時代周刊:為什么比特是自由的源泉?

    銀行賬戶,但他無法凍結(jié)比特錢包;在難民營,你可能無法找到一家銀行,但只要有網(wǎng)絡(luò),你就可以收到比特,你不需要獲得任何人的批準(zhǔn),也不用證明自己的身份。
    發(fā)表于 01-01 23:23

    萊特比特的區(qū)別

    本文詳細的介紹了萊特比特的相關(guān)概念,其中包括了萊特礦池介紹、比特特征和
    發(fā)表于 01-09 11:21 ?6589次閱讀

    比特是不是電子貨幣_比特怎么交易

    本文開始詳細的介紹了比特的特征,其次介紹了比特的幾個易平臺和分析比特
    發(fā)表于 01-30 16:25 ?1w次閱讀

    關(guān)于比特源碼技術(shù)分析

    為了存儲、搜索、讀取在內(nèi)存與磁盤中的區(qū)塊和交易信息,比特引入了一些訪問類。它們包括:CBlockIndex和CDiskBlockIndex用于索引區(qū)塊,CDiskTxPos和CTxIndex用于索引交易。
    的頭像 發(fā)表于 04-02 16:55 ?5310次閱讀

    比特現(xiàn)金B(yǎng)CH才是原始的比特區(qū)塊鏈

    美國國家標(biāo)準(zhǔn)和技術(shù)研究所(NIST ):比特是一個分叉,BCH才是最初的區(qū)塊鏈。NIST 于2018年1月29日發(fā)布了一份詳細的比特和區(qū)
    發(fā)表于 11-08 14:19 ?1585次閱讀

    比特價格的上漲推動了比特礦業(yè)的利潤

    加密貨幣分析師亞歷克斯克魯格(Alex Kruger)表示,有效的比特開采業(yè)務(wù)目前的盈虧平衡點在3550美元至4350美元之間,而在撰寫本文時比特
    發(fā)表于 06-18 10:59 ?698次閱讀
    <b class='flag-5'>比特</b><b class='flag-5'>幣</b>價格的上漲推動了<b class='flag-5'>比特</b><b class='flag-5'>幣</b>礦業(yè)的利潤

    比特比特現(xiàn)金的區(qū)別是什么

    比特核心(BTC)的支持者說,比特不是用來買咖啡的。他們認為比特的目的是作為一種價值儲備,
    發(fā)表于 12-27 09:27 ?2709次閱讀

    Twitter的比特情感分析器怎樣來構(gòu)建

    我們的比特情緒分析儀功能完善,為進一步分析比特情緒提供了良好的基礎(chǔ)。
    發(fā)表于 01-12 10:49 ?1227次閱讀