Urbit Docs
  • What is Urbit?
  • Get on Urbit
  • Build on Urbit
    • Contents
    • Environment Setup
    • Hoon School
      • 1. Hoon Syntax
      • 2. Azimuth (Urbit ID)
      • 3. Gates (Functions)
      • 4. Molds (Types)
      • 5. Cores
      • 6. Trees and Addressing
      • 7. Libraries
      • 8. Testing Code
      • 9. Text Processing I
      • 10. Cores and Doors
      • 11. Data Structures
      • 12. Type Checking
      • 13. Conditional Logic
      • 14. Subject-Oriented Programming
      • 15. Text Processing II
      • 16. Functional Programming
      • 17. Text Processing III
      • 18. Generic and Variant Cores
      • 19. Mathematics
    • App School I
      • 1. Arvo
      • 2. The Agent Core
      • 3. Imports and Aliases
      • 4. Lifecycle
      • 5. Cards
      • 6. Pokes
      • 7. Structures and Marks
      • 8. Subscriptions
      • 9. Vanes
      • 10. Scries
      • 11. Failure
      • 12. Next Steps
      • Appendix: Types
    • App School II (Full-Stack)
      • 1. Types
      • 2. Agent
      • 3. JSON
      • 4. Marks
      • 5. Eyre
      • 6. React app setup
      • 7. React app logic
      • 8. Desk and glob
      • 9. Summary
    • Core Academy
      • 1. Evaluating Nock
      • 2. Building Hoon
      • 3. The Core Stack
      • 4. Arvo I: The Main Sequence
      • 5. Arvo II: The Boot Sequence
      • 6. Vere I: u3 and the Serf
      • 7. Vere II: The Loom
      • 8. Vanes I: Behn, Dill, Kahn, Lick
      • 9. Vanes II: Ames
      • 10. Vanes III: Eyre, Iris
      • 11. Vanes IV: Clay
      • 12. Vanes V: Gall and Userspace
      • 13. Vanes VI: Khan, Lick
      • 14. Vanes VII: Jael, Azimuth
    • Runtime
      • U3
      • Conn.c Guide
      • How to Write a Jet
      • API Overview by Prefix
      • C in Urbit
      • Cryptography
      • Land of Nouns
    • Tools
      • Useful Links
      • JS Libraries
        • HTTP API
      • Docs App
        • File Format
        • Index File
        • Suggested Structure
    • Userspace
      • Command-Line App Tutorial
      • Remote Scry
      • Unit Tests
      • Software Distribution
        • Software Distribution Guide
        • Docket File
        • Glob
      • Examples
        • Building a CLI App
        • Debugging Wrapper
        • Host a Website
        • Serving a JS Game
        • Ship Monitoring
        • Styled Text
  • Urbit ID
    • What is Urbit ID?
    • Azimuth Data Flow
    • Life and Rift
    • Urbit HD Wallet
    • Advanced Azimuth Tools
    • Custom Roller Tutorial
    • Azimuth.eth Reference
    • Ecliptic.eth Reference
    • Layer 2
      • L2 Actions
      • L2 Rollers
      • L2 Roller HTTP RPC-API
      • L2 Transaction Format
  • Urbit OS
    • What is Urbit OS?
    • Base
      • Hood
      • Threads
        • Basics Tutorial
          • Bind
          • Fundamentals
          • Input
          • Output
          • Summary
        • HTTP API Guide
        • Spider API Reference
        • Strandio Reference
        • Examples
          • Child Thread
          • Fetch JSON
          • Gall
            • Poke Thread
            • Start Thread
            • Stop Thread
            • Take Facts
            • Take Result
          • Main-loop
          • Poke Agent
          • Scry
          • Take Fact
    • Kernel
      • Arvo
        • Cryptography
        • Move Trace
        • Scries
        • Subscriptions
      • Ames
        • Ames API Reference
        • Ames Cryptography
        • Ames Data Types
        • Ames Scry Reference
      • Behn
        • Behn API Reference
        • Behn Examples
        • Behn Scry Reference
      • Clay
        • Clay API Reference
        • Clay Architecture
        • Clay Data Types
        • Clay Examples
        • Clay Scry Reference
        • Filesystem Hierarchy
        • Marks
          • Mark Examples
          • Using Marks
          • Writing Marks
        • Using Clay
      • Dill
        • Dill API Reference
        • Dill Data Types
        • Dill Scry Reference
      • Eyre
        • EAuth
        • Eyre Data Types
        • Eyre External API
        • Eyre Internal API
        • Eyre Scry Reference
        • Low-Level Eyre Guide
        • Noun channels
      • Gall
        • Gall API Reference
        • Gall Data Types
        • Gall Scry Reference
      • Iris
        • Iris API Reference
        • Iris Data Types
        • Iris Example
      • Jael
        • Jael API Reference
        • Jael Data Types
        • Jael Examples
        • Jael Scry Reference
      • Khan
        • Khan API Reference
        • Khan Data Types
        • Khan Example
      • Lick
        • Lick API Reference
        • Lick Guide
        • Lick Examples
        • Lick Scry Reference
  • Hoon
    • Why Hoon?
    • Advanced Types
    • Arvo
    • Auras
    • Basic Types
    • Cheat Sheet
    • Cryptography
    • Examples
      • ABC Blocks
      • Competitive Programming
      • Emirp
      • Gleichniszahlenreihe
      • Islands
      • Luhn Number
      • Minimum Path Sum
      • Phone Letters
      • Restore IP
      • Rhonda Numbers
      • Roman Numerals
      • Solitaire Cipher
      • Water Towers
    • Generators
    • Hoon Errors
    • Hoon Style Guide
    • Implementing an Aura
    • Irregular forms
    • JSON
    • Limbs and wings
      • Limbs
      • Wings
    • Mips (Maps of Maps)
    • Parsing Text
    • Runes
      • | bar · Cores
      • $ buc · Structures
      • % cen · Calls
      • : col · Cells
      • . dot · Nock
      • / fas · Imports
      • ^ ket · Casts
      • + lus · Arms
      • ; mic · Make
      • ~ sig · Hints
      • = tis · Subject
      • ? wut · Conditionals
      • ! zap · Wild
      • Constants (Atoms and Strings)
      • --, == · Terminators
    • Sail (HTML)
    • Serialization
    • Sets
    • Standard Library
      • 1a: Basic Arithmetic
      • 1b: Tree Addressing
      • 1c: Molds and Mold-Builders
      • 2a: Unit Logic
      • 2b: List Logic
      • 2c: Bit Arithmetic
      • 2d: Bit Logic
      • 2e: Insecure Hashing
      • 2f: Noun Ordering
      • 2g: Unsigned Powers
      • 2h: Set Logic
      • 2i: Map Logic
      • 2j: Jar and Jug Logic
      • 2k: Queue Logic
      • 2l: Container from Container
      • 2m: Container from Noun
      • 2n: Functional Hacks
      • 2o: Normalizing Containers
      • 2p: Serialization
      • 2q: Molds and Mold-Builders
      • 3a: Modular and Signed Ints
      • 3b: Floating Point
      • 3c: Urbit Time
      • 3d: SHA Hash Family
      • 3e: AES encryption (Removed)
      • 3f: Scrambling
      • 3g: Molds and Mold-Builders
      • 4a: Exotic Bases
      • 4b: Text Processing
      • 4c: Tank Printer
      • 4d: Parsing (Tracing)
      • 4e: Parsing (Combinators)
      • 4f: Parsing (Rule-Builders)
      • 4g: Parsing (Outside Caller)
      • 4h: Parsing (ASCII Glyphs)
      • 4i: Parsing (Useful Idioms)
      • 4j: Parsing (Bases and Base Digits)
      • 4k: Atom Printing
      • 4l: Atom Parsing
      • 4m: Formatting Functions
      • 4n: Virtualization
      • 4o: Molds
      • 5a: Compiler Utilities
      • 5b: Macro Expansion
      • 5c: Compiler Backend & Prettyprinter
      • 5d: Parser
      • 5e: Molds and mold builders
      • 5f: Profiling support
    • Strings
    • The Engine Pattern
    • Udon (Markdown-esque)
    • Vases
    • Zuse
      • 2d(1-5): To JSON, Wains
      • 2d(6): From JSON
      • 2d(7): From JSON (unit)
      • 2e(2-3): Print & Parse JSON
      • 2m: Ordered Maps
  • Nock
    • What is Nock?
    • Decrement
    • Definition
    • Fast Hints and Jets
    • Implementations
    • Specification
  • User Manual
    • Contents
    • Running Urbit
      • Cloud Hosting
      • Home Servers
      • Runtime Reference
      • Self-hosting S3 Storage with MinIO
    • Urbit ID
      • Bridge Troubleshooting
      • Creating an Invite Pool
      • Get an Urbit ID
      • Guide to Factory Resets
      • HD Wallet (Master Ticket)
      • Layer 2 for planets
      • Layer 2 for stars
      • Proxies
      • Using Bridge
    • Urbit OS
      • Basics
      • Configuring S3 Storage
      • Dojo Tools
      • Filesystem
      • Shell
      • Ship Troubleshooting
      • Star and Galaxy Operations
      • Updates
