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

auto-claim gas if it's needed #2008

Closed
wants to merge 23 commits into from

Conversation

shargon
Copy link
Member

@shargon shargon commented Oct 15, 2020

Close #1078

@shargon shargon requested a review from erikzhang October 15, 2020 14:45
@shargon
Copy link
Member Author

shargon commented Oct 15, 2020

@neo-project/ngd-shanghai Could you help me testing it?

@Qiao-Jin
Copy link
Contributor

How about here:

balances_gas = accounts.Select(p => (Account: p, Value: NativeContract.GAS.BalanceOf(snapshot, p))).Where(p => p.Value.Sign > 0).ToList();

Besides, how about an overide func GAS.BalanceOf which takes NEO.UnclaimedGas into account?

@shargon
Copy link
Member Author

shargon commented Oct 16, 2020

Besides, how about an overide func GAS.BalanceOf which takes NEO.UnclaimedGas into account?

It's a good idea :), we can change it later if this work.

@erikzhang
Copy link
Member

If the gas is not enough, users can buy some on the exchange.

@shargon shargon marked this pull request as ready for review October 29, 2020 11:28
@shargon
Copy link
Member Author

shargon commented Oct 29, 2020

If the gas is not enough, users can buy some on the exchange.

Yes, but moving the logic from balanceChanging to OnPersist we can avoid the first use problem without buy Gas, only NEO.

return balance >= fee;
if (balance >= fee) return true;

BigInteger unclaimed = NativeContract.NEO.UnclaimedGas(snapshot, tx.Sender, snapshot.Height);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is in the hot path for transaction verification and after #1848 this call can be quite expensive (with a number of DB accesses).

Copy link
Contributor

@igormcoelho igormcoelho Oct 30, 2020

Choose a reason for hiding this comment

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

But I think this is necessary anyway @roman-khimov , because we must know if someone has enough funds for transfer, during Verification... it really costs to calculate, but we don't need precise value. Maybe, if we have some caching on unclaimedGas values, we could call some method EnoughUnclaimedGas(VALUE), so that if caching already has enough, we don't recalculate. Truth is, we just need to know if Unclaimed is bigger than VALUE, not its precise value.

Copy link
Member Author

Choose a reason for hiding this comment

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

If it has funds, there will be no problem, otherwise, we need to check it.

