Files
ark/common/bip68.go
Louis Singer 287db4e08a Support round expiration and sweep vtxos (#70)
* sweeper base implementation

* sweeper service final implementation

* fixes

* fix CSV script

* RoundSwept event fix & test

* remove Vtxos after a sweep transaction

* ARK_ROUND_LIFETIME config

* remove TxBuilder.GetLifetime

* refactor sweeper

* use GetTransaction blocktime

* polish and comments

* fix linting

* pair programming fixes

* several fixes

* clean Println

* fixes

* linter fixes

* remove infrastructure deps from application layer

* Fixes

---------

Co-authored-by: altafan <18440657+altafan@users.noreply.github.com>
2024-02-08 16:58:04 +01:00

66 lines
1.8 KiB
Go

package common
import (
"encoding/hex"
"fmt"
)
const (
SEQUENCE_LOCKTIME_MASK = 0x0000ffff
SEQUENCE_LOCKTIME_TYPE_FLAG = 1 << 22
SEQUENCE_LOCKTIME_GRANULARITY = 9
SECONDS_MOD = 1 << SEQUENCE_LOCKTIME_GRANULARITY
SECONDS_MAX = SEQUENCE_LOCKTIME_MASK << SEQUENCE_LOCKTIME_GRANULARITY
SEQUENCE_LOCKTIME_DISABLE_FLAG = 1 << 31
)
func closerToModulo512(x uint) uint {
return x - (x % 512)
}
func BIP68EncodeAsNumber(seconds uint) (uint32, error) {
seconds = closerToModulo512(seconds)
if seconds > SECONDS_MAX {
return 0, fmt.Errorf("seconds too large, max is %d", SECONDS_MAX)
}
if seconds%SECONDS_MOD != 0 {
return 0, fmt.Errorf("seconds must be a multiple of %d", SECONDS_MOD)
}
asNumber := SEQUENCE_LOCKTIME_TYPE_FLAG | (seconds >> SEQUENCE_LOCKTIME_GRANULARITY)
return uint32(asNumber), nil
}
// BIP68Encode returns the encoded sequence locktime for the given number of seconds.
func BIP68Encode(seconds uint) ([]byte, error) {
asNumber, err := BIP68EncodeAsNumber(seconds)
if err != nil {
return nil, err
}
hexString := fmt.Sprintf("%x", asNumber)
reversed, err := hex.DecodeString(hexString)
if err != nil {
return nil, err
}
for i, j := 0, len(reversed)-1; i < j; i, j = i+1, j-1 {
reversed[i], reversed[j] = reversed[j], reversed[i]
}
return reversed, nil
}
func BIP68Decode(sequence []byte) (uint, error) {
var asNumber int64
for i := len(sequence) - 1; i >= 0; i-- {
asNumber = asNumber<<8 | int64(sequence[i])
}
if asNumber&SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
return 0, fmt.Errorf("sequence is disabled")
}
if asNumber&SEQUENCE_LOCKTIME_TYPE_FLAG != 0 {
seconds := asNumber & SEQUENCE_LOCKTIME_MASK << SEQUENCE_LOCKTIME_GRANULARITY
return uint(seconds), nil
}
return 0, fmt.Errorf("sequence is encoded as block number")
}