feat: add event hash logic

This commit is contained in:
Gaze
2024-06-10 00:09:18 +07:00
parent 49eff4f3ba
commit 05d7fecf69
6 changed files with 139 additions and 30 deletions

View 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()
}

View File

@@ -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
}

View File

@@ -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),
}
}

View File

@@ -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

View File

@@ -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
}

View File

@@ -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