Interpret a block's nulldata back into a name.  The first three bytes (2 magic + 1 opcode)
    will not be present in bin_payload.
 
    The name will be directly represented by the bytes given.
    
    This works for registrations and renewals.

    Record format (pre F-day 2017):
    
    0    2  3                                  39
    |----|--|----------------------------------|
    magic op   name.ns_id (up to 37 bytes)


    Record format (post F-day 2017):
    
    0    2  3                                  39                  59
    |----|--|----------------------------------|-------------------|
    magic op   name.ns_id (37 bytes, 0-padded)    zone file hash


    Record format (STACKs phase 1):
    (for register, tokens burned is ignored)
    (for renew, tokens burned is the number of tokens to burn)
    
    0    2  3                                  39                  59                             67
    |----|--|----------------------------------|-------------------|------------------------------|
    magic op   name.ns_id (37 bytes, 0-padded)     zone file hash    tokens burned (big-endian)

def parse(bin_payload, block_height):
    """
    Interpret a block's nulldata back into a name.  The first three bytes (2 magic + 1 opcode)
    will not be present in bin_payload.
 
    The name will be directly represented by the bytes given.
    
    This works for registrations and renewals.

    Record format (pre F-day 2017):
    
    0    2  3                                  39
    |----|--|----------------------------------|
    magic op   name.ns_id (up to 37 bytes)


    Record format (post F-day 2017):
    
    0    2  3                                  39                  59
    |----|--|----------------------------------|-------------------|
    magic op   name.ns_id (37 bytes, 0-padded)    zone file hash


    Record format (STACKs phase 1):
    (for register, tokens burned is ignored)
    (for renew, tokens burned is the number of tokens to burn)
    
    0    2  3                                  39                  59                             67
    |----|--|----------------------------------|-------------------|------------------------------|
    magic op   name.ns_id (37 bytes, 0-padded)     zone file hash    tokens burned (big-endian)

    """
    
    # pre F-day 2017: bin_payload is the name.
    # post F-day 2017: bin_payload is the name and possibly the update hash
    # STACKs phase 1: bin_payload possibly has a token burn attached to the end
    epoch_features = get_epoch_features(block_height)
    fqn = None
    value_hash = None
    tokens_burned = 0

    if EPOCH_FEATURE_OP_REGISTER_UPDATE in epoch_features or EPOCH_FEATURE_OP_RENEW_TRANSFER_UPDATE in epoch_features:
        # payload is possibly name + zonefile hash, or name + zonefile hash + tokens
        # if so, it's guaranteed to be max_name_len + value_hash_len bytes long.
        name_value_len = LENGTHS['blockchain_id_name'] + LENGTHS['value_hash']
        if len(bin_payload) >= name_value_len:
            # has name and value hash, and possibly a token burn
            # get name and value hash
            value_hash = bin_payload[LENGTHS['blockchain_id_name']: LENGTHS['blockchain_id_name'] + LENGTHS['value_hash']].encode('hex')
            fqn = bin_payload[:LENGTHS['blockchain_id_name']]
            fqn = fqn.rstrip('\x00')

            if EPOCH_FEATURE_NAMEOPS_COST_TOKENS in epoch_features:
                # might have tokens burned.  If so, it's all or nothing.
                if len(bin_payload) == name_value_len + LENGTHS['tokens_burnt']:
                    # we have a token count (this is a name renewal)
                    bin_tokens = bin_payload[name_value_len: name_value_len + LENGTHS['tokens_burnt']]
                    tokens_burned = int(bin_tokens.encode('hex'), 16)    # NOTE: big-endian

                else:
                    # must not have any bits dangling off the end 
                    if len(bin_payload) != name_value_len:
                        log.warning('Invalid payload {}: expected {} bytes or {} bytes'.format(bin_payload.encode('hex'), name_value_len, name_value_len + LENGTHS['tokens_burnt']))
                        return None 

                    # no token count (might be a register)
                    tokens_burned = None

            else:
                # tokens are not active in this epoch.
                # payload must be *exactly* name + value hash.
                if len(bin_payload) != name_value_len:
                    log.warning("Invalid payload {}: expected {} bytes".format(bin_payload.encode('hex'), name_value_len))
                    return None

        else:
            # payload is just a name
            fqn = bin_payload

    else:
        # payload is only the name
        fqn = bin_payload
 
    if not is_name_valid( fqn ):
        log.warning("Invalid name: {} ({})".format(fqn, fqn.encode('hex')))
        return None

    return {
       'opcode': 'NAME_REGISTRATION',       # NOTE: could be NAME_RENEWAL
       'name': fqn,
       'value_hash': value_hash,
       'token_fee': tokens_burned,
    }