Powered by GitBook

GitHub

  • Urbit ID
  • Urbit OS
  • Runtime

Resources

  • YouTube
  • Whitepaper
  • Awesome Urbit

Contact

  • X
  • Email
  • Gather
On this page
  • Byte format
  • Batches
  • Actions
  • Unsigned transactions
  • Signatures
Edit on GitHub
  1. Urbit ID
  2. Layer 2

L2 Transaction Format

This document gives the bytestring format for layer 2 transactions and batches.

Recall that a layer 2 transaction is a compact representation of an Azimuth action (format given below), along with a 65-byte ECDSA signature. A batch is an atom that is a concatenation of one or more layer 2 transactions and associated signatures. This atom is what is posted on the Ethereum blockchain by a roller.

We remark that each transaction from a given ship in a batch needs a separate signature, since data such as the nonce are not included in the transaction but are used in the signature. Thus a ship cannot submit multiple transactions with a single signature for all of them - a different signature is needed for each transaction.

Byte format

We describe the byte format of a batch and its components in the following. All atoms described here are read by the parser as little-endian - i.e. it reads the last digit first and proceeds backwards.

For the purposes of concatenation, all atoms are encoded using octs=(pair @ud @), which is a way to represent atoms with a fixed width in order to account for leading zeroes. Here @ud will be the length of the atom in bytes, while the @ is actual atom.

