Skip to content

Commit

Permalink
Add block ledger
Browse files Browse the repository at this point in the history
  • Loading branch information
firelizzard18 committed Aug 27, 2024
1 parent f5d8e47 commit 54de673
Show file tree
Hide file tree
Showing 17 changed files with 342 additions and 34 deletions.
18 changes: 12 additions & 6 deletions internal/api/v3/event.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import (
"github.com/cometbft/cometbft/libs/log"
"gitlab.com/accumulatenetwork/accumulate/internal/core/events"
"gitlab.com/accumulatenetwork/accumulate/internal/database"
"gitlab.com/accumulatenetwork/accumulate/internal/database/record"
"gitlab.com/accumulatenetwork/accumulate/internal/logging"
"gitlab.com/accumulatenetwork/accumulate/internal/node/config"
"gitlab.com/accumulatenetwork/accumulate/pkg/api/v3"
"gitlab.com/accumulatenetwork/accumulate/pkg/errors"
"gitlab.com/accumulatenetwork/accumulate/protocol"
)

Expand Down Expand Up @@ -75,15 +77,19 @@ func (s *EventService) didCommitBlock(e events.DidCommitBlock) error {
func (s *EventService) loadBlockInfo(batch *database.Batch, e *api.BlockEvent) {
defer batch.Discard()

var ledger *protocol.BlockLedger
err := batch.Account(s.partition.BlockLedger(e.Index)).Main().GetAs(&ledger)
if err != nil {
s.logger.Error("Loading block ledger failed", "error", err, "block", e.Index, "url", s.partition.BlockLedger(e.Index))
var entries []*protocol.BlockEntry
if _, l1, e1 := batch.Account(s.partition.Ledger()).BlockLedger().Find(record.NewKey(e.Index)).Exact().Get(); e1 == nil {
entries = l1.Entries
} else if l2, e2 := batch.Account(s.partition.BlockLedger(e.Index)).Main().Get(); e2 == nil && l2.Type() == protocol.AccountTypeBlockLedger {
entries = l2.(*protocol.BlockLedger).Entries
} else {
s.logger.Error("Loading block ledger failed", "error", errors.Join(e1, e2), "block", e.Index, "url", s.partition.BlockLedger(e.Index))
return
}

e.Entries = make([]*api.ChainEntryRecord[api.Record], len(ledger.Entries))
for i, le := range ledger.Entries {
e.Entries = make([]*api.ChainEntryRecord[api.Record], len(entries))
for i, le := range entries {
var err error
e.Entries[i], err = loadBlockEntry(batch, le)
if err != nil {
s.logger.Error("Loading block entry", "error", err, "block", e.Index, "account", le.Account, "chain", le.Chain, "index", le.Index)
Expand Down
28 changes: 19 additions & 9 deletions internal/core/execute/v2/block/block_end.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ import (
"gitlab.com/accumulatenetwork/accumulate/pkg/api/v3"
"gitlab.com/accumulatenetwork/accumulate/pkg/errors"
"gitlab.com/accumulatenetwork/accumulate/pkg/types/messaging"
"gitlab.com/accumulatenetwork/accumulate/pkg/types/record"
"gitlab.com/accumulatenetwork/accumulate/pkg/url"
"gitlab.com/accumulatenetwork/accumulate/protocol"
)

// Close ends the block and returns the block state.
func (block *Block) Close() (execute.BlockState, error) {
m := block.Executor
ledgerUrl := m.Describe.NodeUrl(protocol.Ledger)
ledger := block.Batch.Account(ledgerUrl)

r := m.BlockTimers.Start(BlockTimerTypeEndBlock)
defer m.BlockTimers.Stop(r)

Expand Down Expand Up @@ -90,7 +94,7 @@ func (block *Block) Close() (execute.BlockState, error) {

// Record the previous block's state hash it on the BPT chain
if block.Executor.globals.Active.ExecutorVersion.V2BaikonurEnabled() {
err := block.Batch.Account(block.Executor.Describe.Ledger()).BptChain().Inner().AddEntry(block.State.PreviousStateHash[:], false)
err := ledger.BptChain().Inner().AddEntry(block.State.PreviousStateHash[:], false)
if err != nil {
return nil, err
}
Expand All @@ -112,8 +116,6 @@ func (block *Block) Close() (execute.BlockState, error) {
}

// Load the main chain of the minor root
ledgerUrl := m.Describe.NodeUrl(protocol.Ledger)
ledger := block.Batch.Account(ledgerUrl)
rootChain, err := ledger.RootChain().Get()
if err != nil {
return nil, errors.UnknownError.WithFormat("load root chain: %w", err)
Expand Down Expand Up @@ -169,12 +171,20 @@ func (block *Block) Close() (execute.BlockState, error) {
}

// Record the block entries
bl := new(protocol.BlockLedger)
bl.Url = m.Describe.Ledger().JoinPath(strconv.FormatUint(block.Index, 10))
bl.Index = block.Index
bl.Time = block.Time
bl.Entries = block.State.ChainUpdates.Entries
err = block.Batch.Account(bl.Url).Main().Put(bl)
if block.Executor.globals.Active.ExecutorVersion.V2JiuquanEnabled() {
bl := new(database.BlockLedger)
bl.Index = block.Index
bl.Time = block.Time
bl.Entries = block.State.ChainUpdates.Entries
err = ledger.BlockLedger().Append(record.NewKey(block.Index), bl)
} else {
bl := new(protocol.BlockLedger)
bl.Url = m.Describe.Ledger().JoinPath(strconv.FormatUint(block.Index, 10))
bl.Index = block.Index
bl.Time = block.Time
bl.Entries = block.State.ChainUpdates.Entries
err = block.Batch.Account(bl.Url).Main().Put(bl)
}
if err != nil {
return nil, errors.UnknownError.WithFormat("store block ledger: %w", err)
}
Expand Down
8 changes: 4 additions & 4 deletions internal/database/account.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ func (a *Account) Commit() error {
return nil
}

// Prevent any accounts other than the system ledger from modifying events
if values.IsDirty(a.events) {
// Prevent any accounts other than the system ledger from modifying events or the block ledger
if values.IsDirty(a.events) || values.IsDirty(a.blockLedger) {
u := a.Url()
if _, ok := protocol.ParsePartitionUrl(u); !ok {
return errors.InternalError.WithFormat("%v is not allowed to have events", u)
return errors.InternalError.WithFormat("%v is not allowed to have events/blocks", u)
}
if !u.PathEqual(protocol.Ledger) {
return errors.InternalError.WithFormat("%v is not allowed to have events", u)
return errors.InternalError.WithFormat("%v is not allowed to have events/blocks", u)
}
}

Expand Down
7 changes: 7 additions & 0 deletions internal/database/model.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,13 @@
constructor: newBPT
pointer: true

- name: BlockLedger
description: indexes entries of a block. Should only be used on the system ledger
type: other
dataType: indexing.Log[*BlockLedger]
constructor: newBlockEntryLog
pointer: true

- name: Transaction
type: entity
index: getTransactionKeys # Indexed by pending (more or less)
Expand Down
17 changes: 17 additions & 0 deletions internal/database/model_gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"gitlab.com/accumulatenetwork/accumulate/internal/logging"
record "gitlab.com/accumulatenetwork/accumulate/pkg/database"
"gitlab.com/accumulatenetwork/accumulate/pkg/database/bpt"
"gitlab.com/accumulatenetwork/accumulate/pkg/database/indexing"
"gitlab.com/accumulatenetwork/accumulate/pkg/database/values"
"gitlab.com/accumulatenetwork/accumulate/pkg/errors"
"gitlab.com/accumulatenetwork/accumulate/pkg/types/messaging"
Expand Down Expand Up @@ -299,6 +300,7 @@ type Account struct {
syntheticForAnchor map[accountSyntheticForAnchorMapKey]values.Set[*url.TxID]
directory values.Set[*url.URL]
events *AccountEvents
blockLedger *indexing.Log[*BlockLedger]
transaction map[accountTransactionMapKey]*AccountTransaction
mainChain *Chain2
scratchChain *Chain2
Expand Down Expand Up @@ -417,6 +419,14 @@ func (c *Account) newEvents() *AccountEvents {
return v
}

func (c *Account) BlockLedger() *indexing.Log[*BlockLedger] {
return values.GetOrCreate(c, &c.blockLedger, (*Account).newBlockLedger)
}

func (c *Account) newBlockLedger() *indexing.Log[*BlockLedger] {
return newBlockEntryLog(c, c.logger.L, c.store, c.key.Append("BlockLedger"), "block-ledger")
}

func (c *Account) Transaction(hash [32]byte) *AccountTransaction {
return values.GetOrCreateMap(c, &c.transaction, accountTransactionKey{hash}, (*Account).newTransaction)
}
Expand Down Expand Up @@ -562,6 +572,8 @@ func (c *Account) Resolve(key *record.Key) (record.Record, *record.Key, error) {
return c.Directory(), key.SliceI(1), nil
case "Events":
return c.Events(), key.SliceI(1), nil
case "BlockLedger":
return c.BlockLedger(), key.SliceI(1), nil
case "Transaction":
if key.Len() < 2 {
return nil, nil, errors.InternalError.With("bad key for account (4)")
Expand Down Expand Up @@ -642,6 +654,9 @@ func (c *Account) IsDirty() bool {
if values.IsDirty(c.events) {
return true
}
if values.IsDirty(c.blockLedger) {
return true
}
for _, v := range c.transaction {
if v.IsDirty() {
return true
Expand Down Expand Up @@ -730,6 +745,7 @@ func (c *Account) Walk(opts record.WalkOptions, fn record.WalkFunc) error {
values.WalkMap(&err, c.syntheticForAnchor, c.newSyntheticForAnchor, nil, opts, fn)
values.WalkField(&err, c.directory, c.newDirectory, opts, fn)
values.WalkField(&err, c.events, c.newEvents, opts, fn)
values.WalkField(&err, c.blockLedger, c.newBlockLedger, opts, fn)
values.WalkMap(&err, c.transaction, c.newTransaction, c.getTransactionKeys, opts, fn)
values.WalkField(&err, c.mainChain, c.newMainChain, opts, fn)
values.WalkField(&err, c.scratchChain, c.newScratchChain, opts, fn)
Expand Down Expand Up @@ -762,6 +778,7 @@ func (c *Account) baseCommit() error {
}
values.Commit(&err, c.directory)
values.Commit(&err, c.events)
values.Commit(&err, c.blockLedger)
for _, v := range c.transaction {
values.Commit(&err, v)
}
Expand Down
12 changes: 12 additions & 0 deletions internal/database/types.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,15 @@ BlockStateSynthTxnEntry:
type: bytes
- name: ChainEntry
type: uvarint

BlockLedger:
fields:
- name: Index
type: uint
- name: Time
type: time
- name: Entries
type: protocol.BlockEntry
marshal-as: reference
pointer: true
repeatable: true
Loading

0 comments on commit 54de673

Please sign in to comment.