Skip to content

Commit 1566509

Browse files
Merge branch 'master' into resharding
2 parents 1f1d107 + d49bf8f commit 1566509

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ Changes to the protocol specification and standards are called NEAR Enhancement
2323
| [0181](https://github.com/near/NEPs/blob/master/neps/nep-0181.md) | Non Fungible Token Enumeration | @chadoh @thor314 | Final |
2424
| [0199](https://github.com/near/NEPs/blob/master/neps/nep-0199.md) | Non Fungible Token Royalties and Payouts | @thor314 @mattlockyer | Final |
2525
| [0245](https://github.com/near/NEPs/blob/master/neps/nep-0245.md) | Multi Token Standard | @zcstarr @riqi @jriemann @marcos.sun | Review |
26+
| [0264](https://github.com/near/NEPs/blob/master/neps/nep-0264.md) | Promise Gas Weights | @austinabell | Final |
2627
| [0297](https://github.com/near/NEPs/blob/master/neps/nep-0297.md) | Events Standard | @telezhnaya | Final |
2728
| [0330](https://github.com/near/NEPs/blob/master/neps/nep-0330.md) | Source Metadata | @BenKurrek | Review |
2829
| [0366](https://github.com/near/NEPs/blob/master/neps/nep-0366.md) | Meta Transactions | @ilblackdragon @e-uleyskiy @fadeevab | Draft |

specs/Proposals/0264-promise_gas_ratio.md renamed to neps/nep-0264.md

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,35 @@
1-
- Proposal Name: `promise_gas_weight`
2-
- Start Date: 2021-09-30
3-
- NEP PR: [nearprotocol/neps#264](https://github.com/nearprotocol/neps/pull/264)
4-
- Issue(s): https://github.com/near/near-sdk-rs/issues/526
1+
---
2+
NEP: 264
3+
Title: Utilization of unspent gas for promise function calls
4+
Authors: Austin Abell <[email protected]>
5+
DiscussionsTo: https://github.com/near/NEPs/pull/264
6+
Status: Approved
7+
Type: Protocol
8+
Version: 1.0.0
9+
Created: 2021-09-30
10+
LastUpdated: 2022-05-26
11+
---
512

613
# Summary
7-
[summary]: #summary
814

915
This proposal is to introduce a new host function on the NEAR runtime that allows for scheduling cross-contract function calls using a percentage/weight of the remaining gas in addition to the statically defined amount. This will enable async promise execution to use the remaining gas more efficiently by utilizing unspent gas from the current transaction.
1016

1117
# Motivation
12-
[motivation]: #motivation
1318

1419
We are proposing this to be able to utilize gas more efficiently but also to improve the devX of cross-contract calls. Currently, developers must guess how much gas will remain after the current transaction finishes and if this value is too little, the transaction will fail, and if it is too large, gas will be wasted. Therefore, these cross-contract calls need a reasonable default of splitting unused gas efficiently for basic cases without sacrificing the ability to configure the gas amount attached at a granular level. Currently, gas is allocated very inefficiently, requiring more prepaid gas or failed transactions when the allocations are imprecise.
1520

1621
# Guide-level explanation
17-
[guide-level-explanation]: #guide-level-explanation
1822

1923
This host function is similar to [`promise_batch_action_function_call`](https://github.com/near/nearcore/blob/7d15bbc996282c8ae8f15b8f49d110fc901b84d8/runtime/near-vm-logic/src/logic.rs#L1526), except with an additional parameter that lets you specify how much of the excess gas should be attached to the function call. This parameter is a weight value that determines how much of the excess gas is attached to each function.
2024

2125
So, for example, if there is 40 gas leftover and three function calls that select weights of 1, 5, and 2, the runtime will add 5, 25, and 10 gas to each function call. A developer can specify whether they want to attach a fixed amount of gas, a weight of remaining gas, or both. If at least one function call uses a weight of remaining gas, then all excess gas will be attached to future calls. This proposal allows developers the ability to utilize prepaid gas more efficiently than currently possible.
2226

2327
# Reference-level explanation
24-
[reference-level-explanation]: #reference-level-explanation
2528

2629
This host function would need to be implemented in `nearcore` and parallel [`promise_batch_action_function_call`](https://github.com/near/nearcore/blob/7d15bbc996282c8ae8f15b8f49d110fc901b84d8/runtime/near-vm-logic/src/logic.rs#L1526). Most details of these functions will be consistent, except that there will be additional bookkeeping for keeping track of which functions specified a weight for unused gas. This will not affect or replace any existing host functions, but this will likely require a slightly higher gas cost than the original `promise_batch_action_function_call` host function due to this additional overhead.
2730

2831
This host function definition would look like this (as a Rust consumer):
32+
2933
```rust
3034
/// Appends `FunctionCall` action to the batch of actions for the given promise pointed by
3135
/// `promise_idx`. This function allows not specifying a specific gas value and allowing the
@@ -70,7 +74,8 @@ The only difference from the existing API is `gas_weight` added as another param
7074
As for calculations, the remaining gas at the end of the transaction can be floor divided by the sum of all the weights tracked. Then, after getting this value, just attach that value multiplied by the weight gas to each function call action.
7175

7276
For example, if there are three weights, `a`, `b`, `c`:
73-
```
77+
78+
```rust
7479
weight_sum = a + b + c
7580
a_gas += remaining_gas * a / weight_sum
7681
b_gas += remaining_gas * b / weight_sum
@@ -84,6 +89,7 @@ Any remaining gas that is not allocated to any of these function calls will be a
8489
This protocol change will allow cross-contract calls to provide a fixed amount of gas and/or adjust the weight of unused gas to use. If neither is provided, it will default to using a weight of 1 for each and no static amount of gas. If no function modifies this weight, the runtime will split the unused gas evenly among all function calls.
8590

8691
Currently, the API for a cross-contract call looks like:
92+
8793
```rust
8894
let contract_account_id: AccountId = todo!();
8995
ext::some_method(/* parameters */, contract_account_id, 0 /* deposit amount */, 5_000_000_000_000 /* static amount of gas to attach */)
@@ -105,7 +111,6 @@ cross_contract::ext(contract_account_id)
105111
At a basic level, a developer has only to include the parameters for the function call and specify the account id of the contract being called. Currently, only the amount can be optional because there is no way to set a reasonable default for the amount of gas to use for each function call.
106112

107113
# Drawbacks
108-
[drawbacks]: #drawbacks
109114

110115
- Complexity in refactoring to handle assigning remaining gas at the end of a transaction
111116
- Complexity in extra calculations for assigning gas will make the host function slightly more expensive than the base one. It is not easy to create an API on the SDK level that can decide which host function to call if dynamic gas assigning is needed or not. If both are used, the size of the wasm binary is trivially larger by including both host functions
@@ -116,18 +121,19 @@ At a basic level, a developer has only to include the parameters for the functio
116121
- Keep in mind that it will also be positive because transactions will generally succeed more often due to gas more efficiently
117122

118123
# Rationale and alternatives
119-
[rationale-and-alternatives]: #rationale-and-alternatives
120124

121125
Alternative 1 (fraction parameters):
122126
The primary alternative is using a numerator and denominator to represent a fraction instead of a weight. This alternative would be equivalent to the one listed above except for two u64 additional parameters instead of just the one for weight. I'll list the tradeoff as pros and cons:
123127

124128
Pros:
129+
125130
- Can under-utilize the gas for the current transaction to limit gas allowed for certain functions
126131
- This could take responsibility away from DApp users because they would not have to worry less about attaching too much prepaid gas
127132
- Thinking in terms of fractions may be more intuitive for some developers
128133
- Might future proof better if we ever need this ability in the future, want to minimize the number of host functions created at all costs
129134

130135
Cons:
136+
131137
- More complicated logic/edge cases to handle to make sure the percentages don't sum to greater than 100% (or adjusting if they do)
132138
- Precision loss from dividing integers may lead to unexpected results
133139
- To get closer to expected, we could use floats for the division, but this gets messy
@@ -139,30 +145,32 @@ Alternative 2 (handle within contract/SDK):
139145
The other alternative is to handle all of this logic on the contract side, as seen by [this PR](https://github.com/near/near-sdk-rs/pull/523). This is much less feasible/accurate because there is only so much information available within the runtime, and gas costs and internal functionality may not always be the same. As discussed on [the respective issue](https://github.com/near/near-sdk-rs/issues/526), this alternative seems to be very infeasible.
140146

141147
Pros:
148+
142149
- No protocol change is needed
143150
- Can still have improved API as with protocol change
144151

145152
Cons:
153+
146154
- Additional bloat to every contract, even ones that don't use the pattern (~5kb in PoC, even with simple estimation logic)
147155
- Still inaccurate gas estimations, because at the point of calculation, we cannot know how much gas will be used for assigning gas values as well as gas consumed after the transaction ends
148156
- This leads to either underutilizing or having transactions fail when using too much gas if trying to estimate how much gas will be left
149157
- Prone to breaking existing contracts on protocol changes that affect gas usage or logic of runtime
150158

151159
# Unresolved questions
152-
[unresolved-questions]: #unresolved-questions
153160

154161
What needs to be addressed before this gets merged:
155162
~~- How much refactoring exactly is needed to handle this pattern?~~
156163
~~- Can we keep a queue of receipt and action indices with their respective weights and update their gas values after the current method is executed? Is there a cleaner way to handle this while keeping order?~~
157164
~~- Do we want to attach the gas lost due to precision on division to any function?~~
158-
- The remaining gas is now attached to the last function call
165+
166+
- The remaining gas is now attached to the last function call
159167

160168
What would be addressed in future independently of the solution:
169+
161170
- How many users would expect the ability to refund part of the gas after the initial transaction? (is this worth considering the API difference of using fractions rather than weights)
162171
- Will weights be an intuitive experience for developers?
163172

164173
# Future possibilities
165-
[future-possibilities]: #future-possibilities
166174

167175
The future change that would extend from this being implemented is a much cleaner API for the SDKs. As mentioned previously in the alternatives section, the API changes from [the changes tested on the SDK](https://github.com/near/near-sdk-rs/pull/523) will remain, but without the overhead from implementing this on the contract level. Thus, not only can this be implemented in Rust, but it will also allow a consistent API for existing and future SDK languages to build on.
168176

neps/nep-0393.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,15 @@ trait SBTRegistry {
404404
/// Must also emit `Burn` event if the SBT tokens are burned (removed).
405405
fn sbt_revoke(&mut self, tokens: Vec<TokenId>, burn: bool);
406406

407-
/// Similar to `sbt_revoke`, but revokes all `owner`s tokens issued by the caller.
408-
fn sbt_revoke_by_owner(&mut self, owner: AccountId, burn: bool);
407+
/// Similar to `sbt_revoke`. Allows SBT issuer to revoke all tokens by holder either by
408+
/// burning or updating their expire time. When an owner has many tokens from the issuer,
409+
/// the issuer may need to call this function multiple times, until all tokens are revoked.
410+
/// Retuns true if all the tokens were revoked, false otherwise.
411+
/// If false is returned issuer must call the method until true is returned
412+
/// Must be called by an SBT contract.
413+
/// Must emit `Revoke` event.
414+
/// Must also emit `Burn` event if the SBT tokens are burned (removed).
415+
fn sbt_revoke_by_owner(&mut self, owner: AccountId, burn: bool) -> bool;
409416

410417
/// Allows issuer to update token metadata reference and reference_hash.
411418
/// * `updates` is a list of triples: (token ID, reference, reference base64-encoded sha256 hash).

0 commit comments

Comments
 (0)