Beyond Jets: Microcode: Consensus-Critical Jets Without Softforks



Summary:

In a bitcoin-dev mailing list, ZmnSCPxj has proposed the use of microcodes as a means of enabling new functionality in the Bitcoin consensus layer. The proposal suggests defining a generic, low-level language as the base language and mapping specific high-level languages to it. This will enable existing Bitcoin SCRIPT `OP_` codes to be mapped to one or more `UOP_` micro-opcodes. A default microcode equivalent to the current Bitcoin language would be provided, and users can define a new microcode to implement new or change existing `OP_` codes. ZmnSCPxj also addresses issues with namespace management, particularly in his Simplicity design. In this design, the commitment of a Simplicity program in a scriptpubkey covers the hash of the specification of the jets used, which makes commits unambiguously to the semantics. However, the issue resurfaces at redemption time where he has a consensus critical map of codes to jets that is used to decode the witness data into a Simplicity program. If one were to allow this map of codes to jets to be replaced (rather than just extended) then it would cause redemption to fail.The proposal further explains how Bitcoin fullnode implementations are not very soft because of the need for consensus, and thus should be considered as hardware that other Bitcoin software and layers run on top of. This opens up the thought of using techniques useful in hardware design, such as microcode: a translation layer from "old" instruction sets to "new" instruction sets, with the ability to modify this mapping.In another development, a Bitcoin developer has proposed a new method for enabling the previously disabled OP_CAT opcode in Bitcoin Script while avoiding security issues. The proposal involves creating a new microcode that redefines OP_CAT as UOP_CAT, and then serializing it into a byte sequence before burning Bitcoins in an output that contains the scriptPubKey of OP_TRUE OP_RETURN. Once confirmed, the user can use a SCRIPT with OP_CAT enabled by using a Tapscript with version 0xce and the microcode hash as its first bytes followed by the OP codes. Full nodes will process recognized microcode introduction outputs and store mappings from their hashes to the microcodes in a new microcodes index. Full nodes can then process version-0xce Tapscripts by checking if the microcodes index has the indicated microcode hash.To execute the defined microcode faster than expanding an OP-code SCRIPT to a UOP-code SCRIPT and having an interpreter loop over the UOP-code SCRIPT, the proposal suggests using LLVM. Each UOP-code has an equivalent tree of LLVM code, and each Opcode in the microcode is expanded to this tree, concatenating the equivalent trees for each UOpcode in the sequence. Then LLVM is asked to JIT-compile this code to a new function, running LLVM-provided optimizers, and a pointer to this compiled function is put into a 256-long array of functions where the array index is the OP code.The technique allows users to define "jets," i.e., sequences of low-level general operations determined to be common enough to be implemented as faster code executed directly by the underlying hardware processor rather than via a software interpreter. Bugs in existing microcodes can be fixed by basing a new microcode from the existing one and redefining the buggy implementation. Existing Tapscripts need to be re-spent to point to the new bugfixed microcode.In order to ensure that the JIT-compilation of new microcodes is not triggered trivially, users petitioning for the jettification of some operations must sacrifice Bitcoins. Burning Bitcoins is better than increasing the weight of microcode introduction outputs, and all full nodes are affected by the need to JIT-compile the new microcode, so they benefit from the reduction in supply thus getting compensated for the work of JIT-compiling the new microcode.


Updated on: 2023-06-15T18:18:47.222695+00:00