-
Notifications
You must be signed in to change notification settings - Fork 46
Add multi-action send transaction method to bls signer #540
Add multi-action send transaction method to bls signer #540
Conversation
9bcab53
to
982b417
Compare
*/ | ||
export type TransactionBatch = { | ||
transactions: Array<Transaction>; | ||
batchOptions?: BatchOptions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really utilising this optional property. Tbh slightly confused by what it's purpose is from the draft standard. My interpretation is that these values help smart contract wallets deal with figuring out batch transaction options from multiple transactions, but not sure if that's correct
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using this spec we need to accept them, but some of them we will be unable to pass forward to the agg. gas
can be used with latest contract changes in contract-updates
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Added a helper function (_validateBatchOptions) that validates the batch options if they are passed as an argument. It checks the chain id is correct and ensures the nonce is the correct type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall, think this is a great start on batch txn handling for provider (nice tests btw). Also sets us up well to add additional batch specs. Let's sync offline on how to handle some of the batch options.
To start, I think we can assume that all actions (batched txns) are atomic. We can add more logic later to split actions across multiple operations later.
contracts/clients/src/BlsSigner.ts
Outdated
export type Transaction = { | ||
to?: string; | ||
value?: BigNumberish; | ||
gas?: BigNumberish; | ||
maxPriorityFeePerGas?: BigNumberish; | ||
maxFeePerGas?: BigNumberish; | ||
data?: BytesLike; | ||
nonce?: BigNumberish; | ||
chainId?: number; | ||
accessList?: Array<AccessListish>; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to import this from ethers.js
*/ | ||
export type TransactionBatch = { | ||
transactions: Array<Transaction>; | ||
batchOptions?: BatchOptions; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using this spec we need to accept them, but some of them we will be unable to pass forward to the agg. gas
can be used with latest contract changes in contract-updates
.
contracts/clients/src/BlsSigner.ts
Outdated
const actions: Array<ActionData> = transactionBatch.transactions.map( | ||
(transaction) => { | ||
if (!transaction.to) { | ||
throw new TypeError( | ||
"Transaction.to should be defined for all transactions", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const actions: Array<ActionData> = transactionBatch.transactions.map( | |
(transaction) => { | |
if (!transaction.to) { | |
throw new TypeError( | |
"Transaction.to should be defined for all transactions", | |
const actions: Array<ActionData> = transactionBatch.transactions.map( | |
(transaction, i) => { | |
if (!transaction.to) { | |
throw new TypeError( | |
`Transaction.to missing on txn {i}`, |
contracts/clients/src/BlsSigner.ts
Outdated
(transaction) => { | ||
if (!transaction.to) { | ||
throw new TypeError( | ||
"Transaction.to should be defined for all transactions", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
157790b
to
b257437
Compare
0f15fad
to
edd67d1
Compare
// Assert | ||
expect(result).to.deep.equal(batchOptions); | ||
expect(result.nonce).to.equal(BigNumber.from("39")); | ||
expect(result.nonce).to.have.property("add"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
expect(result.nonce).to.equal(BigNumber.from("39"));
can result in false positives, so these 2 extra assertions test "BigNumber.from" worked.
(e.g. before these extra assertions, the test will still pass if "BigNumber.from" is removed in the method which is incorrect behaviour)
@@ -161,6 +161,9 @@ describe("Provider tests", function () { | |||
.transfer(recipient, amountToTransfer); | |||
await tx.wait(); | |||
|
|||
// wait 1 second to ensure listener count updates | |||
await new Promise((resolve) => setTimeout(resolve, 1000)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When running the whole test suite locally, the expect(blsProvider.listenerCount(filter)).to.equal(0);
assertion would periodically fail as the event listener was still subscribed. Seems a bit hacky for testing a function that is supposed to be synchronous, but the timer appears to fix that issue.
edd67d1
to
ee17357
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 We we decide to promote this for general usage, we should make sure to document the batch function & spec so people are aware they can use that in addition to the normal provider/signer APIs
What is this PR doing?
Adds multi-action transactions to bls provider and bls signer.
New methods were added as to not break the ethers provider base-class function signatures:
multi-action standards
TLDR ended up going for the wallet_batchTransactions standard. It was the simplest option and we can easily build upon it as future requirements come up.
TLDR: Gut feeling is EIP 5792 is the option to go for. But after reading the discussion on eth magicians, it feels like there is some pushback which makes me think it won't get adopted in it's current state. e.g. disagreements about standardisation of bundle identifiers and disagreement about level of 'atomicity'.New types:
These were based on this draft batch transaction standard -
wallet_batchTransactions
JSON-RPC method. The idea was to ensure our code abides by a spec if one exists. There is no formal standard and it was a choice between thewallet_batchTransactions
draft and EIP 5792 (draft). While the draft EIP is further along in it's journey towards becoming a standard (by this, I mean it's an actual draft EIP with discussion, as opposed to an informal draft), it's had some pushback in it's eth magicians thread. I've gone for thewallet_batchTransactions
option for simplicity.I've also created a new response type, this isn't based on any of the above standards, but it was easy to implement.
Further notes and other changes
Preliminary decision with
signer.sendTransactionBatch
was to only add transactions to a single operation. This means that all transactions in the batch will be atomic. Another option may be to give the developer a choice on whether to add transactions to different operations, and thus permit non-atomic transaction flows. Non-atomic tx flows are out of scope for this work.provider.sendTransactionBatch operates on an already signed bundle, so could theoretically receive multiple operations. I've added some code to support this in case of that scenario:
How can these changes be manually tested?
Does this PR resolve or contribute to any issues?
Resolves #375
Checklist
Guidelines
resolve conversation
button is for reviewers, not authors