Batches

A batch is an atom that is the concatenation of several raw transactions, which are themselves atoms. naive.hoon starts reading the batch from the end and working backwards (little-endian). A batch looks like:

action-n
signature-n
action-(n-1)
signature-(n-1)
...
action-2
signature-2
action-1
signature-1

Be careful to distinguish between an "action" and an "unsigned transaction". An action is a short bytestring that describes an Azimuth action as given in the following section, while an unsigned transaction is an action plus the nonce, chain ID, header. Actions are what are submitted to Ethereum, while unsigned transactions are what are signed and used as the signatures in the above batch format. When naive.hoon parses a batch it adds the appropriate nonce, chain ID, and header to a given action and uses that to verify the corresponding signature, rather than just the action itself. This reduces the number of bytes in the batch, making transactions cheaper.

Actions

The byte format of an action as they appear in a batch is as follows. They are parsed by the +parse-tx arm in naive.hoon.

remainder: arguments
7 bits: operation
4 bytes: ship sending the transaction
5 bits: padding
3 bits: proxy

The proxy is an atom between 0 and 4, which corresponds as follows:

%0  %own
%1  %spawn
%2  %manage
%3  %vote
%4  %transfer

Note that %vote proxies are not supported by layer 2.

The ship is its @p encoded as an @. As we are working with fixed width atoms, the full 4 bytes is used, even if the bit length of the @p is shorter.

The operation is an atom between 0 and 10 corresponding as follows:

%0   %transfer-point
%1   %spawn
%2   %configure-keys
%3   %escape
%4   %cancel-escape
%5   %adopt
%6   %reject
%7   %detach
%8   %set-management-proxy
%9   %set-spawn-proxy
%10  %set-transfer-proxy

Since the operation is represented with 7 bits, to complete the byte the arguments either use the remaining bit as a binary flag or as padding.

%transfer-point

20 bytes: address to transfer to
1 bit: breach?

%spawn

As before, the length of the ship argument is always 4 bytes.

20 bytes: address to set transfer proxy of spawned ship to
4 bytes: ship to spawn
1 bit: padding

%configure-keys

4 bytes: crypto suite
32 bytes: encryption public key
32 bytes: authentication public key
1 bit: breach?

%escape, %cancel-escape, %adopt, %reject, %detach

Each of these actions have the same argument - a single ship. Again, the length of the ship argument is always 4 bytes.

4 bytes: ship
1 bit: padding

%set-management-proxy, %set-spawn-proxy, %set-transfer-proxy

Each of these actions have the same argument - an Ethereum address:

20 bytes: address
1 bit: padding

Unsigned transactions

An unsigned transaction is an atom consisting of the concatentation of an Ethereum signed message header, an Urbit ID header, a chain ID, a nonce, and an action. This has the following format:

%:  cad  3
  26^'\19Ethereum Signed Message:\0a'
  (met 3 len)^len
  14^'UrbitIDV1Chain'
  (met 3 chain-t)^chain-t
  1^':'
  4^nonce
  action
  ~
==

Here +cad is a gate in /lib/tiny.hoon that concatenates atoms given in octs format. The argument 3 is a bloq size meaning 2^3=8 bits (one byte), and the head of each cell (which are octs) in the arguments that follow is the number of blocks (number of bytes in this scenario) of each entry, with the tail being the actual data.

len is the length measured in bytes of everything following it except the signature. chain-t is the chain ID, which is to distinguish between e.g. the Ethereum test net and main net, to ensure that transaction used in one cannot be rebroadcast on the other (see EIP-155). We note that len and chain-t are both ASCII decimals (@t in Hoon), while nonce and action are @uds.

Again we emphasize that unsigned transactions are not what is submitted in a batch - an action and a signature are. A ship submitting a layer 2 transaction to a roller signs an unsigned transaction and this signature is included along with the action, which does not include the additional data listed above. When a ship determines whether or not a given layer 2 action is valid, it adds the additional data to the action to form an unsigned transaction and verifies the signature against that.

Signatures

The signature is a 65-byte ECDSA signature as described in EIP-191 and is compatible with personal_sign. The precise format of the signature depends on which wallet was used to sign it. Layer 2 supports all major signature formats, including Metamask, Trezor, Ledger, and others. Signatures in batches are obtained by signing an unsigned transaction.

Because of the format of signatures, it may have leading zeroes resulting in a 64-byte signature, and so it is important to use octs to ensure that it is interpreted as being 65 bytes.

PreviousL2 Roller HTTP RPC-APINextWhat is Urbit OS?

Last updated 1 day ago