; VERSION 0.8

; ####################
; HEADER
; ####################

HEADER-ID        = 32OCTET
HEADER           = HEADER-SIZE %x00 (HEADER-UNSIGNED / HEADER-BFT / HEADER-GP)
HEADER-SIZE      = SIZE-BYTES-16BIT
HEADER-UNSIGNED  = %x00 HEADER-COMMON
HEADER-BFT       = %x01 HEADER-COMMON CONSENSUS-BFT
HEADER-GP        = %x02 HEADER-COMMON CONSENSUS-GP
HEADER-COMMON    = CONTENT-SIZE BLOCK-DATE CHAIN-LENGTH CONTENT-ID PARENT-ID
CONTENT-SIZE     = SIZE-BYTES-32BITS
BLOCK-DATE       = BLOCK-EPOCH BLOCK-SLOT
BLOCK-EPOCH      = U32
BLOCK-SLOT       = U32
CHAIN-LENGTH     = U32
PARENT-ID        = HEADER-ID
CONSENSUS-BFT    = BFT-LEADER-ID BFT-SIGNATURE
CONSENSUS-GP     = POOL-ID VRF-OUTPUT KES-SIGNATURE

; ####################
; CONTENT
; ####################

CONTENT-ID       = 32OCTET
CONTENT          = *FRAGMENT

; ####################
; FRAGMENT
; ####################

FRAGMENT-ID      = 32OCTET
FRAGMENT         = FRAGMENT-SIZE %x00 FRAGMENT-SPEC
FRAGMENT-SIZE    = SIZE-BYTES-32BIT
FRAGMENT-SPEC    = %x00 INITIAL
                 / %x01 OLD-UTXO-DECL
                 / %x02 SIMPLE-TRANSACTION
                 / %x03 OWNER-STAKE-DELEGATION
                 / %x04 STAKE-DELEGATION
                 / %x05 POOL-REGISTRATION
                 / %x06 POOL-RETIREMENT
                 / %x07 POOL-UPDATE
                 / %x08 UPDATE-PROPOSAL
                 / %x09 UPDATE-VOTE

; ####################
; FRAGMENT only present in genesis block
; ####################

INITIAL          = SIZE-ELEMENT-16BIT *CONFIG-ELEMENT
CONFIG-ELEMENT   = CONFIG-TAGLEN CONFIG-VALUE
CONFIG-TAGLEN    = U16                        ; tag number + length
CONFIG-VALUE     = 0*64OCTET                  ; using length

OLD-UTXO-DECLS   = SIZE-ELEMENT-8BIT 1*254OLD_UTXO_DECL
OLD-UTXO-DECL    = VALUE SIZE-BYTE-16BIT OLD-ADDRESS
OLD-ADDRESS      = *OCTET

; ####################
; FRAGMENT common transaction
; ####################

TRANSACTION      = IOW

; ####################
; FRAGMENT stake delegation
; ####################

OWNER-DELEGATION = OWNER-DLG-CERT IOW
OWNER-DLG-CERT   = DLG-TYPE

STAKE-DELEGATION = DLG-CERT IOW STAKE-AUTH
DLG-CERT         = UNTAG-ACCOUNT-ID DLG-TYPE
STAKE-AUTH       = ACCOUNT-SIG

DLG-TYPE         = DLG-NONE / DLG-FULL / DLG-RATIO
DLG-NONE         = %x00
DLG-FULL         = %x01 POOL-ID
DLG-RATIO        = %x02-FF %x02-08 2*8DLG-RATIO-POOL
DLG-RATIO-POOL   = %x01-FF POOL-ID

POOL-ID          = 32OCTET ; blake2b256 of REGISTRATION-CERT

; ####################
; FRAGMENT Pool management
; ####################

POOL-REGISTRATION = REGISTRATION-CERT IOW POOL-SIG
POOL-RETIREMENT   = RETIREMENT-CERT IOW POOL-SIG
POOL-UPDATE       = UPDATE-CERT IOW POOL-SIG

REGISTRATION-CERT = POOL-SERIAL
                    TIME-SINCE-EPOCH0
                    POOL-PERMISSIONS
                    POOL-KEYS
                    POOL-OWNERS
                    POOL-OPERATORS
                    POOL-REWARD-SCHM
                    POOL-REWARD-ACNT
POOL-SERIAL       = 16OCTET
POOL-PERMISSIONS  = U64 ; for now management threshold
POOL-KEYS         = VRF-PUBLICKEY KES-PUBLICKEY
POOL-OWNERS       = SIZE-ELEMENT-1-31 1*31POOL-OWNER
POOL-OPERATORS    = SIZE-ELEMENT-0-3 0*3POOL-OPERATOR
POOL-OWNER        = SINGLE-ACNT-ID
POOL-OPERATOR     = SINGLE-ACNT-ID
POOL-REWARD-SCHM  = 4U64 ; fixed, ratio numerator, denominator, and optional limit value
POOL-REWARD-ACNT  = %x00 / ACCOUNT-ID

RETIREMENT-CERT   = POOL-ID
                    TIME-SINCE-EPOCH0 ; time in seconds
UPDATE-CERT       = POOL-ID ; pool id
                    POOL-ID ; last known pool registration hash. on first update it would be the poolid
                    REGISTRATION-CERT ; the update for the pool which is just a full pool registration certificate

