Skip to content

Commit

Permalink
all: Update for core changes
Browse files Browse the repository at this point in the history
  • Loading branch information
lukechampine committed Jun 26, 2024
1 parent 3285d53 commit 4d8406d
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 61 deletions.
45 changes: 29 additions & 16 deletions chain/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ func (db *DBStore) treeKey(row, col uint64) []byte {
}

func (db *DBStore) getElementProof(leafIndex, numLeaves uint64) (proof []types.Hash256) {
if leafIndex >= numLeaves {
panic(fmt.Sprintf("leafIndex %v exceeds accumulator size %v", leafIndex, numLeaves)) // should never happen
}
// The size of the proof is the mergeHeight of leafIndex and numLeaves. To
// see why, imagine a tree large enough to contain both leafIndex and
// numLeaves within the same subtree; the height at which the paths to those
Expand All @@ -348,7 +351,9 @@ func (db *DBStore) getElementProof(leafIndex, numLeaves uint64) (proof []types.H

func (db *DBStore) getSiacoinElement(id types.SiacoinOutputID, numLeaves uint64) (sce types.SiacoinElement, ok bool) {
ok = db.bucket(bSiacoinElements).get(id[:], &sce)
sce.MerkleProof = db.getElementProof(sce.LeafIndex, numLeaves)
if ok {
sce.MerkleProof = db.getElementProof(sce.LeafIndex, numLeaves)
}
return
}

Expand All @@ -363,7 +368,9 @@ func (db *DBStore) deleteSiacoinElement(id types.SiacoinOutputID) {

func (db *DBStore) getSiafundElement(id types.SiafundOutputID, numLeaves uint64) (sfe types.SiafundElement, ok bool) {
ok = db.bucket(bSiafundElements).get(id[:], &sfe)
sfe.MerkleProof = db.getElementProof(sfe.LeafIndex, numLeaves)
if ok {
sfe.MerkleProof = db.getElementProof(sfe.LeafIndex, numLeaves)
}
return
}

Expand All @@ -378,7 +385,9 @@ func (db *DBStore) deleteSiafundElement(id types.SiafundOutputID) {

func (db *DBStore) getFileContractElement(id types.FileContractID, numLeaves uint64) (fce types.FileContractElement, ok bool) {
ok = db.bucket(bFileContractElements).get(id[:], &fce)
fce.MerkleProof = db.getElementProof(fce.LeafIndex, numLeaves)
if ok {
fce.MerkleProof = db.getElementProof(fce.LeafIndex, numLeaves)
}
return
}

Expand Down Expand Up @@ -428,26 +437,28 @@ func (db *DBStore) applyElements(cau consensus.ApplyUpdate) {
db.bucket(bTree).put(db.treeKey(row, col), h)
})

cau.ForEachSiacoinElement(func(sce types.SiacoinElement, spent bool) {
if sce.LeafIndex == types.EphemeralLeafIndex {
return
cau.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) {
if created && spent {
return // ephemeral
} else if spent {
db.deleteSiacoinElement(types.SiacoinOutputID(sce.ID))
} else {
db.putSiacoinElement(sce)
}
})
cau.ForEachSiafundElement(func(sfe types.SiafundElement, spent bool) {
if sfe.LeafIndex == types.EphemeralLeafIndex {
cau.ForEachSiafundElement(func(sfe types.SiafundElement, created, spent bool) {
if created && spent {
return
} else if spent {
db.deleteSiafundElement(types.SiafundOutputID(sfe.ID))
} else {
db.putSiafundElement(sfe)
}
})
cau.ForEachFileContractElement(func(fce types.FileContractElement, rev *types.FileContractElement, resolved, valid bool) {
if resolved {
cau.ForEachFileContractElement(func(fce types.FileContractElement, created bool, rev *types.FileContractElement, resolved, valid bool) {
if created && resolved {
return
} else if resolved {
db.deleteFileContractElement(types.FileContractID(fce.ID))
db.deleteFileContractExpiration(types.FileContractID(fce.ID), fce.FileContract.WindowEnd)
} else if rev != nil {
Expand All @@ -464,8 +475,10 @@ func (db *DBStore) applyElements(cau consensus.ApplyUpdate) {
}

func (db *DBStore) revertElements(cru consensus.RevertUpdate) {
cru.ForEachFileContractElement(func(fce types.FileContractElement, rev *types.FileContractElement, resolved, valid bool) {
if resolved {
cru.ForEachFileContractElement(func(fce types.FileContractElement, created bool, rev *types.FileContractElement, resolved, valid bool) {
if created && resolved {
return
} else if resolved {
// contract no longer resolved; restore it
db.putFileContractElement(fce)
db.putFileContractExpiration(types.FileContractID(fce.ID), fce.FileContract.WindowEnd)
Expand All @@ -482,8 +495,8 @@ func (db *DBStore) revertElements(cru consensus.RevertUpdate) {
db.deleteFileContractExpiration(types.FileContractID(fce.ID), fce.FileContract.WindowEnd)
}
})
cru.ForEachSiafundElement(func(sfe types.SiafundElement, spent bool) {
if sfe.LeafIndex == types.EphemeralLeafIndex {
cru.ForEachSiafundElement(func(sfe types.SiafundElement, created, spent bool) {
if created && spent {
return
} else if spent {
// output no longer spent; restore it
Expand All @@ -493,8 +506,8 @@ func (db *DBStore) revertElements(cru consensus.RevertUpdate) {
db.deleteSiafundElement(types.SiafundOutputID(sfe.ID))
}
})
cru.ForEachSiacoinElement(func(sce types.SiacoinElement, spent bool) {
if sce.LeafIndex == types.EphemeralLeafIndex {
cru.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) {
if created && spent {
return
} else if spent {
// output no longer spent; restore it
Expand Down
32 changes: 16 additions & 16 deletions chain/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -645,23 +645,23 @@ func (m *Manager) revertPoolUpdate(cru consensus.RevertUpdate, cs consensus.Stat
return
} else if uncreated == nil {
uncreated = make(map[types.Hash256]bool)
cru.ForEachSiacoinElement(func(sce types.SiacoinElement, spent bool) {
if !spent {
cru.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) {
if created {
uncreated[sce.ID] = true
}
})
cru.ForEachSiafundElement(func(sfe types.SiafundElement, spent bool) {
if !spent {
cru.ForEachSiafundElement(func(sfe types.SiafundElement, created, spent bool) {
if created {
uncreated[sfe.ID] = true
}
})
cru.ForEachFileContractElement(func(fce types.FileContractElement, rev *types.FileContractElement, resolved, valid bool) {
if !resolved {
cru.ForEachFileContractElement(func(fce types.FileContractElement, created bool, rev *types.FileContractElement, resolved, valid bool) {
if created {
uncreated[fce.ID] = true
}
})
cru.ForEachV2FileContractElement(func(fce types.V2FileContractElement, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) {
if res != nil {
cru.ForEachV2FileContractElement(func(fce types.V2FileContractElement, created bool, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) {
if created {
uncreated[fce.ID] = true
}
})
Expand Down Expand Up @@ -702,23 +702,23 @@ func (m *Manager) applyPoolUpdate(cau consensus.ApplyUpdate, cs consensus.State)
return
} else if newElements == nil {
newElements = make(map[types.Hash256]types.StateElement)
cau.ForEachSiacoinElement(func(sce types.SiacoinElement, spent bool) {
if !spent {
cau.ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool) {
if created {
newElements[sce.ID] = sce.StateElement
}
})
cau.ForEachSiafundElement(func(sfe types.SiafundElement, spent bool) {
if !spent {
cau.ForEachSiafundElement(func(sfe types.SiafundElement, created, spent bool) {
if created {
newElements[sfe.ID] = sfe.StateElement
}
})
cau.ForEachFileContractElement(func(fce types.FileContractElement, rev *types.FileContractElement, resolved, valid bool) {
if !resolved {
cau.ForEachFileContractElement(func(fce types.FileContractElement, created bool, rev *types.FileContractElement, resolved, valid bool) {
if created {
newElements[fce.ID] = fce.StateElement
}
})
cau.ForEachV2FileContractElement(func(fce types.V2FileContractElement, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) {
if res != nil {
cau.ForEachV2FileContractElement(func(fce types.V2FileContractElement, created bool, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) {
if created {
newElements[fce.ID] = fce.StateElement
}
})
Expand Down
37 changes: 8 additions & 29 deletions wallet/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [
siacoinElements := make(map[types.SiacoinOutputID]types.SiacoinElement)

// cache the value of siacoin elements to use when calculating v1 outflow
cau.ForEachSiacoinElement(func(se types.SiacoinElement, spent bool) {
cau.ForEachSiacoinElement(func(se types.SiacoinElement, created, spent bool) {
siacoinElements[types.SiacoinOutputID(se.ID)] = se
})

Expand Down Expand Up @@ -187,7 +187,8 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [
addEvent(types.Hash256(txn.ID()), EventTypeV2Transaction, EventV2Transaction(txn))
}

cau.ForEachFileContractElement(func(fce types.FileContractElement, rev *types.FileContractElement, resolved bool, valid bool) {
// add the file contract outputs
cau.ForEachFileContractElement(func(fce types.FileContractElement, created bool, rev *types.FileContractElement, resolved bool, valid bool) {
if !resolved {
return
}
Expand Down Expand Up @@ -221,7 +222,7 @@ func appliedEvents(cau chain.ApplyUpdate, walletAddress types.Address) (events [
}
})

cau.ForEachV2FileContractElement(func(fce types.V2FileContractElement, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) {
cau.ForEachV2FileContractElement(func(fce types.V2FileContractElement, created bool, rev *types.V2FileContractElement, res types.V2FileContractResolutionType) {
if res == nil {
return
}
Expand Down Expand Up @@ -287,31 +288,10 @@ func applyChainState(tx UpdateTx, address types.Address, cau chain.ApplyUpdate)
return fmt.Errorf("failed to get state elements: %w", err)
}

// determine which siacoin and siafund elements are ephemeral
//
// note: I thought we could use LeafIndex == EphemeralLeafIndex, but
// it seems to be set before the subscriber is called.
created := make(map[types.Hash256]bool)
ephemeral := make(map[types.Hash256]bool)
for _, txn := range cau.Block.Transactions {
for i := range txn.SiacoinOutputs {
created[types.Hash256(txn.SiacoinOutputID(i))] = true
}
for _, input := range txn.SiacoinInputs {
ephemeral[types.Hash256(input.ParentID)] = created[types.Hash256(input.ParentID)]
}
for i := range txn.SiafundOutputs {
created[types.Hash256(txn.SiafundOutputID(i))] = true
}
for _, input := range txn.SiafundInputs {
ephemeral[types.Hash256(input.ParentID)] = created[types.Hash256(input.ParentID)]
}
}

var createdUTXOs, spentUTXOs []types.SiacoinElement
utxoValues := make(map[types.SiacoinOutputID]types.Currency)

cau.ForEachSiacoinElement(func(se types.SiacoinElement, spent bool) {
cau.ForEachSiacoinElement(func(se types.SiacoinElement, created, spent bool) {
if se.SiacoinOutput.Address != address {
return
}
Expand All @@ -320,7 +300,7 @@ func applyChainState(tx UpdateTx, address types.Address, cau chain.ApplyUpdate)
utxoValues[types.SiacoinOutputID(se.ID)] = se.SiacoinOutput.Value

// ignore ephemeral elements
if ephemeral[se.ID] {
if created && spent {
return
}

Expand All @@ -346,11 +326,10 @@ func applyChainState(tx UpdateTx, address types.Address, cau chain.ApplyUpdate)
// revertChainUpdate atomically reverts a chain update from a wallet
func revertChainUpdate(tx UpdateTx, revertedIndex types.ChainIndex, address types.Address, cru chain.RevertUpdate) error {
var removedUTXOs, unspentUTXOs []types.SiacoinElement
cru.ForEachSiacoinElement(func(se types.SiacoinElement, spent bool) {
if se.SiacoinOutput.Address != address {
cru.ForEachSiacoinElement(func(se types.SiacoinElement, created, spent bool) {
if se.SiacoinOutput.Address != address || (created && spent) {
return
}

if spent {
unspentUTXOs = append(unspentUTXOs, se)
} else {
Expand Down

0 comments on commit 4d8406d

Please sign in to comment.