Sequence
O campo que controla locktime, RBF e locktime relativo
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:
- <=0xFFFFFFFE — Locktime. Habilita o uso do campo locktime da transação.
- <=0xFFFFFFFD — Replace By Fee (RBF). Habilita o recurso RBF, que permite substituir uma transação por uma de taxa mais alta enquanto ela está no mempool.
- <=0xEFFFFFFF — Locktime Relativo. Permite definir um locktime na transação relativo a quando a saída sendo gasta foi minerada.
- 0x00000000 a 0x0000FFFF — Blocos. Define o locktime relativo como um número de blocos.
- 0x00400000 a 0x0040FFFF — Tempo. Define o locktime relativo como um número de segundos.
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.
Locktime
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).
Unix Time
Replace By Fee
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:
- Você não precisa aumentar ou diminuir o número de sequence na transação de substituição. Tudo o que importa é que a transação de substituição tenha uma taxa mais alta.
- Você pode substituir transações repetidamente, desde que a nova transação tenha uma taxa mais alta que a que está substituindo. Quanto mais substituições você fizer, mais alta a taxa precisará ser a cada vez para superar as taxas das transações de substituição anteriores.
- Você pode enviar as moedas para um destino diferente (ou seja, criar saídas diferentes) na transação de substituição, se quiser. É por isso que isso às vezes é chamado de "Full RBF", já que outras propostas de RBF exigiam que a transação de substituição tivesse as mesmas saídas.
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
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
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.
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):
- Bit 31: Disable Flag
- 1 = Locktime Relativo Desabilitado
- 0 = Locktime Relativo Habilitado
- Bit 22: Type Flag
- 1 = Tempo (o valor é multiplicado por 512 para dar o tempo em segundos)
- 0 = Blocos
- Bits 15-0: Valor
- Esses 16 bits podem conter qualquer número entre 0 e 65535 (
0x0000a0xffff)
- Esses 16 bits podem conter qualquer número entre 0 e 65535 (
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.
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.
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:
- 2833fece3b1c38dffc11a7f211b05512512b0f8dec7055b6d7e7c155d83e7dec (Entrada 0)
- Sequence =
fffffffe - Locktime habilitado. O valor do campo locktime também era 699999, então esta transação não podia ser minerada até depois do bloco 699.999. Ela acabou sendo minerada no bloco 700.000.
- Sequence =
- 163558ace2946d805b688d89d8ba0dd607d9f947073b45f393d9757eef1a4af7 (Entrada 0)
- Sequence =
fffffffd - RBF habilitado. Não dá para saber se esta transação foi substituída ou não, mas poderia ter sido enquanto estava no mempool.
- Sequence =
- 62fb5ecd3f022a2f09b73723b56410db0545923516b611013aed5218e4979322 (Entrada 0)
- Sequence =
00000090 - Locktime relativo habilitado (blocos). Esta transação não podia ser minerada até 144 blocos (0x0090 = 144) depois de a saída sendo gasta ter sido minerada. A saída gasta foi minerada no bloco 603.018, e esta transação foi minerada 146 blocos depois, no bloco 603.164.
- Sequence =
- 12fa403cb22bf08c4c5542cc00673495a0c54c9cc8181bea850a12d40d7593a2 (Entrada 0)
- Sequence =
00400007 - Locktime relativo habilitado (tempo). Esta transação não podia ser minerada até 3584 segundos (0x0007 = 7, 7 × 512 = 3584) depois de a saída sendo gasta ter sido minerada. A saída gasta foi minerada no bloco 603.434 com um timestamp de 1573549241 (12 de novembro de 2019, 09:00:41), e esta transação foi minerada 6426 segundos depois, no bloco 603.450, com um timestamp de 1573555667 (12 de novembro de 2019, 10:47:47).
- Sequence =
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.