Skip to main content

Module types

Module types 

Source
Expand description

Graphene wire-format primitives.

Everything Hive signs is a byte string produced by these encoders, so a divergence here does not fail loudly — it produces a valid-looking signature over the wrong bytes, which the chain then rejects. That makes this the highest-risk module in the crate and the one the differential digest oracle in tests/ targets hardest.

§Fixes relative to beem

§String matches what hived’s JSON parser produces — beem was right

This section previously claimed the opposite, and the crate’s published findings said so too. It was wrong, and the correction is worth keeping visible.

beem’s String.__bytes__ runs the payload through unicodify():

if (o <= 7) or (o == 11) or (o > 13 and o < 32):
    r.append("u%04x" % o)      # note: no backslash
elif o == 8:  r.append("b")    # note: no backslash
elif o == 12: r.append("f")    # note: no backslash

The missing backslashes read as an obvious defect. They are not. Hive is reached over JSON-RPC, and hived parses that JSON with fc, which does not implement the \uXXXX, \b or \f escapes – it strips the backslash and keeps the rest literally. Asked to serialize a comment whose body is the three characters x, U+0001, y, a live node returns the bytes for the seven characters xu0001y.

So unicodify is a model of the transport, and it is an exact one: measured against a node, hived mangles precisely the set beem lists – everything under 0x20 except \t, \n and \r, with 0x08 and 0x0c collapsing to b and f.

Writing raw UTF-8, which this crate did until the node was asked, yields a digest hived does not compute and a signature it rejects. write_string now applies the same transform.

§Length prefixes count bytes, and are bounded

beem computed varint(len(d)) where d was already the encoded bytes, which is correct, but nothing anywhere bounded the length. A String longer than u32::MAX would silently truncate through the varint. We return an error.

§Timestamps are parsed strictly, in UTC

beem’s PointInTime appended the literal text "UTC" to the input and parsed with %Y-%m-%dT%H:%M:%S%Z, and in the datetime branch called timegm(d.timetuple()), which reads a timezone-aware, non-UTC datetime as though its wall-clock fields were UTC. That silently shifts a transaction’s expiration by the UTC offset. Here there is one representation — seconds since the Unix epoch, UTC — and parsing is strict.

§Validation is not assert

beem validated hash lengths with bare assert statements (Sha256, Ripemd160, Sha1 in types.py). Python strips those under -O, so the length checks vanish in an optimised deployment. These are ordinary checked errors.

Structs§

PointInTime
A point in time on the Graphene wire: uint32 seconds since the Unix epoch, UTC.

Traits§

GrapheneSerialize
Anything that can be written in Graphene wire format.

Functions§

read_varint32
Read a LEB128 varint, returning the value and the number of bytes consumed.
write_array
Write an array: varint element count, then each element.
write_bool
Write a bool as one byte: 0 or 1. hived rejects any other value.
write_bytes
Write a length-prefixed byte buffer.
write_i16
Write a signed 16-bit integer, little-endian (vote weights).
write_i64
Write a signed 64-bit integer, little-endian (asset amounts).
write_optional
Write an optional<T>: a presence byte, then the value if present.
write_raw
Write a fixed-width byte array with no length prefix (hashes, chain ids).
write_static_variant
Write a static_variant: varint type tag, then the value.
write_string
Write a Graphene string: varint byte length, then the UTF-8 bytes.
write_u8
Write one byte.
write_u16
Write an unsigned 16-bit integer, little-endian.
write_u32
Write an unsigned 32-bit integer, little-endian.
write_u64
Write an unsigned 64-bit integer, little-endian.
write_varint32
Write a LEB128 varint.