Sequence

O campo que controla locktime, RBF e locktime relativo

Diagrama mostrando os campos sequence ao lado de cada entrada de transação.

O campo sequence pode ser encontrado em toda entrada de transação. Ele te dá controle sobre quando uma transação pode ser minerada ou se uma transação pode ser substituída enquanto está no mempool.

Em termos mais técnicos, você pode dizer que o campo sequence controla a "finalidade" de uma transação — se ela está em seu estado "final" antes de ser minerada em um bloco. Se não estiver em seu estado "final", é possível substituí-la antes que ela chegue à blockchain.

Estas são as configurações mais comuns:

Uma escolha popular é usar 0xFFFFFFFD nos seus campos sequence, pois habilita tanto o campo locktime (caso queira usá-lo) quanto o replace-by-fee (geralmente útil).

Se você definir o valor máximo 0xFFFFFFFF em todas as entradas de uma transação, a transação inteira é considerada "final" e não pode ser substituída nem impedida de ser minerada.

Você só precisa definir um dos campos sequence para habilitar o locktime ou o RBF (mesmo que haja várias entradas e campos sequence em uma transação). Porém, as configurações de locktime relativo são específicas de cada entrada.

Sequence

Veja quais recursos (locktime, RBF, locktime relativo) um valor de sequence habilita — ou monte um sequence marcando os recursos.

O sequence como aparece nos dados brutos da transação

0x
4 bytes
0x
4 bytes
Recursos
Tipo do Locktime Relativo
segundos

Locktime

Diagrama mostrando o campo sequence sendo definido para habilitar o campo locktime de uma transação.

Você pode habilitar o campo locktime para a transação inteira se definir qualquer um dos valores de sequence das entradas como 0xFFFFFFFE ou abaixo.

Por exemplo:

0xFFFFFFFE <- habilita o locktime

Como mencionado, definir todos os valores de sequence de uma transação como 0xFFFFFFFF indica que a transação é final. Então, ao definir qualquer um dos sequence abaixo do valor máximo 0xFFFFFFFF, você está indicando que a transação não é final e, portanto, o campo locktime será habilitado.

O campo locktime fica no fim da transação. Ele permite definir um tempo específico ou uma altura de bloco no futuro a partir do qual a transação será válida (e, portanto, poderá ser minerada na blockchain).

Por padrão, a carteira do Bitcoin Core define o campo sequence de cada entrada como 0xFFFFFFFE. Isso habilita o campo locktime da transação, mas nenhum outro recurso.

Uso

Se você quer que uma transação só possa ser minerada em algum momento no futuro, precisa usar o campo locktime no fim da transação.

Para habilitar o campo locktime, você precisa definir um dos valores de sequence da sua transação como 0xFFFFFFFE ou abaixo.

Você pode então definir o campo locktime entre 0 e 499999999 para a transação poder ser minerada após uma certa altura de bloco, ou entre 500000000 e 4294967295 para ela ser minerada após um momento específico no tempo (ou seja, um timestamp Unix).

Ícone Ferramenta Unix Time

Unix Time

Converta o número de segundos desde 01/01/1970, 00:00:00 para uma data.

0d

Replace By Fee

BIP 125

Diagrama mostrando o campo sequence sendo definido para habilitar o recurso replace by fee em uma transação.

Você pode permitir que uma transação seja substituída por uma de taxa mais alta mais tarde (enquanto ainda está na memory pool) definindo o valor de sequence em qualquer uma das suas entradas como 0xFFFFFFFD ou abaixo.

Por exemplo:

0xFFFFFFFD <- habilita o replace-by-fee

Esse valor é 1 a menos que a configuração de locktime acima, o que significa que você pode habilitar o locktime sem habilitar o replace-by-fee.

Uso

Digamos que você criou uma transação e a enviou para a rede, mas definiu uma taxa irritantemente baixa nela.

Se há um grande volume de transações com taxas altas na rede, a sua transação pode acabar ficando na memory pool esperando para ser minerada. Normalmente você não conseguiria desfazer ou substituir essa transação até que ela fosse minerada ou expirasse da memory pool, mas isso poderia levar alguns dias.

Porém, se você definir um valor de sequence de 0xFFFFFFFD em qualquer uma das entradas da sua transação, você está sinalizando que qualquer uma dessas entradas pode ser gasta por uma transação mais nova com uma taxa mais alta. Então, em vez de ter que esperar a primeira transação ser minerada, você pode enviar uma transação de substituição para acelerar o processo.

