void Payload_Reject::deserialize(uint8_t* dataptr, size_t len) { uint64_t typeLen; auto remaining = len; auto varintlen = get_varint(typeLen, dataptr, len); auto ptr = dataptr + varintlen; remaining -= (varintlen + typeLen + 1); string msgtype((char*)ptr, typeLen); auto typeIter = BitcoinP2P::strToPayload_.find(msgtype); if (typeIter == BitcoinP2P::strToPayload_.end()) throw BitcoinMessageDeserError("unknown reject type"); rejectType_ = typeIter->second; ptr += typeLen; code_ = (char)*ptr; ptr++; uint64_t reasonLen; varintlen = get_varint(reasonLen, ptr, len); ptr += varintlen; remaining -= (reasonLen + varintlen); reasonStr_ = move(string((char*)ptr, reasonLen)); ptr += reasonLen; if (remaining == 32) extra_.resize(32); memcpy(&extra_[0], ptr, 32); }
void Payload_GetData::deserialize(uint8_t* dataptr, size_t len) { uint64_t invCount; auto varintlen = get_varint(invCount, dataptr, len); if (invCount > INV_MAX) throw BitcoinMessageDeserError("inv count > INV_MAX"); invVector_.resize(invCount); auto ptr = dataptr + varintlen; auto remaining = len - varintlen; for (auto& entry : invVector_) { if (remaining < INV_ENTRY_LEN) throw BitcoinMessageDeserError("inv deser size mismatch"); auto entrytype = *(uint32_t*)(ptr); if ((entrytype & ~Inv_Witness) > 3) throw BitcoinMessageDeserError("invalid inv entry type"); entry.invtype_ = (InvType)entrytype; memcpy(entry.hash, ptr + 4, 32); remaining -= INV_ENTRY_LEN; ptr += INV_ENTRY_LEN; } }
unsigned long UnMarshaller::get_varint() { bool done; unsigned long val = get_varint(&done); if(!done) { std::ostringstream msg; msg << "Unable to unmarshal variable length integer: exceeds " << sizeof(long) << " bytes"; Exception::type_error(state, msg.str().c_str()); } return val; }
void Payload_Version::deserialize(uint8_t* data, size_t len) { uint8_t* dataptr = data; vheader_.version_ = *(uint32_t*)dataptr; dataptr += 4; vheader_.services_ = *(uint64_t*)dataptr; dataptr += 8; vheader_.timestamp_ = *(int64_t*)dataptr; dataptr += 8; vheader_.addr_recv_.services_ = *(uint64_t*)dataptr; dataptr += 8; memcpy(vheader_.addr_recv_.ipV6_, dataptr, 16); dataptr += 16; vheader_.addr_recv_.port_ = *(uint16_t*)dataptr; dataptr += 2; vheader_.addr_from_.services_ = *(uint64_t*)dataptr; dataptr += 8; memcpy(vheader_.addr_from_.ipV6_, dataptr, 16); dataptr += 16; vheader_.addr_from_.port_ = *(uint16_t*)dataptr; dataptr += 2; vheader_.nonce_ = *(uint64_t*)dataptr; dataptr += 8; size_t remaining = len - MESSAGE_HEADER_LEN - USERAGENT_OFFSET; uint64_t uaLen; auto varintlen = get_varint(uaLen, dataptr, remaining); dataptr += varintlen; char* userAgentPtr = (char*)(dataptr); userAgent_ = string(userAgentPtr, uaLen); dataptr += uaLen; startHeight_ = *(uint32_t*)dataptr; }
Object* UnMarshaller::get_positive_varint() { bool done; unsigned long val = get_varint(&done); bool is_fixnum = done; mp_int mp_val; // do we need to switch to bignum math? if(!done) { int shift = sizeof(long) * 7; mp_int a; mp_init_set_int(&mp_val, val); mp_init(&a); #if (__WORDSIZE == 64) // mp_(init_)set_int can only deal with 32 bit values, // so the above call only copied the lower 32 bits of _val_. // Handle the upper 32 bits as well: mp_set_int(&a, val >> 32); mp_mul_2d(&a, 32, &a); mp_add(&a, &mp_val, &mp_val); #endif while(!done) { unsigned int byte = stream.get(); mp_set_int(&a, byte & ~128); mp_mul_2d(&a, shift, &a); mp_add(&a, &mp_val, &mp_val); shift += 7; done = byte < 128; } mp_clear(&a); }