go-blockchain/chain/index.go
Snider 76488e0beb
Some checks are pending
Security Scan / security (push) Waiting to run
Test / Test (push) Waiting to run
feat(wire): add alias entry readers + AX usage-example comments
Add readExtraAliasEntryOld (tag 20) and readExtraAliasEntry (tag 33)
wire readers so the node can deserialise blocks containing alias
registrations. Without these readers, mainnet sync would fail on any
block with an alias transaction. Three round-trip tests validate the
new readers.

Also apply AX-2 (comments as usage examples) across 12 files: add
concrete usage-example comments to exported functions in config/,
types/, wire/, chain/, difficulty/, and consensus/. Fix stale doc
in consensus/doc.go that incorrectly referenced *config.ChainConfig.

Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-05 08:46:54 +01:00

107 lines
3.3 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 (
"encoding/json"
"errors"
"fmt"
"strconv"
coreerr "dappco.re/go/core/log"
"dappco.re/go/core/blockchain/types"
store "dappco.re/go/core/store"
)
// MarkSpent records a key image as spent at the given block height.
//
// err := blockchain.MarkSpent(input.KeyImage, blockHeight)
func (c *Chain) MarkSpent(ki types.KeyImage, height uint64) error {
if err := c.store.Set(groupSpentKeys, ki.String(), strconv.FormatUint(height, 10)); err != nil {
return coreerr.E("Chain.MarkSpent", fmt.Sprintf("chain: mark spent %s", ki), err)
}
return nil
}
// IsSpent checks whether a key image has been spent.
//
// spent, err := blockchain.IsSpent(keyImage)
func (c *Chain) IsSpent(ki types.KeyImage) (bool, error) {
_, err := c.store.Get(groupSpentKeys, ki.String())
if errors.Is(err, store.ErrNotFound) {
return false, nil
}
if err != nil {
return false, coreerr.E("Chain.IsSpent", fmt.Sprintf("chain: check spent %s", ki), err)
}
return true, nil
}
// outputGroup returns the go-store group for outputs of the given amount.
func outputGroup(amount uint64) string {
return groupOutputsPfx + strconv.FormatUint(amount, 10)
}
// PutOutput appends an output to the global index for the given amount.
// Returns the assigned global index.
func (c *Chain) PutOutput(amount uint64, txID types.Hash, outNo uint32) (uint64, error) {
grp := outputGroup(amount)
count, err := c.store.Count(grp)
if err != nil {
return 0, coreerr.E("Chain.PutOutput", "chain: output count", err)
}
gindex := uint64(count)
entry := outputEntry{
TxID: txID.String(),
OutNo: outNo,
}
val, err := json.Marshal(entry)
if err != nil {
return 0, coreerr.E("Chain.PutOutput", "chain: marshal output", err)
}
key := strconv.FormatUint(gindex, 10)
if err := c.store.Set(grp, key, string(val)); err != nil {
return 0, coreerr.E("Chain.PutOutput", "chain: store output", err)
}
return gindex, nil
}
// GetOutput retrieves an output by amount and global index.
func (c *Chain) GetOutput(amount uint64, gindex uint64) (types.Hash, uint32, error) {
grp := outputGroup(amount)
key := strconv.FormatUint(gindex, 10)
val, err := c.store.Get(grp, key)
if err != nil {
if errors.Is(err, store.ErrNotFound) {
return types.Hash{}, 0, coreerr.E("Chain.GetOutput", fmt.Sprintf("chain: output %d:%d not found", amount, gindex), nil)
}
return types.Hash{}, 0, coreerr.E("Chain.GetOutput", "chain: get output", err)
}
var entry outputEntry
if err := json.Unmarshal([]byte(val), &entry); err != nil {
return types.Hash{}, 0, coreerr.E("Chain.GetOutput", "chain: unmarshal output", err)
}
hash, err := types.HashFromHex(entry.TxID)
if err != nil {
return types.Hash{}, 0, coreerr.E("Chain.GetOutput", "chain: parse output tx_id", err)
}
return hash, entry.OutNo, nil
}
// OutputCount returns the number of outputs indexed for the given amount.
//
// count, err := blockchain.OutputCount(1_000_000_000_000)
func (c *Chain) OutputCount(amount uint64) (uint64, error) {
n, err := c.store.Count(outputGroup(amount))
if err != nil {
return 0, coreerr.E("Chain.OutputCount", "chain: output count", err)
}
return uint64(n), nil
}