Os nós e mineradores saberão que um sequence foi definido como 0xFFFFFFFD ou abaixo, então ficarão dispostos a substituir essa transação nas suas memory pools se chegar uma com taxa mais alta.

Algumas notas sobre o uso do RBF:

O RBF é válido para a transação inteira, não específico por entrada. Definir um sequence de 0xFFFFFFFD ou abaixo em qualquer entrada torna a transação inteira substituível. Então, se você tem outras entradas na mesma transação, essas entradas individuais também podem ser gastas em uma transação de taxa mais alta, mesmo que você tenha dado a elas o sequence máximo de 0xFFFFFFFF.

Definindo Taxas Mais Altas

Diagrama mostrando as taxas das transações de substituição, incluindo o tamanho das taxas das transações que elas substituem.

A taxa da transação de substituição precisa ser suficiente para cobrir a taxa mínima de retransmissão (minimum relay fee), mais o tamanho das taxas das transações que ela substitui:

Taxa Mínima da Transação RBF = Taxa Mínima de Retransmissão + Taxa(s) da(s) Transação(ões) Anterior(es)
Exemplos de RBF

Digamos que a taxa mínima de retransmissão seja atualmente 1 sat/vbyte.

Para uma transação replace-by-fee simples (em que a transação de substituição é exatamente igual à original), a taxa da transação de substituição só precisa ser pelo menos o dobro da taxa da transação que você quer substituir:

Taxa Mínima de Retransmissão: 1 sat/vbyte

Transação     | Tamanho   | Taxa Mín. Retr. | Taxa(s) Anterior(es) | Taxa Mínima  | Feerate
--------------|-----------|-----------------|----------------------|--------------|------------
Original      | 200 bytes | 200 sats        | 0                    | 200 sats     | 1 sat/vbyte
Substituição 1| 200 bytes | 200 sats        | 200 sats             | 400 sats     | 2 sat/vbyte

Então, neste exemplo, a taxa da transação de substituição precisava ser de pelo menos 200 sats por si só (para satisfazer a taxa mínima de retransmissão de 1 sat/vbyte), mais a taxa de 200 sats da transação que estamos substituindo, totalizando uma taxa mínima de 400 sats. Você pode ir bem mais alto que isso se quiser (e provavelmente vai, para criar um feerate mais atraente), mas este é o mínimo.

Agora, se você está substituindo uma transação várias vezes (aumentando a taxa repetidamente), a taxa mínima da próxima transação precisa ser maior que a soma de todas as taxas das transações anteriores que você quer substituir, mais a taxa mínima de retransmissão da transação atual (como sempre):

Taxa Mínima de Retransmissão: 1 sat/vbyte

Transação     | Tamanho   | Taxa Mín. Retr. | Taxa(s) Anterior(es) | Taxa Mínima  | Feerate
--------------|-----------|-----------------|----------------------|--------------|------------
Original      | 200 bytes | 200 sats        | 0                    | 200 sats     | 1 sat/vbyte
Substituição 1| 200 bytes | 200 sats        | 200 sats             | 400 sats     | 2 sat/vbyte
Substituição 2| 200 bytes | 200 sats        | 400 sats             | 600 sats     | 3 sat/vbyte

Aqui está outro exemplo em que as transações de substituição têm tamanhos diferentes (o que também é perfeitamente aceitável):

Taxa Mínima de Retransmissão: 1 sat/vbyte

Transação     | Tamanho   | Taxa Mín. Retr. | Taxa(s) Anterior(es) | Taxa Mínima  | Feerate
--------------|-----------|-----------------|----------------------|--------------|---------------
Original      | 200 bytes | 200 sats        | 0                    |  200 sats    | 1 sat/vbyte
Substituição 1| 800 bytes | 800 sats        | 200 sats             | 1000 sats    | 1,25 sat/vbyte
Substituição 2| 300 bytes | 300 sats        | 1000 sats            | 1300 sats    | 4,33 sat/vbyte
Substituição 3| 200 bytes | 200 sats        | 1300 sats            | 1500 sats    | 7,50 sat/vbyte

Então, basicamente, para calcular a próxima taxa mais alta, você só precisa começar somando as taxas das transações que quer substituir. A taxa mínima é, então, a soma de todas essas taxas anteriores mais a taxa mínima de retransmissão da transação atual.

