View in context in the libbitcoin Slack #general mirror.
chain:: object model. All objects, down to op.data stored on std::share_ptr<> instances. Then to serialize out the entire object model is walked on a system::ostream to create a single buffer. For text (hex) encoding the buffer is then translated to hex using system::base16_encode. For json the object modal is walked directly by boost::json.
For wire/text there is really no need whatsoever to translated through the normal form (object model). The wire serialization can be trivially produced directly onto the stream from store serialization. This would bypass countless allocations and copies. Scripts and witnesses for example, making up the bulk of all data, do not even require parse, they can just be written to the stream. (Though it would certainly be cleaner if no for the tragic segwit decision to serialize witnesses independently from inputs.) I'd estimate that this would cut large block deserialization time in half, and on my old machine that would put it under 20ms.