src/neo/SmartContract/Native/Tokens/NeoToken.cs Outdated Show resolved Hide resolved
@@ -27,6 +27,7 @@ protected override void OnPersist(ApplicationEngine engine)
long totalNetworkFee = 0;
foreach (Transaction tx in engine.Snapshot.PersistingBlock.Transactions)
{
NEO.DistributeGas(engine, tx.Sender);
Copy link
Member

Choose a reason for hiding this comment

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

@shargon, maybe it should only distributeGAS for the tx.Sender that needs it.
In this sense, perhaps we could have a flag before return balance + unclaimed >= fee;

Copy link
Member Author

Choose a reason for hiding this comment

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

Please, take a look again

@shargon
Copy link
Member Author

shargon commented Nov 14, 2020

@superboyiii could you test it please?

@vncoelho
Copy link
Member

vncoelho commented Jan 6, 2021

If the gas is not enough, users can buy some on the exchange.

It is a barrier that we can avoid, @erikzhang, at least for a basic transaction, if the user holds NEO for some couple of time.

@vncoelho vncoelho closed this Jan 6, 2021
@vncoelho vncoelho reopened this Jan 6, 2021
@shargon
Copy link
Member Author

shargon commented Jan 7, 2021

@erikzhang As @vncoelho said, it will help with adoption, impatient users always can buy GAS.

@superboyiii
Copy link
Member

superboyiii commented Jan 30, 2021

Done! it should work with neo-node master

I'm testing it on latest master. Not sure how to test it. I saw you changed CheckTransaction() to add unclaimed gas into calculation. But cli is not using this, I mean I supposed to use send command and it will calculate netfee within the claimed + unclaimed, if not enough claimed, then claim the unclaimed to be fee.
image

@shargon
Copy link
Member Author

shargon commented Jan 31, 2021

@superboyiii please check it again

Tommo-L
Tommo-L previously approved these changes Jan 31, 2021
@superboyiii
Copy link
Member

superboyiii commented Jan 31, 2021

balances_gas = accounts.Select(p => (Account: p, Value: NativeContract.GAS.BalanceOf(snapshot, p))).Where(p => p.Value.Sign > 0).ToList();

@shargon We're using this MakeTransaction(TransferOutput[] outputs, UInt160 from = null, Signer[] cosigners = null) for send command. Need using unclaimedGas as balance as well.
https://github.com/neo-project/neo-node/blob/a7f06cab3f5cb3099ba7e75ba3d1e18d6eda337d/neo-cli/CLI/MainService.Wallet.cs#L475

@superboyiii
Copy link
Member

I could make Tx successfully but seems it has been rejected by mempool verification.
image
image
You forget here:
image

@superboyiii
Copy link
Member

I think for neo-core it's OK now, but we need modify more on neo-node and neo-modules.
For example: https://github.com/neo-project/neo-node/blob/f0fc56690388167fa472b843a659d61fd135238e/neo-cli/CLI/MainService.cs#L480
Vote still will be failed.
I will not approve this beacuse we'll release Preview5 tommorrow. It could be merged in next version.

@erikzhang
Copy link
Member

I'm not sure if we really need it. Originally, if there was no GAS in my account, I know the transaction would fail. Now even if I transfer all the GAS away, it may still be claimed automatically.

@superboyiii
Copy link
Member

I'm not sure if we really need it. Originally, if there was no GAS in my account, I know the transaction would fail. Now even if I transfer all the GAS away, it may still be claimed automatically.

unclaimed gas + claimed gas = your gas. I think it makes sense. No need to ask user know how much they need to claim because the claim mechanism is never important. If we can claim for user, we just do it. And CLI should show unclaimed gas + claimed gas as balance and use it as balance.

@shargon
Copy link
Member Author

shargon commented Feb 2, 2021

Now even if I transfer all the GAS away, it may still be claimed automatically.

But it is a benefit more than a problem. Otherwise, in many cases this gas was like burned.

@superboyiii
Copy link
Member

superboyiii commented Feb 2, 2021

It benefits a lot in initial NEO transaction. Exchange don't allow a little gas withdraw, that means you need buy a certain amount of GAS just for one transaction. It's not good for NEO flowability and it makes exchange difficult for initial NEO3 technicial integration.

@roman-khimov
Copy link
Contributor

roman-khimov commented Feb 2, 2021

On a real network we'll get 100 tx in a block and all of them will come from different addresses. So we'll distribute GAS for all of them and invoke onNEP17Payment for all of them (which can fail BTW). Then in the next block we'll get another 100 tx and something like half of them will come from the same addresses as in previous block, so we'll distribute GAS... Practically it means that for some active addresses GAS will be distributed with every block. My concern is that it can add some substantial overhead and a lot of not really useful (but still happening) invocations and state changes.

And accepting a transaction which can't really pay according to the state we have at the current height is still a little scary to me, even though it doesn't seem to create any issues if GAS is to be distributed before writing the commission off the balance.

foreach (Transaction tx in engine.PersistingBlock.Transactions)
{
if (distributed.Add(tx.Sender)) NEO.DistributeGas(engine, tx.Sender);
Copy link
Member

Choose a reason for hiding this comment

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

This is just to ensure that it is distributed only once per Persist, right?

Copy link
Member

Choose a reason for hiding this comment

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

Isn't there any need to avoid the

protected override void OnBalanceChanging(ApplicationEngine engine, UInt160 account, NeoAccountState state, BigInteger amount)
?

If the transfer also changes NEO's balance?

Copy link
Contributor

Choose a reason for hiding this comment

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

We're running this line in OnPersist context. It invokes GAS.Mint. It calls PostTransfer. Which calls onNEP17Payment. That fails. What are we gonna do then? Fail persisting a block? Not an option. Ignore this problem and fail GAS distribution? Fine, except some storage changes are already in-flight in this context and, most importantly, tx.Sender may just not have enough GAS for the Burn() one line below. So, what are the options we have?

Copy link
Member Author

@shargon shargon Feb 26, 2021

Choose a reason for hiding this comment

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

@roman-khimov it's the same problem here

GAS.Mint(engine, account, gasPerBlock * CommitteeRewardRatio / 100, false);

I think that we should not rise onNEP17Payment during OnPersist

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not. This invocation specifically has false for callOnPayment. And we only have simple standard accounts in the committee (their keys are known).

Copy link
Member Author

Choose a reason for hiding this comment

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

I'll put "false" here too

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think it's legal to do this! Unlike committee members transaction sender can be anything, including deployed contract. And deployed contract must be invoked on this mint.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, I we merge it, the generated gas will come to not call onNEP17Payment, before this PR it does....

@superboyiii
Copy link
Member

superboyiii commented Feb 25, 2021

@erikzhang @shargon @roman-khimov @vncoelho Let's move on? If we'd like to do this, we shall merge it ASAP and modify neo-node and neo-modules before RC1.

@superboyiii
Copy link
Member

@erikzhang Need your review.

@erikzhang
Copy link
Member

We're running this line in OnPersist context. It invokes GAS.Mint. It calls PostTransfer. Which calls onNEP17Payment. That fails. What are we gonna do then? Fail persisting a block? Not an option. Ignore this problem and fail GAS distribution? Fine, except some storage changes are already in-flight in this context and, most importantly, tx.Sender may just not have enough GAS for the Burn() one line below. So, what are the options we have?

I agree with @roman-khimov. And I think we shouldn't merge this PR.

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.

auto-claim gas on tx submission
8 participants