mirror of
https://github.com/alexgo-io/gaze-indexer.git
synced 2026-04-30 20:52:01 +08:00
* fix: don't remove first block * fix: make etching_terms nullable * fix: fix panic if empty pkscript * chore: change testnet starting block * feat: more logs * fix: extract tapscript bug * feat: more logs * fix: switch pk to block height * chore: remove redundant log * fix: repo * fix: not found error * fix: golangci-lint * feat: add etching tx hash to rune entries * feat: stop main if indexer failed * fix: check balance after populating current balance * fix: sql ambiguous column * feat: add tx hash and out index in tx output * fix: actually use transactions to write db * fix: create rune entry states only during flushes * fix: mint cap reached off by one * fix: debug log unsafe * feat: prevent processing of txs before activation height * feat: add rune number to rune entry * feat: include new rune entries in event hash and flushing * refactor(config): separate init and get config func Co-authored-by: Gaze <dev@gaze.network> * feat: remove annoying log Co-authored-by: Gaze <dev@gaze.network> * feat: mod tidy Co-authored-by: Gaze <dev@gaze.network> * refactor: move main to root Co-authored-by: Gaze <dev@gaze.network> * feat(cli): create cli commands Co-authored-by: Gaze <dev@gaze.network> * refactor: move main logic to command Co-authored-by: Gaze <dev@gaze.network> * doc: remove unused desc Co-authored-by: Gaze <dev@gaze.network> * refactor: test structure in runestone_test.go * fix: edict flaws were ignored * feat: more tests * refactor(cli): add local flag Co-authored-by: Gaze <dev@gaze.network> * feat: set symbol limit to utf8.MaxRune * refactor(cli): flags for each module Co-authored-by: Gaze <dev@gaze.network> * feat(cli): support db selection Co-authored-by: Gaze <dev@gaze.network> * fix: remove temp code Co-authored-by: Gaze <dev@gaze.network> * fix: get data from cache in processor first, then dg * feat(cli): add version command Co-authored-by: Gaze <dev@gaze.network> * doc(cli): add refactor plan Co-authored-by: Gaze <dev@gaze.network> * refactor(cli): rename files Co-authored-by: Gaze <dev@gaze.network> * feat: add main.go Co-authored-by: Gaze <dev@gaze.network> * feat: more tests * feat: add overflow err * feat: finish runestone tests * refactor(cli): separate protocol config and cli flag Co-authored-by: Gaze <dev@gaze.network> * chore(btc): update example config Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add get block header to datasource interface Co-authored-by: Gaze <dev@gaze.network> * feat(btc): reorg handling Co-authored-by: Gaze <dev@gaze.network> * fix: interface Co-authored-by: Gaze <dev@gaze.network> * fix: rename postgres config key * fix: migrated runes indexer integration to new cli * fix: commit every block * feat(btc): add revert data query Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add revert data to processor Co-authored-by: Gaze <dev@gaze.network> * feat: implement public errors * fix: use errs in api * refactor: move api and usecase outside of internal * feat: add custom opcode check for datapush * fix: break if input utxo is not P2TR * fix: zero len destination case * fix: get the rest of transaction data in GetTransaction * refactor: create subscription utils tools Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add btc_database from datasource Co-authored-by: Gaze <dev@gaze.network> * doc(btc): add note Co-authored-by: Gaze <dev@gaze.network> * wip(btc): imple prepare range func Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add pg queries for datasource Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update queries Co-authored-by: Gaze <dev@gaze.network> * feat(btc): implement repo for get blocks Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update dg Co-authored-by: Gaze <dev@gaze.network> * fix(btc): return nil if errors Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update fetch async for db datasource Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add get block header from db for reorg handling Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add todo notes Co-authored-by: Gaze <dev@gaze.network> * feat: implement get tx by hash * fix: rename func * fix: rename func * fix: rename func * fix: fix get transaction by hash * feat: integrate bitcoin client db to main * fix: reduce chunk size * fix: stop main if bitcoin indexer failed * fix: stop main if runes indexer failed * fix: move stop() inside goroutine * chore: add log * fix: duplicate rune entry number * feat(btc): add witness utils Co-authored-by: Gaze <dev@gaze.network> * feat(btc): witness datamodel parsing Co-authored-by: Gaze <dev@gaze.network> * fix(btc): invalid table name Co-authored-by: Gaze <dev@gaze.network> * fix(btc): remove uniqte index for hash Co-authored-by: Gaze <dev@gaze.network> * doc: add todo Co-authored-by: Gaze <dev@gaze.network> * feat(logger): remove error verbose Co-authored-by: Gaze <dev@gaze.network> * feat: support postgresql db Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add err notfound Co-authored-by: Gaze <dev@gaze.network> * fix: invalid pgx version Co-authored-by: Gaze <dev@gaze.network> * fix: invalid indexer flow Co-authored-by: Gaze <dev@gaze.network> * feat: refactor runes api * feat: implement http server * fix: mount runes api * fix: error handler * fix: first empty state error Co-authored-by: Gaze <dev@gaze.network> * fix: off by one confirmation * ci: ignore RollBack error * fix: change WithPublicMessage to be prefix * feat: bump cstream version Co-authored-by: Gaze <dev@gaze.network> * feat(btc): nullable pkscript Co-authored-by: Gaze <dev@gaze.network> * feat(btc): change rollback style Co-authored-by: Gaze <dev@gaze.network> * refactor: move runes out of internal * feat: rename id field to runeId in rune transaction * feat(btc): update index Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add default current block Co-authored-by: Gaze <dev@gaze.network> * doc: add note Co-authored-by: Gaze <dev@gaze.network> * fix(btc): use int64 to store sequence Co-authored-by: Gaze <dev@gaze.network> * fix(btc): upgrade data type for numbers Co-authored-by: Gaze <dev@gaze.network> * feat(btc): upgrade data type for idx Co-authored-by: Gaze <dev@gaze.network> * feat(btc): get indexed block impl Co-authored-by: Gaze <dev@gaze.network> * feat(btc): add common.ZeroHash Co-authored-by: Gaze <dev@gaze.network> * feat: add chainparam * feat: implement get transactions * fix: wrong condition for non-OP_RETURN output * feat(btc): add verify indexer states Co-authored-by: Gaze <dev@gaze.network> * refactor: sorting code Co-authored-by: Gaze <dev@gaze.network> * feat: fix interface * feat(btc): update chuunk size Co-authored-by: Gaze <dev@gaze.network> * feat: add rune_etched column in rune transaction * fix: missing field in create * feat: add runeEtched in get transactions * feat: implement get token info * feat: add holders count in token info * feat: implement get holders * fix: return a new repository when beginning a new tx * fix: rename type * feat: add pkscript to outpoint balance * feat: implement get utxos by address api * fix: spend outpoint bug * feat: implement get balances by address batch * feat: sort balances result by amount * ci: create Dockerfile Co-authored-by: Gaze <dev@gaze.network> * ci: add arg run Co-authored-by: Gaze <dev@gaze.network> * perf: add automaxprocs Co-authored-by: Gaze <dev@gaze.network> * chore: add performance logging Co-authored-by: Gaze <dev@gaze.network> * chore: add performance logger for debyug Co-authored-by: Gaze <dev@gaze.network> * fix: empty etched at * fix: revert data sequentially * fix: remove unused funcs * fix: main.go * feat: add flag --api-only to run cmd * fix: create index * fix: don't add zero mint to unallocated * fix: ignore zero burn amount * feat(reorg): add reorg detail Co-authored-by: Gaze <dev@gaze.network> * fix: wrong index type * feat: implement reporting client to report runes blocks * feat: implement report node * feat(runes): add latest block api Co-authored-by: Gaze <dev@gaze.network> * feat(btc): use logger warn Co-authored-by: Gaze <dev@gaze.network> * fix(btc): txout aren't revert if it's have to revert spent Co-authored-by: Gaze <dev@gaze.network> * fix: annoying error when unsubscribe fetcher Co-authored-by: Gaze <dev@gaze.network> * refactor(btc): readable code Co-authored-by: Gaze <dev@gaze.network> * fix(indexer): fix subscription closed before process when success fetch Co-authored-by: Gaze <dev@gaze.network> * fix: remove module enum * fix: increase max reorg limit * feat: add starting height for runes mainnet * fix(btc): fix `with` modified same row twice Co-authored-by: Gaze <dev@gaze.network> * fix(runes): handling latest block not found Co-authored-by: Gaze <dev@gaze.network> * feat: add decimals in get transactions * fix: wrong condition * feat: add more index * feat: implement get transactions by pkscript * feat: allow query by rune id too * feat: more comments * perf(btc): bitcoin indexer performance optimization (#4) * feat(btc): not null to witness Co-authored-by: Gaze <dev@gaze.network> * perf(btc): add batch insert txin Co-authored-by: Gaze <dev@gaze.network> * perf(btc): batch insert txout Co-authored-by: Gaze <dev@gaze.network> * perf(btc): batch insert transaction Co-authored-by: Gaze <dev@gaze.network> * feat(btc): remove old queries Co-authored-by: Gaze <dev@gaze.network> * fix(btc): typo Co-authored-by: Gaze <dev@gaze.network> * perf(btc): batch insert blocks (#5) Co-authored-by: Gaze <gazenw@users.noreply.github.com> --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat(btc): Duplicate coinbase transaction handling (#7) * feat(btc): tx_hash can duplicated in block v1 Co-authored-by: Gaze <dev@gaze.network> * feat(btc): duplicate tx will use same txin/txout from previous tx Co-authored-by: Gaze <dev@gaze.network> * feat(btc): prevent revert block v1 data if you really want to revert the data before the block version 2, you should reset the database and reindex the data instead. Co-authored-by: Gaze <dev@gaze.network> * doc(btc): update list duplicate tx hash Co-authored-by: Gaze <dev@gaze.network> * doc(btc): update docs Co-authored-by: Gaze <dev@gaze.network> * fix(btc): use last v1 block instead Co-authored-by: Gaze <dev@gaze.network> --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat: add ping handler * fix: type Co-authored-by: Gaze <dev@gaze.network> * doc: add refactor note Co-authored-by: Gaze <dev@gaze.network> * ci: add golang linter and test runner gh action * ci: use go-test-action@v0 * ci: annotate test result * ci: update running flag * fix: try to fix malformed import path * feat: add mock test * ci: remove annotation ci * ci: add annotate test result * chore: remove unused * feat: try testify * feat: remove test * ci: add go test on macos, windows and go latest version * ci: test building * feat: remove mock code * ci: add sqlc diff checker action (#10) * feat: Graceful shutdown (#8) * feat: add shutdown function for indexer Co-authored-by: Gaze <dev@gaze.network> * feat: add force shutdown Co-authored-by: Gaze <dev@gaze.network> * revert Co-authored-by: Gaze <dev@gaze.network> * feat(btc): remove unused Co-authored-by: Gaze <dev@gaze.network> * style: go fmt Co-authored-by: Gaze <dev@gaze.network> * feat: separate context for worker and application * feat: increase force shutdown timeout Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update logging Co-authored-by: Gaze <dev@gaze.network> * feat(btc): update shutdown function Co-authored-by: Gaze <dev@gaze.network> * feat: remove wg for shutdown Co-authored-by: Gaze <dev@gaze.network> * feat: refactor shutdown flow Co-authored-by: Gaze <dev@gaze.network> * feat: update shutdown flow Co-authored-by: Gaze <dev@gaze.network> * feat: update maming Co-authored-by: Gaze <dev@gaze.network> * feat: update force shutdown logic Co-authored-by: Gaze <dev@gaze.network> --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat: check reporting config name * fix: use db config in bitcoin module for runes datasource * Add migrate commands (#2) * feat: add migrate up * feat: add down migration * fix: example * feat: change description * fix: hardcode migration source directory * Update README.md for public release. (#11) * feat: initial draft for README.md * fix: remove some sections * feat: add block reporting to first description * fix: reduce redundancy * feat: update README.md * Update README.md * feat: update README.md * fix: update config.yaml in README * fix: remove redundant words * fix: change default datasource * fix: config.yaml comments * feat: update README.md * refactor(logger): format logging (#12) * feat(logger): format main logger * feat(logger): use duration ms for gcp output * refactor(logger): bitcoin node logger * refactor(logger): indexer logger * refactor(logger): fix cmd logger * refactor(logger): logger in config pacakge * refactor(logger): set pgx error log level debug * refactor(logger): btcclient datasource * refactor: processor name * refactor(logger): runese logger * refactor(logger): update logger * fix(runes): wrong btc db datasource * refactor(logger): remove unnecessary debug log * refactor: update logger in indexer * fix(logger): deadlock in load() * fix: remove unused --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> * feat(btc): remove unused func * fix: fix golangci-lint error * fix(pg): update logger level * doc: update config example * feat: go mod tidy * doc: update readme * fix: panic cause didn't handle error * doc: update example config * doc: update example config in readme * feat(logger): only log error stacktrace when debug mode is on * feat(reporting): handling invalid config error * feat(pg): handling invalid config error * fix: panic in get_token_info --------- Co-authored-by: Gaze <gazenw@users.noreply.github.com> Co-authored-by: Planxnx <thanee@cleverse.com> Co-authored-by: Thanee Charattrakool <37617738+Planxnx@users.noreply.github.com>
273 lines
7.6 KiB
Go
273 lines
7.6 KiB
Go
package runes
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/Cleverse/go-utilities/utils"
|
|
"github.com/gaze-network/indexer-network/common"
|
|
"github.com/gaze-network/uint128"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestRuneString(t *testing.T) {
|
|
test := func(rune Rune, encoded string) {
|
|
t.Run(encoded, func(t *testing.T) {
|
|
t.Parallel()
|
|
actualEncoded := rune.String()
|
|
assert.Equal(t, encoded, actualEncoded)
|
|
|
|
actualRune, err := NewRuneFromString(encoded)
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, rune, actualRune)
|
|
})
|
|
}
|
|
|
|
test(NewRune(0), "A")
|
|
test(NewRune(1), "B")
|
|
test(NewRune(2), "C")
|
|
test(NewRune(3), "D")
|
|
test(NewRune(4), "E")
|
|
test(NewRune(5), "F")
|
|
test(NewRune(6), "G")
|
|
test(NewRune(7), "H")
|
|
test(NewRune(8), "I")
|
|
test(NewRune(9), "J")
|
|
test(NewRune(10), "K")
|
|
test(NewRune(11), "L")
|
|
test(NewRune(12), "M")
|
|
test(NewRune(13), "N")
|
|
test(NewRune(14), "O")
|
|
test(NewRune(15), "P")
|
|
test(NewRune(16), "Q")
|
|
test(NewRune(17), "R")
|
|
test(NewRune(18), "S")
|
|
test(NewRune(19), "T")
|
|
test(NewRune(20), "U")
|
|
test(NewRune(21), "V")
|
|
test(NewRune(22), "W")
|
|
test(NewRune(23), "X")
|
|
test(NewRune(24), "Y")
|
|
test(NewRune(25), "Z")
|
|
test(NewRune(26), "AA")
|
|
test(NewRune(27), "AB")
|
|
test(NewRune(51), "AZ")
|
|
test(NewRune(52), "BA")
|
|
test(NewRune(53), "BB")
|
|
test(NewRuneFromUint128(utils.Must(uint128.FromString("2055900680524219742"))), "UNCOMMONGOODS")
|
|
test(NewRuneFromUint128(uint128.Max.Sub64(2)), "BCGDENLQRQWDSLRUGSNLBTMFIJAT")
|
|
test(NewRuneFromUint128(uint128.Max.Sub64(1)), "BCGDENLQRQWDSLRUGSNLBTMFIJAU")
|
|
test(NewRuneFromUint128(uint128.Max), "BCGDENLQRQWDSLRUGSNLBTMFIJAV")
|
|
}
|
|
|
|
func TestNewRuneFromBase26Error(t *testing.T) {
|
|
_, err := NewRuneFromString("?")
|
|
assert.ErrorIs(t, err, ErrInvalidBase26)
|
|
}
|
|
|
|
func TestFirstRuneHeight(t *testing.T) {
|
|
test := func(network common.Network, expected uint64) {
|
|
t.Run(network.String(), func(t *testing.T) {
|
|
t.Parallel()
|
|
actual := FirstRuneHeight(network)
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
|
|
test(common.NetworkMainnet, 840_000)
|
|
test(common.NetworkTestnet, 2_520_000)
|
|
}
|
|
|
|
func TestMinimumRuneAtHeightMainnet(t *testing.T) {
|
|
test := func(height uint64, encoded string) {
|
|
t.Run(fmt.Sprintf("%d", height), func(t *testing.T) {
|
|
t.Parallel()
|
|
rune, err := NewRuneFromString(encoded)
|
|
assert.NoError(t, err)
|
|
actual := MinimumRuneAtHeight(common.NetworkMainnet, height)
|
|
assert.Equal(t, rune, actual)
|
|
})
|
|
}
|
|
|
|
start := FirstRuneHeight(common.NetworkMainnet)
|
|
end := start + common.HalvingInterval
|
|
interval := uint64(common.HalvingInterval / 12)
|
|
|
|
test(0, "AAAAAAAAAAAAA")
|
|
test(start/2, "AAAAAAAAAAAAA")
|
|
test(start, "ZZYZXBRKWXVA")
|
|
test(start+1, "ZZXZUDIVTVQA")
|
|
test(end-1, "A")
|
|
test(end, "A")
|
|
test(end+1, "A")
|
|
test(math.MaxUint32, "A")
|
|
|
|
test(start+interval*0-1, "AAAAAAAAAAAAA")
|
|
test(start+interval*0, "ZZYZXBRKWXVA")
|
|
test(start+interval*0+1, "ZZXZUDIVTVQA")
|
|
|
|
test(start+interval*1-1, "AAAAAAAAAAAA")
|
|
test(start+interval*1, "ZZYZXBRKWXV")
|
|
test(start+interval*1+1, "ZZXZUDIVTVQ")
|
|
|
|
test(start+interval*2-1, "AAAAAAAAAAA")
|
|
test(start+interval*2, "ZZYZXBRKWY")
|
|
test(start+interval*2+1, "ZZXZUDIVTW")
|
|
|
|
test(start+interval*3-1, "AAAAAAAAAA")
|
|
test(start+interval*3, "ZZYZXBRKX")
|
|
test(start+interval*3+1, "ZZXZUDIVU")
|
|
|
|
test(start+interval*4-1, "AAAAAAAAA")
|
|
test(start+interval*4, "ZZYZXBRL")
|
|
test(start+interval*4+1, "ZZXZUDIW")
|
|
|
|
test(start+interval*5-1, "AAAAAAAA")
|
|
test(start+interval*5, "ZZYZXBS")
|
|
test(start+interval*5+1, "ZZXZUDJ")
|
|
|
|
test(start+interval*6-1, "AAAAAAA")
|
|
test(start+interval*6, "ZZYZXC")
|
|
test(start+interval*6+1, "ZZXZUE")
|
|
|
|
test(start+interval*7-1, "AAAAAA")
|
|
test(start+interval*7, "ZZYZY")
|
|
test(start+interval*7+1, "ZZXZV")
|
|
|
|
test(start+interval*8-1, "AAAAA")
|
|
test(start+interval*8, "ZZZA")
|
|
test(start+interval*8+1, "ZZYA")
|
|
|
|
test(start+interval*9-1, "AAAA")
|
|
test(start+interval*9, "ZZZ")
|
|
test(start+interval*9+1, "ZZY")
|
|
|
|
test(start+interval*10-2, "AAC")
|
|
test(start+interval*10-1, "AAA")
|
|
test(start+interval*10, "AAA")
|
|
test(start+interval*10+1, "AAA")
|
|
|
|
test(start+interval*10+interval/2, "NA")
|
|
|
|
test(start+interval*11-2, "AB")
|
|
test(start+interval*11-1, "AA")
|
|
test(start+interval*11, "AA")
|
|
test(start+interval*11+1, "AA")
|
|
|
|
test(start+interval*11+interval/2, "N")
|
|
|
|
test(start+interval*12-2, "B")
|
|
test(start+interval*12-1, "A")
|
|
test(start+interval*12, "A")
|
|
test(start+interval*12+1, "A")
|
|
}
|
|
|
|
func TestMinimumRuneAtHeightTestnet(t *testing.T) {
|
|
test := func(height uint64, runeStr string) {
|
|
t.Run(fmt.Sprintf("%d", height), func(t *testing.T) {
|
|
t.Parallel()
|
|
rune, err := NewRuneFromString(runeStr)
|
|
assert.NoError(t, err)
|
|
actual := MinimumRuneAtHeight(common.NetworkTestnet, height)
|
|
assert.Equal(t, rune, actual)
|
|
})
|
|
}
|
|
|
|
start := FirstRuneHeight(common.NetworkTestnet)
|
|
|
|
test(start-1, "AAAAAAAAAAAAA")
|
|
test(start, "ZZYZXBRKWXVA")
|
|
test(start+1, "ZZXZUDIVTVQA")
|
|
}
|
|
|
|
func TestIsReserved(t *testing.T) {
|
|
test := func(runeStr string, expected bool) {
|
|
t.Run(runeStr, func(t *testing.T) {
|
|
t.Parallel()
|
|
rune, err := NewRuneFromString(runeStr)
|
|
assert.NoError(t, err)
|
|
actual := rune.IsReserved()
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
|
|
test("A", false)
|
|
test("B", false)
|
|
test("ZZZZZZZZZZZZZZZZZZZZZZZZZZ", false)
|
|
test("AAAAAAAAAAAAAAAAAAAAAAAAAAA", true)
|
|
test("AAAAAAAAAAAAAAAAAAAAAAAAAAB", true)
|
|
test("BCGDENLQRQWDSLRUGSNLBTMFIJAV", true)
|
|
}
|
|
|
|
func TestGetReservedRune(t *testing.T) {
|
|
test := func(blockHeight uint64, txIndex uint32, expected Rune) {
|
|
t.Run(fmt.Sprintf("blockHeight_%d_txIndex_%d", blockHeight, txIndex), func(t *testing.T) {
|
|
t.Parallel()
|
|
rune := GetReservedRune(blockHeight, txIndex)
|
|
assert.Equal(t, expected.String(), rune.String())
|
|
})
|
|
}
|
|
|
|
test(0, 0, firstReservedRune)
|
|
test(0, 1, Rune(firstReservedRune.Uint128().Add(uint128.From64(1))))
|
|
test(0, 2, Rune(firstReservedRune.Uint128().Add(uint128.From64(2))))
|
|
test(1, 0, Rune(firstReservedRune.Uint128().Add(uint128.From64(1).Lsh(32))))
|
|
test(1, 1, Rune(firstReservedRune.Uint128().Add(uint128.From64(1).Lsh(32).Add(uint128.From64(1)))))
|
|
test(1, 2, Rune(firstReservedRune.Uint128().Add(uint128.From64(1).Lsh(32).Add(uint128.From64(2)))))
|
|
test(2, 0, Rune(firstReservedRune.Uint128().Add(uint128.From64(2).Lsh(32))))
|
|
test(2, 1, Rune(firstReservedRune.Uint128().Add(uint128.From64(2).Lsh(32).Add(uint128.From64(1)))))
|
|
test(2, 2, Rune(firstReservedRune.Uint128().Add(uint128.From64(2).Lsh(32).Add(uint128.From64(2)))))
|
|
test(math.MaxUint64, math.MaxUint32, Rune(firstReservedRune.Uint128().Add(uint128.From64(math.MaxUint64).Lsh(32).Add(uint128.From64(math.MaxUint32)))))
|
|
}
|
|
|
|
func TestUnlockSteps(t *testing.T) {
|
|
for i := 0; i < len(unlockSteps); i++ {
|
|
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
|
|
t.Parallel()
|
|
encoded := Rune(unlockSteps[i]).String()
|
|
expected := strings.Repeat("A", i+1)
|
|
assert.Equal(t, expected, encoded)
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCommitment(t *testing.T) {
|
|
test := func(rune Rune, expected []byte) {
|
|
t.Run(rune.String(), func(t *testing.T) {
|
|
t.Parallel()
|
|
actual := rune.Commitment()
|
|
assert.Equal(t, expected, actual)
|
|
})
|
|
}
|
|
|
|
test(NewRune(0), []byte{})
|
|
test(NewRune(1), []byte{1})
|
|
test(NewRune(2), []byte{2})
|
|
test(NewRune(255), []byte{255})
|
|
test(NewRune(256), []byte{0, 1})
|
|
test(NewRune(257), []byte{1, 1})
|
|
test(NewRune(65535), []byte{255, 255})
|
|
test(NewRune(65536), []byte{0, 0, 1})
|
|
}
|
|
|
|
func TestRuneMarshal(t *testing.T) {
|
|
rune := NewRune(5)
|
|
bytes, err := rune.MarshalJSON()
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, []byte(`"F"`), bytes)
|
|
}
|
|
|
|
func TestRuneUnmarshal(t *testing.T) {
|
|
str := `"F"`
|
|
var rune Rune
|
|
err := rune.UnmarshalJSON([]byte(str))
|
|
assert.NoError(t, err)
|
|
assert.Equal(t, NewRune(5), rune)
|
|
|
|
str = `1`
|
|
err = rune.UnmarshalJSON([]byte(str))
|
|
assert.Error(t, err)
|
|
}
|