Mas, em geral, para uma transação replace-by-fee direta, você só precisa dobrar o tamanho da taxa anterior.

Locktime Relativo

BIP 68

Diagrama mostrando o campo sequence sendo usado para definir um locktime relativo na transação.
O locktime relativo (RLT) permite que uma entrada de transação assinada permaneça inválida por um período de tempo definido após a confirmação do seu outpoint correspondente.
BIP 68

O locktime relativo permite especificar uma quantidade de tempo ou um número de blocos a partir de quando uma saída foi minerada, antes que uma transação que a gaste se torne válida.

Então, enquanto o locktime da transação permite especificar um tempo absoluto em que uma transação pode ser minerada, o locktime relativo permite especificar uma quantidade de tempo relativa (a partir de quando uma saída foi minerada) antes que a transação que a gasta possa ser minerada.

Para definir o locktime relativo em uma entrada, você precisa ver o sequence como um campo de 32 bits individuais (ou seja, um bit field):

Primeiro, para habilitar a configuração de locktime relativo, você precisa definir o disable flag (bit 31) como 0. Eu sei que é meio contraintuitivo definir algo como zero para ligá-lo, mas é assim que funciona aqui. Mas, como este é o primeiro bit e está definido como zero, todas as configurações de locktime relativo serão sempre menores ou iguais a 0xEFFFFFFF.

Segundo, temos o type flag (bit 22), que permite escolher entre definir um locktime relativo como uma quantidade de tempo ou um número de blocos desde que a saída que você está gastando foi minerada.

Por último, os últimos 16 bits contêm o valor de fato (bits 15-0) em termos de blocos ou tempo. Se você escolher tempo, esse valor é multiplicado por 512 para dar o locktime relativo em segundos.

Relative Locktime

Construa um locktime relativo para o campo sequence de uma entrada de transação.

O sequence como aparece nos dados brutos da transação

0x
4 bytes
0x
4 bytes
Sequence (Campo de Bits) 00000000000000000000000000000000
Flags
Locktime Relativo
× 512 = 0 segundos

O RBF e o locktime serão habilitados ao usar o locktime relativo.

Para habilitar o locktime relativo, a versão da transação precisa ser 2 ou maior.

Por que o valor de tempo é multiplicado por 512?

Porque isso cria um intervalo semelhante entre definir um número de blocos e um número de segundos.

Por exemplo, há, em média, 600 segundos (10 minutos) entre blocos, e o valor máximo que você pode colocar para qualquer um dos tipos de locktime relativo é 65535 (0xffff), então:

Máx. Blocos = 65535 × 600 = 39321600 segundos = 455,11111 dias
Máx. Tempo  = 65535 × 512 = 33553920 segundos = 388,35556 dias

Assim, usando um type flag de blocos ou de tempo, você consegue definir um locktime relativo máximo de pouco mais de um ano no futuro em ambos os casos.

Mas por que multiplicar por 512 em vez de 600? Porque 512 é 2⁹, o que significa que você pode fazer um deslocamento de bits (bitwise left shift) de 9 para converter o valor em segundos rapidamente. Isso é mais rápido do que multiplicar por 600, e 512 é a potência de 2 mais próxima de 600 que você consegue.

0b0000000001 = 1
0b1000000000 = 512 (o deslocamento de bits no computador é mais rápido que multiplicar)
Deslocamentos de bits são baratos.
Mark Friedenbach (autor do BIP 68), (via e-mail)
Exemplos de Locktime Relativo

Definir um locktime relativo de 65535 × 512 = 33553920 segundos:

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│0│0│0│0│0│0│0│0│0│1│0│0│0│0│0│0│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

0x0040ffff

Definir um locktime relativo de 1 × 512 = 512 segundos:

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│0│0│0│0│0│0│0│0│0│1│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│1│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

0x00400001

Definir um locktime relativo de 65535 blocos:

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│1│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

0x0000ffff

Definir um locktime relativo de 1 bloco:

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│1│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

0x00000001

Desabilitar completamente o locktime relativo:

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐
│1│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│0│
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘

0x80000000

Um locktime relativo de 0 blocos (0x00000000) significa que a entrada pode ser minerada em um bloco imediatamente, sem ter que esperar. Isso é como não ter locktime relativo nenhum, então é melhor usar um sequence de 0xFFFFFFFF em vez disso.

