9 #include "scale/scale.hpp" 10 #include "scale/scale_decoder_stream.hpp" 18 case E::TOO_MANY_NIBBLES:
19 return "number of nibbles in key is >= 2**16";
20 case E::UNKNOWN_NODE_TYPE:
21 return "unknown polkadot node type";
22 case E::INPUT_TOO_SMALL:
23 return "not enough bytes in the input to decode a node";
24 case E::NO_NODE_VALUE:
25 return "no value in leaf node";
35 out[1] = (b >> 8u) & 0xffu;
52 const auto size =
static_cast<size_t>(buf.size());
72 switch (static_cast<TrieNode::Type>(node.
getType())) {
74 return encodeLeaf(dynamic_cast<const LeafNode &>(node));
78 return encodeBranch(dynamic_cast<const BranchNode &>(node),
82 return encodeLeaf(dynamic_cast<const LeafNode &>(node));
85 return encodeBranch(dynamic_cast<const BranchNode &>(node),
89 return std::errc::invalid_argument;
92 return std::errc::invalid_argument;
96 return std::errc::invalid_argument;
99 return std::errc::invalid_argument;
110 uint8_t partial_length_mask;
116 partial_length_mask = 0b00'111111;
120 partial_length_mask = 0b00'111111;
124 partial_length_mask = 0b00'111111;
128 partial_length_mask = 0b000'11111;
132 partial_length_mask = 0b0000'1111;
136 partial_length_mask = 0;
140 partial_length_mask = 0;
147 if (node.
key_nibbles.size() < partial_length_mask) {
153 head += partial_length_mask;
155 size_t l = node.
key_nibbles.size() - partial_length_mask;
165 out[out.size() - 1] = l % 0xffu;
183 OUTCOME_TRY(encNodeValue, scale::encode(node.
value.value()));
184 encoding +=
Buffer(std::move(encNodeValue));
190 if (
auto dummy = std::dynamic_pointer_cast<DummyNode>(child);
192 auto merkle_value = dummy->db_key;
193 OUTCOME_TRY(scale_enc, scale::encode(std::move(merkle_value)));
194 encoding.put(scale_enc);
199 OUTCOME_TRY(store_children(merkle, std::move(enc)));
201 OUTCOME_TRY(scale_enc, scale::encode(merkle));
202 encoding.put(scale_enc);
207 return outcome::success(std::move(encoding));
219 OUTCOME_TRY(encNodeValue, scale::encode(node.
value.value()));
220 encoding +=
Buffer(std::move(encNodeValue));
222 return outcome::success(std::move(encoding));
226 gsl::span<const uint8_t> encoded_data)
const {
230 auto [type, pk_length] = header;
237 OUTCOME_TRY(value, scale::decode<Buffer>(stream.leftBytes()));
238 return std::make_shared<LeafNode>(partial_key, value);
246 OUTCOME_TRY(value, scale::decode<Buffer>(stream.leftBytes()));
247 return std::make_shared<LeafContainingHashesNode>(partial_key, value);
264 outcome::result<std::pair<TrieNode::Type, size_t>>
270 auto first = stream.
next();
272 uint8_t partial_key_length_mask = 0;
273 if (first & 0b1100
'0000) { 274 if ((first >> 6 & 0b11) == 0b01) { 275 type = TrieNode::Type::Leaf; 276 } else if ((first >> 6 & 0b11) == 0b10) { 277 type = TrieNode::Type::BranchEmptyValue; 278 } else if ((first >> 6 & 0b11) == 0b11) { 279 type = TrieNode::Type::BranchWithValue; 281 BOOST_UNREACHABLE_RETURN(); 283 partial_key_length_mask = 0b00'111111;
284 }
else if (first & 0b0010
'0000) { 285 type = TrieNode::Type::LeafContainingHashes; 286 partial_key_length_mask = 0b000'11111;
287 }
else if (first & 0b0001
'0000) { 288 if (first & 0b0000'1111) {
290 partial_key_length_mask = 0b0000
'1111; 292 type = TrieNode::Type::ReservedForCompactEncoding; 294 } else if (first == 0) { 295 type = TrieNode::Type::Empty; 297 BOOST_UNREACHABLE_RETURN(); 300 // decode partial key length, which is stored in the last bits and, 301 // if it's greater than max partial key length, in the following bytes
302 size_t pk_length = first & partial_key_length_mask;
304 if (pk_length == partial_key_length_mask) {
305 uint8_t read_length = 0;
307 if (not stream.hasMore(1)) {
310 read_length = stream.next();
311 pk_length += read_length;
312 }
while (read_length == 0xFF);
314 return std::make_pair(type, pk_length);
320 auto byte_length = nibbles_num / 2 + nibbles_num % 2;
322 partial_key.
reserve(byte_length);
323 while (byte_length-- != 0) {
332 if (nibbles_num % 2 == 1) {
333 partial_key_nibbles = partial_key_nibbles.subbuffer(1);
335 return partial_key_nibbles;
342 constexpr uint8_t kChildrenBitmapSize = 2;
344 if (not stream.
hasMore(kChildrenBitmapSize)) {
347 auto node = std::make_shared<BranchNode>(partial_key);
349 uint16_t children_bitmap = stream.
next();
350 children_bitmap += stream.
next() << 8u;
352 scale::ScaleDecoderStream ss(stream.
leftBytes());
359 }
catch (std::system_error &e) {
360 return outcome::failure(e.code());
366 while (children_bitmap != 0) {
368 if ((children_bitmap & (1u << i)) != 0) {
370 children_bitmap &= ~(1u << i);
376 }
catch (std::system_error &e) {
377 return outcome::failure(e.code());
379 node->children.at(i) = std::make_shared<DummyNode>(child_hash);
Class represents arbitrary (including empty) byte buffer.
common::Buffer merkleValue(const BufferView &buf) const override
Get the merkle value of a node.
uint16_t childrenBitmap() const
OUTCOME_CPP_DEFINE_CATEGORY(kagome::storage::trie, PolkadotCodec::Error, e)
std::array< std::shared_ptr< OpaqueTrieNode >, kMaxChildren > children
outcome::result< Buffer > encodeHeader(const TrieNode &node) const
outcome::result< Buffer > encodeLeaf(const LeafNode &node) const
number of nibbles in key is >= 2**16
int blake2b(void *out, size_t outlen, const void *key, size_t keylen, const void *in, size_t inlen)
outcome::result< Buffer > encodeBranch(const BranchNode &node, const StoreChildren &store_children) const
outcome::result< std::pair< TrieNode::Type, size_t > > decodeHeader(BufferStream &stream) const
outcome::result< KeyNibbles > decodePartialKey(size_t nibbles_num, BufferStream &stream) const
virtual int getType() const =0
bool isMerkleHash(const common::BufferView &buf) const override
is this a hash of value, or value itself
auto toByteBuffer() const
SLBuffer & reserve(size_t size)
common::Buffer ushortToBytes(uint16_t b)
common::Hash256 hash256(const BufferView &buf) const override
Get the hash of a node.
outcome::result< std::shared_ptr< Node > > decodeBranch(TrieNode::Type type, const KeyNibbles &partial_key, BufferStream &stream) const
gsl::span< const uint8_t > leftBytes() const
Type getTrieType() const noexcept
SLBuffer & putUint8(uint8_t n)
Put a 8-bit {.
cannot decode a node, not enough bytes on input
static constexpr size_t size()
std::optional< common::Buffer > value
bool hasMore(index_type num_bytes) const
outcome::result< Buffer > encodeNodeAndStoreChildren(const Node &node, const StoreChildren &store_children) const override
Encode node to byte representation and store children.
outcome::result< std::shared_ptr< Node > > decodeNode(gsl::span< const uint8_t > encoded_data) const override
Decode node from bytes.
static KeyNibbles fromByteBuffer(const common::BufferView &key)
std::function< outcome::result< void >(common::BufferView, common::Buffer &&)> StoreChildren