POOL-SIG          = OWNERS-SIG / OP-SIGNATURE
OPERATOR-SIG      = %x00 SINGLE-ACNT-SIG
OWNERS-SIG        = SIZE-ELEMENT-1-31 1*31OWNER-SIG
OWNER-SIG         = U8 ; owner index in registration
                    SINGLE-ACNT-SIG

; ####################
; FRAGMENT Update proposal and vote
; ####################

UPDATE-PROPOSAL   = PROPOSAL-CERT IOW BFT-SIGNATURE
UPDATE-VOTE       = VOTE-CERT IOW BFT-SIGNATURE

PROPOSAL-CERT     = BFT-LEADER-ID ; proposer id
                    CHANGES

VOTE-CERT         = PROPOSAL-ID
                    BFT-LEADER-ID; voter id

CHANGES           = SIZE-ELEMENT-16BIT ; number of changes
                    *CONFIG-ELEMENT    ; as many as indicated in the number of changes

PROPOSAL-ID       = FRAGMENT-ID

; ####################
; TRANSACTION CONSTRUCTION
;
; note: IOW stand for Inputs-Outputs-Witnesses
; ####################

IOW               = BLOCK-DATE        ; end validity of this IOW
                    SIZE-ELEMENT-8BIT ; number of inputs
                    SIZE-ELEMENT-8BIT ; number of outputs
                    *INPUT            ; as many as indicated in the number of inputs
                    *OUTPUT           ; sa many as indicated in the number of outputs
                    *WITNESS          ; as many as indicated in the number of inputs
INPUT             = INPUT-UTXO / INPUT_ACCOUNT
INPUT-UTXO        = IDX VALUE FRAGMENT-ID
INPUT-ACCOUNT     = %xff VALUE UNTAG-ACCOUNT-ID
IDX               = %x00-fe
OUTPUT            = ADDRESS VALUE
WITNESS           = WITNESS-OLDUTXO / WITNESS-UTXO / WITNESS-ACCOUNT / WITNESS-MULTISIG
WITNESS-OLDUTXO   = %x00 LEGACY-XPUB LEGACY-SIGNATURE
WITNESS-UTXO      = %x01 ED25519-SIGNATURE
WITNESS-ACCOUNT   = %x02 ACCOUNT-NONCE SINGLE-ACNT-SIG
WITNESS-MULTISIG  = %x03 ACCOUNT-NONCE MULTI-ACNT-SIG

VALUE             = U64

; ####################
; ADDRESS
; ####################

ADDRESS           = ADDRESS-SINGLE / ADDRESS-GROUP / ADDRESS-ACCOUNT / ADDRESS-MULTISIG
ADDRESS-SINGLE    = (%x03 / %x83) SPENDINGKEY
ADDRESS-GROUP     = (%x04 / %x84) SPENDINGKEY SINGLE-ACNT-ID
ADDRESS-ACCOUNT   = (%x05 / %x85) SINGLE-ACNT-ID
ADDRESS-MULTISIG  = (%x06 / %x86) MULTI-ACNT-ID

; ####################
; ACCOUNT
; ####################

ACCOUNT-NONCE     = U32
ACCOUNT-ID        = (%x01 SINGLE-ACNT-ID) / (%x02 MULTI-ACNT-ID)
ACCOUNT-SIG       = (%x01 SINGLE-ACNT-SIG) / (%x02 MULTI-ACNT-SIG)
UNTAG-ACCOUNT-ID  = SINGLE-ACNT-ID / MULTI-ACNT-ID
SINGLE-ACNT-ID    = ED25519-PUBLICKEY
SINGLE-ACNT-SIG   = ED25519-SIGNATURE
MULTI-ACNT-ID     = 32OCTET
MULTI-ACNT-SIG    = TODO

; ####################
; CRYPTO
; ####################

BFT-LEADER-ID     = ED25519-PUBLICKEY
BFT-SIGNATURE     = ED25519-SIGNATURE
LEGACY-SIGNATURE  = ED25519-SIGNATURE
LEGACY-XPUB       = 64OCTET
VRF-PUBLICKEY     = 32OCTET
VRF-OUTPUT        = 96OCTET
KES-PUBLICKEY     = 32OCTET
KES-SIGNATURE     = 484OCTET
ED25519-PUBLICKEY = 32OCTET
ED25519-SIGNATURE = 64OCTET

; ####################
; PRIMITIVES
; ####################

TIME-SINCE-EPOCH0 = U64 ; in seconds since genesis block
SIZE-ELEMENT-8BIT = U8  ; size in elements (8 bits)
SIZE-ELEMENT-1-31 = %x01-1f ; size of 1 to 31, in elements
SIZE-ELEMENT-0-3  = %x00-03 ; size of 0 to 3, in elements
SIZE-ELEMENT-16BIT = U16  ; size in elements (16 bits)
SIZE-ELEMENT-OO   = U8  ; size of operators & owners : 5 bits for owners, 3 high bits for operators
SIZE-BYTES-16BIT  = U16 ; size in bytes (16 bits)
SIZE-BYTES-32BIT  = U32 ; size in bytes (32 bits)
U8                = OCTET   ; unsigned integer 8 bit
U16               = 2OCTET ; unsigned integer 16 bit (BE)
U32               = 4OCTET ; unsigned integer 32 bit (BE)
U64               = 8OCTET ; unsigned integer 64 bit (BE)
