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

Implement bonds for fortification #1853

Merged
merged 45 commits into from
Jan 29, 2025
Merged

Implement bonds for fortification #1853

merged 45 commits into from
Jan 29, 2025

Conversation

joshua-kim
Copy link
Contributor

@joshua-kim joshua-kim commented Jan 7, 2025

Implements bonds by maintaining state of an account's pending + max bond balance

@joshua-kim joshua-kim marked this pull request as ready for review January 7, 2025 18:48
chain/bond.go Outdated Show resolved Hide resolved
chain/bond.go Outdated Show resolved Hide resolved
chain/transaction.go Outdated Show resolved Hide resolved
chain/bond.go Outdated Show resolved Hide resolved
chain/bond.go Outdated Show resolved Hide resolved
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
x/fdsmr/node.go Outdated
@@ -42,10 +44,10 @@ type Node[T DSMR[U], U dsmr.Tx] struct {
pending *eheap.ExpiryHeap[U]
}

func (n *Node[T, U]) BuildChunk(ctx context.Context, txs []U, expiry int64, beneficiary codec.Address) error {
func (n *Node[T, U]) BuildChunk(ctx context.Context, mutable state.Mutable, txs []U, expiry int64, beneficiary codec.Address, fee *big.Int) error {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we make it clear when mutable is a local view of the chunk builder vs. operating on the network wide chain state (merkle trie)?

It's not completely clear to me from this in BuildChunk and Accept what state we're operating on.

We need to set the max balance in the chain state, so that each chunk builder has an agreed on view of what the max balance is for each potential tx issuer at the start of an epoch. Each chunk builder must maintain up to date pending balances, so that it can correctly limit transactions if they exceed their cap and needs to maintain a separate state/database for this (cannot write to the network wide state from its own local view).

Should we maintain a database in fdsmr so that we can keep the pending balances up to date rather than leaving this to the caller to supply?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we maintain a database in fdsmr so that we can keep the pending balances up to date rather than leaving this to the caller to supply?

Why would the database live in fdsmr? Is this because you want to commit all of the unbond balance updates in a single batch? If so I think this is simpler to implement by just making Unbond idempotent

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems simpler that fdsmr maintaining responsibility for its own state is simpler than pushing it to the caller.

We just need to maintain that fdsmr can restart correctly and know the outstanding balances of any chunks that it has produced in a given epoch and is therefore responsible for.

Another alternative would be that on restart, we iterate over any pending chunks that we've created (which should include all chunks that could still be included in a block both produced by us and otherwise) and refresh our pending balances from this.

Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Signed-off-by: Joshua Kim <[email protected]>
Copy link
Collaborator

@aaronbuchwald aaronbuchwald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Summarizing my understanding of how we'll break down the state here:

  • max balance will be included in the chain state (state replicated across the network)
  • chunk builders locally maintain a database of pending transactions to ensure they never allow an account to spend more than their max balance

When we pass state.Mutable into fdsmr here, I think that we will need to ensure that the max balance cannot decrease within an epoch.

We want to ensure that chunk builders can guarantee they never replicate more data for an account than what the account can pay for (ie. the account bond). If an account bond can be decreased within an epoch, then the chunk builder can end up in a situation where they have outstanding replicated transactions that cost 100 units and the account bond can be decreased below that threshold, which can generate non-fee paying transactions.

return db
}

type NoAuthFactory struct{}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(optional for this PR / followup) Since we have an auth mock in the chain package, could we move this under auth/authtest/ so that we can re-use instead of creating it in each place we need?


return tx
}(),
feeRate: 0,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(no action necessary) feeRate = 0 should probably be invalid

}

txID := tx.GetID()
if err := batch.Put(txID[:], binary.BigEndian.AppendUint64(nil, fee)); err != nil {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure that writing txs by hash will be performant enough here, but think this is fine for now.

@joshua-kim joshua-kim merged commit 4915e26 into main Jan 29, 2025
17 checks passed
@joshua-kim joshua-kim deleted the bond-impl branch January 29, 2025 21:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants