Bitcoin 시리얼화된 라이브러리 사용
14761 단어 비트코인
serialize.h
파일에 실현되고 전체 코드는 stream
와 서열화에 참여하는 반서열화 유형 T를 중심으로 전개된다. stream 이 템플릿은
read(char**, size_t)
와 write(char**, size_t)
방법을 가진 대상을 나타냅니다. Golang의 io와 유사합니다.reader ,io.writer. 간단한 사용 예:
#include
#include
#include
#include
#include
#include
#include
BOOST_FIXTURE_TEST_SUITE(serialize_tests, BasicTestingSetup)
struct student
{
std::string name;
double midterm, final;
std::vector homework;
ADD_SERIALIZE_METHODS;
template
inline void SerializationOp(Stream& s, Operation ser_action) {
READWRITE(name);
READWRITE(midterm);
READWRITE(final);
READWRITE(homework);
}
};
bool operator==(student const& lhs, student const& rhs){
return lhs.name == rhs.name && \
lhs.midterm == rhs.midterm && \
lhs.final == rhs.final && \
lhs.homework == rhs.homework;
}
std::ostream& operator< {83, 50, 10, 88, 65};
s.homework = v;
CDataStream ss(SER_DISK, 0);
ss << s;
ss >> t;
BOOST_CHECK(t.name == "john");
BOOST_CHECK(t.midterm == 77);
BOOST_CHECK(t.final == 82);
BOOST_TEST(t.homework == v, boost::test_tools::per_element());
CDataStream sd(SER_DISK, 0);
CDataStream sn(SER_NETWORK, PROTOCOL_VERSION);
sd << s;
sn << s;
BOOST_CHECK(Hash(sd.begin(), sd.end()) == Hash(sn.begin(), sn.end()));
}
BOOST_AUTO_TEST_CASE(vector)
{
auto vs = std::vector(3);
vs[0].name = "bob";
vs[0].midterm = 90;
vs[0].final = 76;
vs[0].homework = std::vector {85, 53, 12, 75, 55};
vs[1].name = "jim";
vs[1].midterm = 96;
vs[1].final = 72;
vs[1].homework = std::vector {91, 46, 19, 70, 59};
vs[2].name = "tom";
vs[2].midterm = 85;
vs[2].final = 57;
vs[2].homework = std::vector {91, 77, 45, 50, 35};
CDataStream ss(SER_DISK, 0);
auto vt = std::vector(3);
ss << vs;
ss >> vt;
BOOST_TEST(vs == vt, boost::test_tools::per_element());
}
BOOST_AUTO_TEST_CASE(unique_ptr){
auto hex = "0100000001b14bdcbc3e01bdaad36cc08e81e69c82e1060bc14e518db2b49aa43ad90ba26000000000490047304402203f16c6f40162ab686621ef3000b04e75418a0c0cb2d8aebeac894ae360ac1e780220ddc15ecdfc3507ac48e1681a33eb60996631bf6bf5bc0a0682c4db743ce7ca2b01ffffffff0140420f00000000001976a914660d4ef3a743e3e696ad990364e555c271ad504b88ac00000000";
CDataStream stream(ParseHex(hex), SER_NETWORK, PROTOCOL_VERSION);
//CTransaction tx(deserialize, stream);
auto utx = std::unique_ptr(nullptr);
::Unserialize(stream, utx);
BOOST_TEST(utx->vin.size() == std::size_t(1));
BOOST_TEST(utx->vout[0].nValue == 1000000);
}
BOOST_AUTO_TEST_SUITE_END()
사용자 정의 유형 내부에 ADD 추가 필요SERIALIZE_METHODS 호출, 확대 후:
template \
void Serialize(Stream& s) const { \
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
} \
template \
void Unserialize(Stream& s) { \
SerializationOp(s, CSerActionUnserialize()); \
}
이 매크로는 사용자 정의 형식에 두 개의 구성원 함수를 추가했습니다:serialize와 Unserialize입니다. 사용자 정의 템플릿 구성원 함수인 SerializationOp을 내부에서 호출합니다. SerializationOp 함수 내부에서는 주로 READWRITE와 READWRITEMANY 매크로를 사용하여 사용자 정의 형식의 모든 데이터 구성원에 대한 서열화와 반서열화를 완성합니다.
#define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action))
#define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
struct CSerActionSerialize
{
constexpr bool ForRead() const { return false; }
};
struct CSerActionUnserialize
{
constexpr bool ForRead() const { return true; }
};
template
inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action)
{
::Serialize(s, obj);
}
template
inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
{
::Unserialize(s, obj);
}
template
inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
{
::SerializeMany(s, std::forward(args)...);
}
template
inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
{
::UnserializeMany(s, args...);
}
사용자 정의 유형 내부에 ADD 추가 필요SERIALIZE_METHODS 호출, 확대 후:
template \
void Serialize(Stream& s) const { \
NCONST_PTR(this)->SerializationOp(s, CSerActionSerialize()); \
} \
template \
void Unserialize(Stream& s) { \
SerializationOp(s, CSerActionUnserialize()); \
}
이 매크로는 사용자 정의 형식에 두 개의 구성원 함수를 추가했다.
Serialize
와 Unserialize
매크로는 사용자 정의 템플릿 구성원 함수SerializationOp
를 내부 호출하고 SerializationOp
함수 내부에서 주로 READWRITE
와 READWRITEMANY
매크로를 사용하며 사용자 정의 형식의 모든 데이터 구성원에 대한 서열화와 반서열화를 완성했다.#define READWRITE(obj) (::SerReadWrite(s, (obj), ser_action))
#define READWRITEMANY(...) (::SerReadWriteMany(s, ser_action, __VA_ARGS__))
struct CSerActionSerialize
{
constexpr bool ForRead() const { return false; }
};
struct CSerActionUnserialize
{
constexpr bool ForRead() const { return true; }
};
template
inline void SerReadWrite(Stream& s, const T& obj, CSerActionSerialize ser_action)
{
::Serialize(s, obj);
}
template
inline void SerReadWrite(Stream& s, T& obj, CSerActionUnserialize ser_action)
{
::Unserialize(s, obj);
}
template
inline void SerReadWriteMany(Stream& s, CSerActionSerialize ser_action, Args&&... args)
{
::SerializeMany(s, std::forward(args)...);
}
template
inline void SerReadWriteMany(Stream& s, CSerActionUnserialize ser_action, Args&... args)
{
::UnserializeMany(s, args...);
}
여기서 SerReadWrite와 SerReadWriteMany는 각각 두 개의 오버로드가 이루어졌는데 그 차이는 마지막에 각각 다른 유형
CSerActionSerialize
과 CSerActionUnserialize
이 전해졌고 형삼seraction은 내부에서 사용하지 않고 관련 자료를 찾아봤습니다. 여기는 c++ 일반 프로그래밍에서 자주 사용하는 모델을 사용했습니다.tag dispatch 기술] (https://akrzemi1.wordpress.co...다른 설명: [https://arne-mertz.de/2016/10...://arne-mertz.de/2016/10/tag-dispatch/),
서로 다른 유형을 가지고 번역할 때 서로 다른 오버로드를 선택하여 실현하고 CserActionserialize는 서열화에 대응하며 CserActionUnserialize는 반서열화에 대응한다.
SerializeMany
와 SerializeMany
는 길어진 템플릿 파라메터 패키지 전개 기술을 통해 이루어진 것으로 SerializeMany
를 예로 들 수 있다.
template
void SerializeMany(Stream& s)
{
}
template
void SerializeMany(Stream& s, Arg&& arg)
{
::Serialize(s, std::forward(arg));
}
template
void SerializeMany(Stream& s, Arg&& arg, Args&&... args)
{
::Serialize(s, std::forward(arg));
::SerializeMany(s, std::forward(args)...);
}
SerializeMany
세 개의 오버로드가 실현되고 위에서 쓰러진다고 가정하면 각각 1, 2, 3이다.두 개 이상의 실참이 들어오면 컴파일러가 버전 3을 선택하고 버전 3 내부에서parameter 패키지에서 파라미터를 팝업해서 버전 2에 호출하고 나머지 파라미터 목록은 버전 3에 전송하며, 다시 호출하고parameter 패키지가 비어 있을 때까지 버전 1을 선택합니다.이렇게 길게 우회하면 최종 서열화는 전역 명칭 공간
Serialize
을 사용하여 이루어지고 반서열화는 호출Unserialize
을 통해 이루어진다.Serialize
와Unserialize
또 한 무더기의 오버로드가 실현되었다. 비트코인 작가는 흔히 볼 수 있는 유형의 템플릿 특화를 실현했다. 예를 들어 std:::string, 주로 스크립트를 디자인하는 prevector,std:vector,std::pair,std:::map,std:::set,std:::uniqueptr, std::share_ptr . c++의 템플릿 매칭은 매개 변수 목록의 매칭 정도에 따라 다른 실현을 선택하고 정확하고 정확하게 우선하며 마지막으로 유형 T의 구성원 함수를 선택하여 실현한다.template
inline void Serialize(Stream& os, const T& a)
{
a.Serialize(os);
}
template
inline void Unserialize(Stream& is, T& a)
{
a.Unserialize(is);
}
string,map,set,vector,prevector 등 여러 요소를 포함할 수 있는 집합 형식을 서열화할 때 내부적으로
ReadCompactSize
와 WriteCompactSize
를 호출하여 인코딩된 요소의 개수를 읽습니다.template
void WriteCompactSize(Stream& os, uint64_t nSize)
{
if (nSize < 253)
{
ser_writedata8(os, nSize);
}
else if (nSize <= std::numeric_limits::max())
{
ser_writedata8(os, 253);
ser_writedata16(os, nSize);
}
else if (nSize <= std::numeric_limits::max())
{
ser_writedata8(os, 254);
ser_writedata32(os, nSize);
}
else
{
ser_writedata8(os, 255);
ser_writedata64(os, nSize);
}
return;
}
template
uint64_t ReadCompactSize(Stream& is)
{
uint8_t chSize = ser_readdata8(is);
uint64_t nSizeRet = 0;
if (chSize < 253)
{
nSizeRet = chSize;
}
else if (chSize == 253)
{
nSizeRet = ser_readdata16(is);
if (nSizeRet < 253)
throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
else if (chSize == 254)
{
nSizeRet = ser_readdata32(is);
if (nSizeRet < 0x10000u)
throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
else
{
nSizeRet = ser_readdata64(is);
if (nSizeRet < 0x100000000ULL)
throw std::ios_base::failure("non-canonical ReadCompactSize()");
}
if (nSizeRet > (uint64_t)MAX_SIZE)
throw std::ios_base::failure("ReadCompactSize(): size too large");
return nSizeRet;
}
비트폭 1,2,4,8의 기초 유형에 대한
Serialize
와Unserialize
최종 호출serwritedata, ser_readdata8 완성 실현.template inline void Serialize(Stream& s, char a ) { ser_writedata8(s, a); } // TODO Get rid of bare char
template inline void Serialize(Stream& s, int8_t a ) { ser_writedata8(s, a); }
template inline void Serialize(Stream& s, uint8_t a ) { ser_writedata8(s, a); }
template inline void Serialize(Stream& s, int16_t a ) { ser_writedata16(s, a); }
template inline void Serialize(Stream& s, uint16_t a) { ser_writedata16(s, a); }
template inline void Serialize(Stream& s, int32_t a ) { ser_writedata32(s, a); }
template inline void Serialize(Stream& s, uint32_t a) { ser_writedata32(s, a); }
template inline void Serialize(Stream& s, int64_t a ) { ser_writedata64(s, a); }
template inline void Serialize(Stream& s, uint64_t a) { ser_writedata64(s, a); }
template inline void Serialize(Stream& s, float a ) { ser_writedata32(s, ser_float_to_uint32(a)); }
template inline void Serialize(Stream& s, double a ) { ser_writedata64(s, ser_double_to_uint64(a)); }
template inline void Unserialize(Stream& s, char& a ) { a = ser_readdata8(s); } // TODO Get rid of bare char
template inline void Unserialize(Stream& s, int8_t& a ) { a = ser_readdata8(s); }
template inline void Unserialize(Stream& s, uint8_t& a ) { a = ser_readdata8(s); }
template inline void Unserialize(Stream& s, int16_t& a ) { a = ser_readdata16(s); }
template inline void Unserialize(Stream& s, uint16_t& a) { a = ser_readdata16(s); }
template inline void Unserialize(Stream& s, int32_t& a ) { a = ser_readdata32(s); }
template inline void Unserialize(Stream& s, uint32_t& a) { a = ser_readdata32(s); }
template inline void Unserialize(Stream& s, int64_t& a ) { a = ser_readdata64(s); }
template inline void Unserialize(Stream& s, uint64_t& a) { a = ser_readdata64(s); }
template inline void Unserialize(Stream& s, float& a ) { a = ser_uint32_to_float(ser_readdata32(s)); }
template inline void Unserialize(Stream& s, double& a ) { a = ser_uint64_to_double(ser_readdata64(s)); }
template inline void Serialize(Stream& s, bool a) { char f=a; ser_writedata8(s, f); }
template inline void Unserialize(Stream& s, bool& a) { char f=ser_readdata8(s); a=f; }
그리고 코드가 시작되는 곳의
struct deserialize_type {};
constexpr deserialize_type deserialize {};
tag 유형으로서 tag 대상은 주로 여러 개의 실현 서명에 다음과 같은 형식이 있다.
template
T::T(deserialize_type, Stream& s)
Ctransaction, CMutable Transaction 유형:
template
CTransaction(deserialize_type, Stream& s) : CTransaction(CMutableTransaction(deserialize, s)) {}
template
CMutableTransaction(deserialize_type, Stream& s) {
Unserialize(s);
}
원본 주소:https://mp.weixin.qq.com/s/_fhGCfkI0sT3fasSKWqdPA
본문은
Copernicus
에 작성되었고 전재는 권한을 부여할 필요가 없다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
비트코인 재정 거래의 기회를 시각화GitHub Pages에서 비트코인 재정 기회를 시각화하는 사이트를 만들었습니다. 이 스크린 샷의 순간은 Bitflyer에서 1.75 BTC를 471,109 엔으로 사고 Quoine에서 1.75 BTC를 475,04...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.