Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ResourcePopulator #2

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 227 additions & 0 deletions ledger/simulation/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,230 @@
}
return p.tracker.addBox(app, name, readSize, *p.initialBoxSurplusReadBudget, p.ep.Proto.BytesPerBoxReference)
}

type TxnResources struct {

Check failure on line 609 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-errors

[Lint Errors] reported by reviewdog 🐶 exported: exported type TxnResources should have comment or be unexported (revive) Raw Output: ledger/simulation/resources.go:609:6: exported: exported type TxnResources should have comment or be unexported (revive) type TxnResources struct { ^
// The static fields are resource arrays that were given in the transaciton group and thus cannot be removed

Check failure on line 610 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-errors

[Lint Errors] reported by reviewdog 🐶 `transaciton` is a misspelling of `transactions` (misspell) Raw Output: ledger/simulation/resources.go:610:66: `transaciton` is a misspelling of `transactions` (misspell) // The static fields are resource arrays that were given in the transaciton group and thus cannot be removed ^
// The assumption is that these are prefilled because of one of the following reaons:
// - This transaction has already been signed
// - One of the foreign arrays is accessed on-chain
StaticAssets map[basics.AssetIndex]struct{}
StaticApps map[basics.AppIndex]struct{}
StaticAccounts map[basics.Address]struct{}
StaticBoxes map[logic.BoxRef]struct{}

// The following fields are fields that are implicitly available to the transaction group from transaction fields
AssetFromField basics.AssetIndex
AppFromField basics.AppIndex
AccountsFromFields map[basics.Address]struct{}

// These are the fields currently being populated, thus we can mutate them however we'd like
Assets map[basics.AssetIndex]struct{}
Apps map[basics.AppIndex]struct{}
Boxes map[logic.BoxRef]struct{}
Accounts map[basics.Address]struct{}

MaxTotalRefs int
MaxAccounts int
}

func (r *TxnResources) getTotalRefs() int {

Check failure on line 634 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).getTotalRefs` is unused (unused) Raw Output: ledger/simulation/resources.go:634:24: func `(*TxnResources).getTotalRefs` is unused (unused) func (r *TxnResources) getTotalRefs() int { ^
return len(r.Accounts) + len(r.Assets) + len(r.Apps) + len(r.Boxes) + len(r.StaticAccounts) + len(r.StaticAssets) + len(r.StaticApps) + len(r.StaticBoxes)
}

// Methods for determining room for specific references

func (r *TxnResources) hasRoom() bool {

Check failure on line 640 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).hasRoom` is unused (unused) Raw Output: ledger/simulation/resources.go:640:24: func `(*TxnResources).hasRoom` is unused (unused) func (r *TxnResources) hasRoom() bool { ^
return r.getTotalRefs() < r.MaxTotalRefs
}

func (r *TxnResources) hasRoomForAccount() bool {

Check failure on line 644 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).hasRoomForAccount` is unused (unused) Raw Output: ledger/simulation/resources.go:644:24: func `(*TxnResources).hasRoomForAccount` is unused (unused) func (r *TxnResources) hasRoomForAccount() bool { ^
return r.hasRoom() && (len(r.Accounts)+len(r.StaticAccounts)) < r.MaxAccounts
}

func (r *TxnResources) hasRoomForCrossRef() bool {

Check failure on line 648 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).hasRoomForCrossRef` is unused (unused) Raw Output: ledger/simulation/resources.go:648:24: func `(*TxnResources).hasRoomForCrossRef` is unused (unused) func (r *TxnResources) hasRoomForCrossRef() bool { ^
return r.hasRoomForAccount() && r.getTotalRefs() < r.MaxTotalRefs-1
}

func (r *TxnResources) hasRoomForBoxWithApp() bool {

Check failure on line 652 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).hasRoomForBoxWithApp` is unused (unused) Raw Output: ledger/simulation/resources.go:652:24: func `(*TxnResources).hasRoomForBoxWithApp` is unused (unused) func (r *TxnResources) hasRoomForBoxWithApp() bool { ^
return r.getTotalRefs() < r.MaxTotalRefs-1
}

// Methods for determining if a resource is available

func (r *TxnResources) hasApp(app basics.AppIndex) bool {

Check failure on line 658 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).hasApp` is unused (unused) Raw Output: ledger/simulation/resources.go:658:24: func `(*TxnResources).hasApp` is unused (unused) func (r *TxnResources) hasApp(app basics.AppIndex) bool { ^
_, hasStatic := r.StaticApps[app]
_, hasRef := r.Apps[app]
return r.AppFromField == app || hasStatic || hasRef
}

func (r *TxnResources) hasAsset(aid basics.AssetIndex) bool {

Check failure on line 664 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).hasAsset` is unused (unused) Raw Output: ledger/simulation/resources.go:664:24: func `(*TxnResources).hasAsset` is unused (unused) func (r *TxnResources) hasAsset(aid basics.AssetIndex) bool { ^
_, hasStatic := r.StaticAssets[aid]
_, hasRef := r.Assets[aid]
return r.AssetFromField == aid || hasStatic || hasRef
}

func (r *TxnResources) hasAccount(addr basics.Address) bool {

Check failure on line 670 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).hasAccount` is unused (unused) Raw Output: ledger/simulation/resources.go:670:24: func `(*TxnResources).hasAccount` is unused (unused) func (r *TxnResources) hasAccount(addr basics.Address) bool { ^
_, hasStatic := r.StaticAccounts[addr]
_, hasRef := r.Accounts[addr]
_, hasField := r.AccountsFromFields[addr]

return hasField || hasStatic || hasRef
}

func (r *TxnResources) addAccount(addr basics.Address) {
r.Accounts[addr] = struct{}{}
}

func (r *TxnResources) addAsset(aid basics.AssetIndex) {
r.Assets[aid] = struct{}{}
}

func (r *TxnResources) addApp(aid basics.AppIndex) {
r.Apps[aid] = struct{}{}
}

func (r *TxnResources) addBox(app basics.AppIndex, name string) {

Check failure on line 690 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-warnings

[Lint Warnings] reported by reviewdog 🐶 func `(*TxnResources).addBox` is unused (unused) Raw Output: ledger/simulation/resources.go:690:24: func `(*TxnResources).addBox` is unused (unused) func (r *TxnResources) addBox(app basics.AppIndex, name string) { ^
r.Boxes[logic.BoxRef{App: app, Name: name}] = struct{}{}
}

type PopulatedArrays struct {

Check failure on line 694 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-errors

[Lint Errors] reported by reviewdog 🐶 exported: exported type PopulatedArrays should have comment or be unexported (revive) Raw Output: ledger/simulation/resources.go:694:6: exported: exported type PopulatedArrays should have comment or be unexported (revive) type PopulatedArrays struct { ^
Accounts []basics.Address
Assets []basics.AssetIndex
Apps []basics.AppIndex
Boxes []logic.BoxRef
}

func (r *TxnResources) getPopulatedArrays() PopulatedArrays {
accounts := make([]basics.Address, 0, len(r.Accounts)+len(r.StaticAccounts))
for account := range r.Accounts {
accounts = append(accounts, account)
}

assets := make([]basics.AssetIndex, 0, len(r.Assets)+len(r.StaticAssets))
for asset := range r.Assets {
assets = append(assets, asset)
}

apps := make([]basics.AppIndex, 0, len(r.Apps)+len(r.StaticApps))
for app := range r.Apps {
apps = append(apps, app)
}

boxes := make([]logic.BoxRef, 0, len(r.Boxes)+len(r.StaticBoxes))
for box := range r.Boxes {
boxes = append(boxes, box)
}

return PopulatedArrays{
Accounts: accounts,
Assets: assets,
Apps: apps,
Boxes: boxes,
}
}

type ResourcePopulator struct {

Check failure on line 730 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-errors

[Lint Errors] reported by reviewdog 🐶 exported: exported type ResourcePopulator should have comment or be unexported (revive) Raw Output: ledger/simulation/resources.go:730:6: exported: exported type ResourcePopulator should have comment or be unexported (revive) type ResourcePopulator struct { ^
TxnResources []TxnResources
}

func (p *ResourcePopulator) addTransaction(txn transactions.Transaction, groupIndex int) {
p.TxnResources[groupIndex] = TxnResources{
StaticAssets: make(map[basics.AssetIndex]struct{}),
StaticApps: make(map[basics.AppIndex]struct{}),
StaticAccounts: make(map[basics.Address]struct{}),
StaticBoxes: make(map[logic.BoxRef]struct{}),
AccountsFromFields: make(map[basics.Address]struct{}),
Assets: make(map[basics.AssetIndex]struct{}),
Apps: make(map[basics.AppIndex]struct{}),
Accounts: make(map[basics.Address]struct{}),
Boxes: make(map[logic.BoxRef]struct{}),
// TODO: Get these values from the consensus params
MaxTotalRefs: 8,
MaxAccounts: 4,
}

// The Sender and RekeyTo will always be implicitly available for every transaction type
p.TxnResources[groupIndex].AccountsFromFields[txn.Sender] = struct{}{}
p.TxnResources[groupIndex].StaticAccounts[txn.RekeyTo] = struct{}{}

if txn.Type == protocol.ApplicationCallTx {
for _, asset := range txn.ForeignAssets {
p.TxnResources[groupIndex].StaticAssets[asset] = struct{}{}
}

for _, app := range txn.ForeignApps {
p.TxnResources[groupIndex].StaticApps[app] = struct{}{}
}

for _, account := range txn.Accounts {
p.TxnResources[groupIndex].StaticAccounts[account] = struct{}{}
}

for _, box := range txn.Boxes {
ref := logic.BoxRef{App: txn.ForeignApps[box.Index], Name: string(box.Name)}
p.TxnResources[groupIndex].StaticBoxes[ref] = struct{}{}
}

p.TxnResources[groupIndex].AppFromField = txn.ApplicationID

return
}

if txn.Type == protocol.AssetTransferTx {
p.TxnResources[groupIndex].AssetFromField = txn.XferAsset

p.TxnResources[groupIndex].AccountsFromFields[txn.AssetReceiver] = struct{}{}
p.TxnResources[groupIndex].AccountsFromFields[txn.AssetCloseTo] = struct{}{}
p.TxnResources[groupIndex].AccountsFromFields[txn.AssetSender] = struct{}{}

return
}

if txn.Type == protocol.PaymentTx {
p.TxnResources[groupIndex].AccountsFromFields[txn.Receiver] = struct{}{}
p.TxnResources[groupIndex].AccountsFromFields[txn.CloseRemainderTo] = struct{}{}

return
}

if txn.Type == protocol.AssetConfigTx {
p.TxnResources[groupIndex].AssetFromField = txn.ConfigAsset

return
}

if txn.Type == protocol.AssetFreezeTx {
p.TxnResources[groupIndex].AssetFromField = txn.FreezeAsset
p.TxnResources[groupIndex].AccountsFromFields[txn.FreezeAccount] = struct{}{}

return
}
}

func (p *ResourcePopulator) populateResources(groupResourceTracker groupResourceTracker) {
for i, tracker := range groupResourceTracker.localTxnResources {
for asset := range tracker.Assets {
p.TxnResources[i].addAsset(asset)
}

for app := range tracker.Apps {
p.TxnResources[i].addApp(app)
}

for account := range tracker.Accounts {
p.TxnResources[i].addAccount(account)
}
}
}

func MakeResourcePopulator(txnGroup []transactions.SignedTxnWithAD) ResourcePopulator {

Check failure on line 824 in ledger/simulation/resources.go

View workflow job for this annotation

GitHub Actions / reviewdog-errors

[Lint Errors] reported by reviewdog 🐶 exported: exported function MakeResourcePopulator should have comment or be unexported (revive) Raw Output: ledger/simulation/resources.go:824:1: exported: exported function MakeResourcePopulator should have comment or be unexported (revive) func MakeResourcePopulator(txnGroup []transactions.SignedTxnWithAD) ResourcePopulator { ^
populator := ResourcePopulator{
TxnResources: make([]TxnResources, len(txnGroup)),
}

for i, txn := range txnGroup {
populator.addTransaction(txn.Txn, i)
}

return populator
}
39 changes: 39 additions & 0 deletions ledger/simulation/resources_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,42 @@ func TestGlobalVsLocalResources(t *testing.T) {
}, groupAssignment.localTxnResources[2].Apps)
})
}

func TestPopulatorWithLocalResources(t *testing.T) {
partitiontest.PartitionTest(t)
t.Parallel()

txns := make([]transactions.SignedTxnWithAD, 1)
txns[0].Txn.Type = protocol.ApplicationCallTx

populator := MakeResourcePopulator(txns)

proto := config.Consensus[protocol.ConsensusFuture]
groupTracker := makeGroupResourceTracker(txns, &proto)

// Note we don't need to test a box here since it will never be a local txn resource
addr := basics.Address{1, 1, 1}
app := basics.AppIndex(12345)
asset := basics.AssetIndex(12345)

groupTracker.localTxnResources[0].Accounts = make(map[basics.Address]struct{})
groupTracker.localTxnResources[0].Assets = make(map[basics.AssetIndex]struct{})
groupTracker.localTxnResources[0].Apps = make(map[basics.AppIndex]struct{})

groupTracker.localTxnResources[0].Accounts[addr] = struct{}{}
groupTracker.localTxnResources[0].Assets[asset] = struct{}{}
groupTracker.localTxnResources[0].Apps[app] = struct{}{}

populator.populateResources(groupTracker)

require.Equal(
t,
PopulatedArrays{
Assets: []basics.AssetIndex{asset},
Apps: []basics.AppIndex{app},
Accounts: []basics.Address{addr},
Boxes: []logic.BoxRef{},
},
populator.TxnResources[0].getPopulatedArrays(),
)
}
Loading