mirror of
https://github.com/alexgo-io/gaze-brc20-indexer.git
synced 2026-01-12 14:34:54 +08:00
feat: add event hash logic
This commit is contained in:
69
modules/brc20/event_hash.go
Normal file
69
modules/brc20/event_hash.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package brc20
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gaze-network/indexer-network/modules/brc20/internal/entity"
|
||||
"github.com/samber/lo"
|
||||
)
|
||||
|
||||
const eventHashSeparator = "|"
|
||||
|
||||
func getEventDeployString(event *entity.EventDeploy) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("deploy-inscribe;")
|
||||
sb.WriteString(event.InscriptionId.String() + ";")
|
||||
sb.WriteString(hex.EncodeToString(event.PkScript) + ";")
|
||||
sb.WriteString(event.Tick + ";")
|
||||
sb.WriteString(event.OriginalTick + ";")
|
||||
sb.WriteString(event.TotalSupply.StringFixed(int32(event.Decimals)) + ";")
|
||||
sb.WriteString(strconv.Itoa(int(event.Decimals)) + ";")
|
||||
sb.WriteString(event.LimitPerMint.StringFixed(int32(event.Decimals)) + ";")
|
||||
sb.WriteString(lo.Ternary(event.IsSelfMint, "True", "False"))
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func getEventMintString(event *entity.EventMint, decimals uint16) string {
|
||||
var sb strings.Builder
|
||||
var parentId string
|
||||
if event.ParentId != nil {
|
||||
parentId = event.ParentId.String()
|
||||
}
|
||||
sb.WriteString("mint-inscribe;")
|
||||
sb.WriteString(event.InscriptionId.String() + ";")
|
||||
sb.WriteString(hex.EncodeToString(event.PkScript) + ";")
|
||||
sb.WriteString(event.Tick + ";")
|
||||
sb.WriteString(event.OriginalTick + ";")
|
||||
sb.WriteString(event.Amount.StringFixed(int32(decimals)) + ";")
|
||||
sb.WriteString(parentId)
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func getEventInscribeTransferString(event *entity.EventInscribeTransfer, decimals uint16) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("inscribe-transfer;")
|
||||
sb.WriteString(event.InscriptionId.String() + ";")
|
||||
sb.WriteString(hex.EncodeToString(event.PkScript) + ";")
|
||||
sb.WriteString(event.Tick + ";")
|
||||
sb.WriteString(event.OriginalTick + ";")
|
||||
sb.WriteString(event.Amount.StringFixed(int32(decimals)))
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func getEventTransferTransferString(event *entity.EventTransferTransfer, decimals uint16) string {
|
||||
var sb strings.Builder
|
||||
sb.WriteString("transfer-transfer;")
|
||||
sb.WriteString(event.InscriptionId.String() + ";")
|
||||
sb.WriteString(hex.EncodeToString(event.FromPkScript) + ";")
|
||||
if event.SpentAsFee {
|
||||
sb.WriteString(";")
|
||||
} else {
|
||||
sb.WriteString(hex.EncodeToString(event.ToPkScript) + ";")
|
||||
}
|
||||
sb.WriteString(event.Tick + ";")
|
||||
sb.WriteString(event.OriginalTick + ";")
|
||||
sb.WriteString(event.Amount.StringFixed(int32(decimals)))
|
||||
return sb.String()
|
||||
}
|
||||
@@ -5,6 +5,6 @@ import "github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
type IndexedBlock struct {
|
||||
Height uint64
|
||||
Hash chainhash.Hash
|
||||
EventHash chainhash.Hash
|
||||
CumulativeEventHash chainhash.Hash
|
||||
EventHash []byte
|
||||
CumulativeEventHash []byte
|
||||
}
|
||||
|
||||
@@ -70,19 +70,19 @@ func mapIndexedBlockModelToType(src gen.Brc20IndexedBlock) (entity.IndexedBlock,
|
||||
if err != nil {
|
||||
return entity.IndexedBlock{}, errors.Wrap(err, "invalid block hash")
|
||||
}
|
||||
eventHash, err := chainhash.NewHashFromStr(src.EventHash)
|
||||
eventHash, err := hex.DecodeString(src.EventHash)
|
||||
if err != nil {
|
||||
return entity.IndexedBlock{}, errors.Wrap(err, "invalid event hash")
|
||||
}
|
||||
cumulativeEventHash, err := chainhash.NewHashFromStr(src.CumulativeEventHash)
|
||||
cumulativeEventHash, err := hex.DecodeString(src.CumulativeEventHash)
|
||||
if err != nil {
|
||||
return entity.IndexedBlock{}, errors.Wrap(err, "invalid cumulative event hash")
|
||||
}
|
||||
return entity.IndexedBlock{
|
||||
Height: uint64(src.Height),
|
||||
Hash: *hash,
|
||||
EventHash: *eventHash,
|
||||
CumulativeEventHash: *cumulativeEventHash,
|
||||
EventHash: eventHash,
|
||||
CumulativeEventHash: cumulativeEventHash,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ func mapIndexedBlockTypeToParams(src entity.IndexedBlock) gen.CreateIndexedBlock
|
||||
return gen.CreateIndexedBlockParams{
|
||||
Height: int32(src.Height),
|
||||
Hash: src.Hash.String(),
|
||||
EventHash: src.EventHash.String(),
|
||||
CumulativeEventHash: src.CumulativeEventHash.String(),
|
||||
EventHash: hex.EncodeToString(src.EventHash),
|
||||
CumulativeEventHash: hex.EncodeToString(src.CumulativeEventHash),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,8 @@ type Processor struct {
|
||||
newEventInscribeTransfers []*entity.EventInscribeTransfer
|
||||
newEventTransferTransfers []*entity.EventTransferTransfer
|
||||
newBalances map[string]map[string]*entity.Balance
|
||||
|
||||
eventHashString string
|
||||
}
|
||||
|
||||
// TODO: move this to config
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/cockroachdb/errors"
|
||||
@@ -96,6 +97,7 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
newEventInscribeTransfers := make([]*entity.EventInscribeTransfer, 0)
|
||||
newEventTransferTransfers := make([]*entity.EventTransferTransfer, 0)
|
||||
newBalances := make(map[string]map[string]*entity.Balance)
|
||||
var eventHashBuilder strings.Builder
|
||||
|
||||
handleEventDeploy := func(payload *brc20.Payload, tickEntry *entity.TickEntry) {
|
||||
if payload.Transfer.TransferCount > 1 {
|
||||
@@ -126,7 +128,7 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
// update entries for other operations in same block
|
||||
tickEntries[payload.Tick] = newEntry
|
||||
|
||||
newEventDeploys = append(newEventDeploys, &entity.EventDeploy{
|
||||
event := &entity.EventDeploy{
|
||||
Id: latestEventId + 1,
|
||||
InscriptionId: payload.Transfer.InscriptionId,
|
||||
InscriptionNumber: inscriptionIdsToNumber[payload.Transfer.InscriptionId],
|
||||
@@ -142,8 +144,11 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
Decimals: payload.Dec,
|
||||
LimitPerMint: payload.Lim,
|
||||
IsSelfMint: payload.SelfMint,
|
||||
})
|
||||
}
|
||||
newEventDeploys = append(newEventDeploys, event)
|
||||
latestEventId++
|
||||
|
||||
eventHashBuilder.WriteString(getEventDeployString(event) + eventHashSeparator)
|
||||
}
|
||||
handleEventMint := func(payload *brc20.Payload, tickEntry *entity.TickEntry) {
|
||||
if payload.Transfer.TransferCount > 1 {
|
||||
@@ -192,7 +197,7 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
}
|
||||
|
||||
newTickEntryStates[payload.Tick] = tickEntry
|
||||
newEventMints = append(newEventMints, &entity.EventMint{
|
||||
event := &entity.EventMint{
|
||||
Id: latestEventId + 1,
|
||||
InscriptionId: payload.Transfer.InscriptionId,
|
||||
InscriptionNumber: inscriptionIdsToNumber[payload.Transfer.InscriptionId],
|
||||
@@ -206,10 +211,13 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
SatPoint: payload.Transfer.NewSatPoint,
|
||||
Amount: payload.Amt,
|
||||
ParentId: parentId,
|
||||
})
|
||||
}
|
||||
newEventMints = append(newEventMints, event)
|
||||
latestEventId++
|
||||
|
||||
eventHashBuilder.WriteString(getEventMintString(event, tickEntry.Decimals) + eventHashSeparator)
|
||||
}
|
||||
handleEventInscribeTransfer := func(payload *brc20.Payload) {
|
||||
handleEventInscribeTransfer := func(payload *brc20.Payload, tickEntry *entity.TickEntry) {
|
||||
// inscribe transfer event
|
||||
pkScriptHex := hex.EncodeToString(payload.Transfer.NewPkScript)
|
||||
balance, ok := balances[pkScriptHex][payload.Tick]
|
||||
@@ -257,8 +265,10 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
latestEventId++
|
||||
eventInscribeTransfers[payload.Transfer.InscriptionId] = event
|
||||
newEventInscribeTransfers = append(newEventInscribeTransfers, event)
|
||||
|
||||
eventHashBuilder.WriteString(getEventInscribeTransferString(event, tickEntry.Decimals) + eventHashSeparator)
|
||||
}
|
||||
handleEventTransferTransferAsFee := func(payload *brc20.Payload, inscribeTransfer *entity.EventInscribeTransfer) {
|
||||
handleEventTransferTransferAsFee := func(payload *brc20.Payload, tickEntry *entity.TickEntry, inscribeTransfer *entity.EventInscribeTransfer) {
|
||||
// return balance to sender
|
||||
fromPkScriptHex := hex.EncodeToString(inscribeTransfer.PkScript)
|
||||
fromBalance, ok := balances[fromPkScriptHex][payload.Tick]
|
||||
@@ -282,7 +292,7 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
}
|
||||
newBalances[fromPkScriptHex][payload.Tick] = fromBalance
|
||||
|
||||
newEventTransferTransfers = append(newEventTransferTransfers, &entity.EventTransferTransfer{
|
||||
event := &entity.EventTransferTransfer{
|
||||
Id: latestEventId + 1,
|
||||
InscriptionId: payload.Transfer.InscriptionId,
|
||||
InscriptionNumber: inscriptionIdsToNumber[payload.Transfer.InscriptionId],
|
||||
@@ -300,7 +310,10 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
ToOutputIndex: payload.Transfer.NewSatPoint.OutPoint.Index,
|
||||
SpentAsFee: true,
|
||||
Amount: payload.Amt,
|
||||
})
|
||||
}
|
||||
newEventTransferTransfers = append(newEventTransferTransfers, event)
|
||||
|
||||
eventHashBuilder.WriteString(getEventTransferTransferString(event, tickEntry.Decimals) + eventHashSeparator)
|
||||
}
|
||||
handleEventTransferTransferNormal := func(payload *brc20.Payload, tickEntry *entity.TickEntry, inscribeTransfer *entity.EventInscribeTransfer) {
|
||||
// subtract balance from sender
|
||||
@@ -352,7 +365,7 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
newBalances[toPkScriptHex][payload.Tick] = toBalance
|
||||
}
|
||||
|
||||
newEventTransferTransfers = append(newEventTransferTransfers, &entity.EventTransferTransfer{
|
||||
event := &entity.EventTransferTransfer{
|
||||
Id: latestEventId + 1,
|
||||
InscriptionId: payload.Transfer.InscriptionId,
|
||||
InscriptionNumber: inscriptionIdsToNumber[payload.Transfer.InscriptionId],
|
||||
@@ -370,7 +383,10 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
ToOutputIndex: payload.Transfer.NewSatPoint.OutPoint.Index,
|
||||
SpentAsFee: false,
|
||||
Amount: payload.Amt,
|
||||
})
|
||||
}
|
||||
newEventTransferTransfers = append(newEventTransferTransfers, event)
|
||||
|
||||
eventHashBuilder.WriteString(getEventTransferTransferString(event, tickEntry.Decimals) + eventHashSeparator)
|
||||
}
|
||||
|
||||
for _, payload := range payloads {
|
||||
@@ -401,7 +417,7 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
}
|
||||
|
||||
if payload.Transfer.OldSatPoint == (ordinals.SatPoint{}) {
|
||||
handleEventInscribeTransfer(payload)
|
||||
handleEventInscribeTransfer(payload, tickEntry)
|
||||
} else {
|
||||
// transfer transfer event
|
||||
inscribeTransfer, ok := eventInscribeTransfers[payload.Transfer.InscriptionId]
|
||||
@@ -411,7 +427,7 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
}
|
||||
|
||||
if payload.Transfer.SentAsFee {
|
||||
handleEventTransferTransferAsFee(payload, inscribeTransfer)
|
||||
handleEventTransferTransferAsFee(payload, tickEntry, inscribeTransfer)
|
||||
} else {
|
||||
handleEventTransferTransferNormal(payload, tickEntry, inscribeTransfer)
|
||||
}
|
||||
@@ -426,5 +442,6 @@ func (p *Processor) processBRC20States(ctx context.Context, transfers []*entity.
|
||||
p.newEventInscribeTransfers = newEventInscribeTransfers
|
||||
p.newEventTransferTransfers = newEventTransferTransfers
|
||||
p.newBalances = newBalances
|
||||
p.eventHashString = eventHashBuilder.String()
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -2,10 +2,11 @@ package brc20
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"slices"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/cockroachdb/errors"
|
||||
"github.com/gaze-network/indexer-network/common/errs"
|
||||
"github.com/gaze-network/indexer-network/core/types"
|
||||
"github.com/gaze-network/indexer-network/modules/brc20/internal/entity"
|
||||
"github.com/gaze-network/indexer-network/modules/brc20/internal/ordinals"
|
||||
@@ -78,15 +79,35 @@ func (p *Processor) flushBlock(ctx context.Context, blockHeader types.BlockHeade
|
||||
|
||||
blockHeight := uint64(blockHeader.Height)
|
||||
|
||||
// CreateIndexedBlock must be performed before other flush methods to correctly calculate event hash
|
||||
// TODO: calculate event hash
|
||||
if err := brc20DgTx.CreateIndexedBlock(ctx, &entity.IndexedBlock{
|
||||
Height: blockHeight,
|
||||
Hash: blockHeader.Hash,
|
||||
EventHash: chainhash.Hash{},
|
||||
CumulativeEventHash: chainhash.Hash{},
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to create indexed block")
|
||||
// calculate event hash
|
||||
{
|
||||
eventHashString := p.eventHashString
|
||||
if len(eventHashString) > 0 && eventHashString[len(eventHashString)-1:] == eventHashSeparator {
|
||||
eventHashString = eventHashString[:len(eventHashString)-1]
|
||||
}
|
||||
eventHash := sha256.Sum256([]byte(eventHashString))
|
||||
prevIndexedBlock, err := brc20DgTx.GetIndexedBlockByHeight(ctx, blockHeader.Height-1)
|
||||
if err != nil && errors.Is(err, errs.NotFound) && blockHeader.Height-1 == startingBlockHeader[p.network].Height {
|
||||
prevIndexedBlock = &entity.IndexedBlock{
|
||||
Height: uint64(startingBlockHeader[p.network].Height),
|
||||
Hash: startingBlockHeader[p.network].Hash,
|
||||
EventHash: []byte{},
|
||||
CumulativeEventHash: []byte{},
|
||||
}
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get previous indexed block")
|
||||
}
|
||||
cumulativeEventHash := sha256.Sum256(append(prevIndexedBlock.CumulativeEventHash[:], eventHash[:]...))
|
||||
if err := brc20DgTx.CreateIndexedBlock(ctx, &entity.IndexedBlock{
|
||||
Height: blockHeight,
|
||||
Hash: blockHeader.Hash,
|
||||
EventHash: eventHash[:],
|
||||
CumulativeEventHash: cumulativeEventHash[:],
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "failed to create indexed block")
|
||||
}
|
||||
}
|
||||
|
||||
// flush new inscription entries
|
||||
|
||||
Reference in New Issue
Block a user