Update go.mod module line, all require/replace directives, and every .go import path from forge.lthn.ai/core/go-blockchain to dappco.re/go/core/blockchain. Add replace directives to bridge dappco.re paths to existing forge.lthn.ai registry during migration. Update CLAUDE.md, README, and docs to reflect the new module path. Co-Authored-By: Virgil <virgil@lethean.io>
119 lines
3.5 KiB
Go
119 lines
3.5 KiB
Go
// Copyright (c) 2017-2026 Lethean (https://lt.hn)
|
|
//
|
|
// Licensed under the European Union Public Licence (EUPL) version 1.2.
|
|
// SPDX-License-Identifier: EUPL-1.2
|
|
|
|
package chain
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"dappco.re/go/core/blockchain/types"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestSparseChainHistory_Empty(t *testing.T) {
|
|
c := newTestChain(t)
|
|
|
|
history, err := c.SparseChainHistory()
|
|
require.NoError(t, err)
|
|
require.Len(t, history, 1) // genesis hash so the peer can locate us
|
|
expected, _ := types.HashFromHex(GenesisHash)
|
|
require.Equal(t, expected, history[0])
|
|
}
|
|
|
|
func TestSparseChainHistory_FewBlocks(t *testing.T) {
|
|
c := newTestChain(t)
|
|
|
|
// Store 5 blocks with known hashes.
|
|
for i := uint64(0); i < 5; i++ {
|
|
hash := types.Hash{byte(i + 1)}
|
|
blk := &types.Block{
|
|
BlockHeader: types.BlockHeader{MajorVersion: 1},
|
|
MinerTx: testCoinbaseTx(i),
|
|
}
|
|
if i > 0 {
|
|
blk.PrevID = types.Hash{byte(i)}
|
|
}
|
|
err := c.PutBlock(blk, &BlockMeta{Hash: hash, Height: i})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
history, err := c.SparseChainHistory()
|
|
require.NoError(t, err)
|
|
|
|
// With 5 blocks (heights 0-4), all within the first 10 so step=1
|
|
// throughout. Should return hashes for heights 4, 3, 2, 1, 0.
|
|
require.Greater(t, len(history), 0)
|
|
|
|
// First entry should be top block hash (height 4).
|
|
require.Equal(t, types.Hash{5}, history[0])
|
|
|
|
// Last entry should be genesis hash (height 0).
|
|
require.Equal(t, types.Hash{1}, history[len(history)-1])
|
|
|
|
// All 5 blocks should be present since count < 10.
|
|
require.Len(t, history, 5)
|
|
}
|
|
|
|
func TestSparseChainHistory_SingleBlock(t *testing.T) {
|
|
c := newTestChain(t)
|
|
|
|
blk := &types.Block{
|
|
BlockHeader: types.BlockHeader{MajorVersion: 1},
|
|
MinerTx: testCoinbaseTx(0),
|
|
}
|
|
err := c.PutBlock(blk, &BlockMeta{Hash: types.Hash{0xaa}, Height: 0})
|
|
require.NoError(t, err)
|
|
|
|
history, err := c.SparseChainHistory()
|
|
require.NoError(t, err)
|
|
require.Len(t, history, 1)
|
|
require.Equal(t, types.Hash{0xaa}, history[0])
|
|
}
|
|
|
|
func TestSparseChainHistory_ExponentialSpacing(t *testing.T) {
|
|
c := newTestChain(t)
|
|
|
|
// Store 20 blocks (heights 0-19) to exercise exponential stepping.
|
|
for i := uint64(0); i < 20; i++ {
|
|
hash := types.Hash{byte(i + 1)}
|
|
blk := &types.Block{
|
|
BlockHeader: types.BlockHeader{MajorVersion: 1},
|
|
MinerTx: testCoinbaseTx(i),
|
|
}
|
|
if i > 0 {
|
|
blk.PrevID = types.Hash{byte(i)}
|
|
}
|
|
err := c.PutBlock(blk, &BlockMeta{Hash: hash, Height: i})
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
history, err := c.SparseChainHistory()
|
|
require.NoError(t, err)
|
|
|
|
// First entry should be top block (height 19).
|
|
require.Equal(t, types.Hash{20}, history[0])
|
|
|
|
// Last entry should be genesis (height 0).
|
|
require.Equal(t, types.Hash{1}, history[len(history)-1])
|
|
|
|
// Should have fewer entries than total blocks due to exponential steps.
|
|
require.Less(t, len(history), 20)
|
|
|
|
// First 10 entries should be consecutive (step=1): heights 19, 18, ..., 10.
|
|
for i := 0; i < 10; i++ {
|
|
expected := types.Hash{byte(20 - i)}
|
|
require.Equal(t, expected, history[i],
|
|
"entry %d: expected hash for height %d", i, 19-i)
|
|
}
|
|
|
|
// After the first 10, steps double each entry:
|
|
// Entry 10: step becomes 2, current = 10 - 2 = 8 -> hash {9}
|
|
// Entry 11: step becomes 4, current = 8 - 4 = 4 -> hash {5}
|
|
// Entry 12: step becomes 8, current 4 < 8, jump to 0 -> hash {1} (genesis)
|
|
require.Equal(t, types.Hash{byte(9)}, history[10]) // height 8
|
|
require.Equal(t, types.Hash{byte(5)}, history[11]) // height 4
|
|
require.Equal(t, types.Hash{byte(1)}, history[12]) // height 0 (genesis)
|
|
require.Len(t, history, 13)
|
|
}
|