NOTE: the first three bytes will be missing


    wire format (Pre-STACKs Phase 1)

    0     2   3                                      23               39
    |-----|---|--------------------------------------|----------------|
    magic op  hash(ns_id,script_pubkey,reveal_addr)   consensus hash

    wire format (Post-STACKs phase 1)

    0     2   3                                      23               39                         47
    |-----|---|--------------------------------------|----------------|--------------------------|
    magic op  hash(ns_id,script_pubkey,reveal_addr)   consensus hash    token fee (big-endian)

    Returns {
        'opcode': ...
        'preorder_hash': ...
        'consensus_hash': ...
        'token_fee': ...
    }

def parse( bin_payload, block_height ):
    """
    NOTE: the first three bytes will be missing


    wire format (Pre-STACKs Phase 1)

    0     2   3                                      23               39
    |-----|---|--------------------------------------|----------------|
    magic op  hash(ns_id,script_pubkey,reveal_addr)   consensus hash

    wire format (Post-STACKs phase 1)

    0     2   3                                      23               39                         47
    |-----|---|--------------------------------------|----------------|--------------------------|
    magic op  hash(ns_id,script_pubkey,reveal_addr)   consensus hash    token fee (big-endian)

    Returns {
        'opcode': ...
        'preorder_hash': ...
        'consensus_hash': ...
        'token_fee': ...
    }
    """
   
    if len(bin_payload) < LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash']:
        log.warning("Invalid namespace preorder payload length %s" % len(bin_payload))
        return None

    namespace_id_hash = bin_payload[ :LENGTHS['preorder_name_hash'] ]
    consensus_hash = bin_payload[ LENGTHS['preorder_name_hash']: LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash'] ]
    tokens_burned = None
    
    epoch_features = get_epoch_features(block_height)

    if len(bin_payload) > LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash']:
        if EPOCH_FEATURE_STACKS_BUY_NAMESPACES not in epoch_features:
            # not allowed--we can't use tokens in this epoch
            log.warning("Invalid payload {}: expected {} bytes".format(bin_payload.encode('hex'), LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash']))
            return None

        if len(bin_payload) != LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash'] + LENGTHS['tokens_burnt']:
            # not allowed--invalid length
            log.warning("Invalid payload {}: expected {} bytes".format(bin_payload.encode('hex'), LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash'] + LENGTHS['tokens_burnt']))
            return None
        
        bin_tokens_burned = bin_payload[LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash']: LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash'] + LENGTHS['tokens_burnt']]
        tokens_burned = int(bin_tokens_burned.encode('hex'), 16)
  
    else:
        # only allow the absence of the tokens field if we're in a pre-STACKs epoch 
        if EPOCH_FEATURE_STACKS_BUY_NAMESPACES in epoch_features:
            # not allowed---we need the stacks token field
            log.warning('Invalid payload {}: expected {} bytes'.format(bin_payload.encode('hex'), LENGTHS['preorder_name_hash'] + LENGTHS['consensus_hash'] + LENGTHS['tokens_burnt']))
            return None

    namespace_id_hash = hexlify( namespace_id_hash )
    consensus_hash = hexlify( consensus_hash )
   
    return {
       'opcode': 'NAMESPACE_PREORDER',
       'preorder_hash': namespace_id_hash,
       'consensus_hash': consensus_hash,
       'token_fee': tokens_burned
    }