Qualquer valor de sequence de 0x80000000 ou acima vai desabilitar o recurso de locktime relativo.

Código
# -----------------
# Operadores Bit a Bit
# -----------------
#
# A forma mais fácil de trabalhar com bits diretamente é usando "operadores bit a bit". Eles estão disponíveis em todas as boas linguagens de programação:
#
#  << - "SHIFT LEFT" - Move os bits um número de posições para a esquerda
#  |  - "OR"         - Combina dois conjuntos de bits
#  &  - "AND"        - Extrai bits de um conjunto usando uma "máscara de bits"

# ---------------------------
# Construir o Locktime Relativo
# ---------------------------

# Define o Disable Flag (0 = habilitado, 1 = desabilitado)
disable = 0<<31 # Move um zero 31 bits para a esquerda. Inútil, na verdade, já que isto é só 0, mas tudo bem
# 00000000000000000000000000000000

# Define o Type Flag (0 = blocos, 1 = tempo)
type    = 1<<22 # Move um um 22 bits para a esquerda.
#          10000000000000000000000

# Define o Valor
value   = 10000 # Isto é só um inteiro; todo inteiro tem a sua própria representação em bits
#                   10011100010000

# Combina todos os bits em um único campo
sequence = 0<<31 | 1<<22 | 10000
# disable  = 00000000000000000000000000000000
# type     =          10000000000000000000000 |
# value    =                   10011100010000 | (O operador OR retorna 1 se qualquer um dos bits estiver setado)
#            --------------------------------
#            00000000010000000010011100010000

# O Ruby imprime este valor como inteiro por padrão, mas, para exibição, podemos convertê-lo em uma string de bits (base 2)
bits = sequence.to_s(2)
puts bits #=> 10000000010011100010000

# Também podemos converter o valor de sequence em uma string hexadecimal (base 16)
hex  = sequence.to_s(16)
puts hex #=> "402710"

# ------
# Decodificar
# ------

# Sequence
sequence = 0x00402710

# Extrai o Disable Flag
disable = 1<<31 & sequence
# 1<31     = 10000000000000000000000000000000
# sequence = 00000000010000000010011100010000 & (O operador AND retorna 1 se ambos os bits estiverem setados)
#            --------------------------------
#            00000000000000000000000000000000 = 0

# Extrai o Type Flag
type = 1<<22 & sequence
# 1<22     = 00000000010000000000000000000000
# sequence = 00000000010000000010011100010000 &
#            --------------------------------
#            00000000010000000000000000000000 = 4194304 (Qualquer valor diferente de zero significa que este bit foi setado)

# Extrai o Valor
value = 0xffff & sequence # 0xffff é a máscara de bits
# 0xffff   = 00000000000000001111111111111111
# sequence = 00000000010000000010011100010000 &
#            --------------------------------
#            00000000000000000010011100010000 = 10000

# Mostra os resultados
puts (disable ? 'true' : 'false')
puts (type ? 'time' : 'blocks')
puts value #=> 10000

Exemplos

Aqui estão alguns exemplos de valores de sequence sendo usados em transações reais na blockchain:

História

Para que o campo sequence foi originalmente projetado?

O campo sequence foi originalmente projetado para permitir a substituição de transações enquanto elas ainda estavam na memory pool.

Originalmente, você definiria um locktime em uma transação para algum momento no futuro e, se qualquer um dos campos sequence estivesse abaixo do valor máximo 0xFFFFFFFF, poderia substituí-la por uma nova versão da transação com um valor de sequence mais alto.

Esperava-se que nós e mineradores segurassem essas transações não finais até o locktime ser atingido, ou até chegar uma transação de substituição com todos os valores de sequence em 0xFFFFFFFF (significando que ela finalmente poderia ser minerada em um bloco). Porém, não havia incentivo para os mineradores manterem essas transações não finais na memória, então o campo sequence nunca foi totalmente usado para esse propósito, e foi discretamente desabilitado pelo Satoshi em 2010, no Bitcoin v0.3.12.

Desde então, o campo sequence foi reaproveitado várias vezes, mas todas as mudanças no campo sequence estão relacionadas à "finalidade" da transação, ou à capacidade de substituir uma transação enquanto ela está (ou antes de entrar) na memory pool.

Recursos