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

Move everything into LedgerContract #2215

Merged
merged 23 commits into from
Jan 21, 2021
Merged

Move everything into LedgerContract #2215

merged 23 commits into from
Jan 21, 2021

Conversation

erikzhang
Copy link
Member

No description provided.

@erikzhang erikzhang added this to the NEO 3.0 milestone Jan 11, 2021
@erikzhang
Copy link
Member Author

Any one can help me to fix the UTs? 😅

@chenzhitong
Copy link
Member

chenzhitong commented Jan 11, 2021

I'll try.

public class TransactionState : IInteroperable
{
public uint BlockIndex;
public Transaction Transaction;
Copy link
Member

Choose a reason for hiding this comment

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

Missing VMState?

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 removed it.

Copy link
Member

Choose a reason for hiding this comment

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

I think that it's useful for explorers know if the transaction was fault.

Copy link
Member Author

Choose a reason for hiding this comment

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

Explorers can use ApplicationLogs.

Copy link
Member

Choose a reason for hiding this comment

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

I think that only cost one byte and it's a useful information

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 you need VMState, inLedgerContract.OnPersist you have to run the script of all the transactions.

Copy link
Member

Choose a reason for hiding this comment

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

How to get transaction.BlockIndex, Is this correct?

TransactionState txState = Blockchain.Singleton.View.Transactions.TryGet(hash);
var blockIndex = txState.BlockIndex;using var snapshot = Blockchain.Singleton.GetSnapshot();
Transaction tx = NativeContract.Ledger.GetTransaction(snapshot, hash);
TransactionState txState = new TransactionState()
{
    Transaction = tx,
    BlockIndex = NativeContract.Ledger.CurrentIndex(snapshot) - tx.ValidUntilBlock
};
var blockIndex = txState.BlockIndex;

src/neo/Ledger/MemoryPool.cs Show resolved Hide resolved
src/neo/Ledger/MemoryPool.cs Show resolved Hide resolved
Copy link
Member

@vncoelho vncoelho left a comment

Choose a reason for hiding this comment

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

I like this clean and organization.
In particular, empowering Native Contracts is a promising direction in our opinion.
It is better for users, maintenance and general view of the system.

Copy link
Contributor

@roman-khimov roman-khimov left a comment

Choose a reason for hiding this comment

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

This move adds unnecessary pressure on MPT and breaks tail cutting (MaxTraceableBlock) because the node that deletes blocks/transactions after MaxTraceableBlock will have a different state from the one that doesn't do that.

Does it solve any real problem?

@erikzhang
Copy link
Member Author

What do you think? @neo-project/core

@chenzhitong chenzhitong mentioned this pull request Jan 12, 2021
18 tasks
@shargon
Copy link
Member

shargon commented Jan 12, 2021

I am worry about the TPS, I think that it could be slower

@erikzhang
Copy link
Member Author

I am worry about the TPS, I think that it could be slower

Why do you think that it could be slower?

@shargon
Copy link
Member

shargon commented Jan 12, 2021

Why do you think that it could be slower?

There are more method calls, the key is more complex, and also its converted to StackItem before serialization, so serialization is less optimized.

@vncoelho
Copy link
Member

vncoelho commented Jan 12, 2021

In terms of design I believe it is the correct design, appropriated in terms of security, transparency and practice.
It is an innovative use of certificates aligned with Native contracts.

I still see other possible important Native contracts in a near future, such as MultiSign composing that we are discussing and other mechanisms.

In terms of computation costs, I believe it is almost the same.
The MPT could be outside as we have been suggesting, but since it is now embedded we should not block innovative features because of this choice.

@roman-khimov
Copy link
Contributor

we should not block innovative features

Sure, but what this feature really buys us? What is the problem we're trying to solve?

Apart from problems mentioned above we're currently defining state as a set of contract storage key-value pairs. Which are side-effects of block/transaction executions. But they're side-effects, not blocks and transactions themselves. The difference is that blocks (with transactions included) are easy to obtain via P2P while state is not, it requires some processing overhead to get it (even if we're to imagine P2P state exchange mechanism that would imply synchronization to some height H and while we're getting it the chain would advance to H+X). So to me adding blocks to contract storage space just adds unnecessary overhead, it's not a state, it's what state is derived from.

It also makes it harder to optimize some things, like nspcc-dev/neo-go#1586 or trying to move block/transaction serialization in a separate thread (it's somewhat visible in the profiler and yes, I have to confess, I have already tried that in neo-go).

@vncoelho
Copy link
Member

vncoelho commented Jan 12, 2021

defining state as a set of contract storage key-value pairs

That is the state.

The MPT and other mechanisms are certificates.

@erikzhang
Copy link
Member Author

This move adds unnecessary pressure on MPT

We can exclude the storage of some contracts from the calculation of MPT.

Sure, but what this feature really buys us? What is the problem we're trying to solve?

For me, it provides a unified aesthetic design that makes everything in the contracts.

@igormcoelho
Copy link
Contributor

Hi all, I think this is an innovative approach, couldn't look into implementation details though... but one very important indicator is this basic code diff summary: +1,302 −2,204
I don't know if proposal is far from complete, but judging it's not, it may be really interesting to see the ledger as an active contract inside the network. As long as each contract hold its logic, and they manage to interoperate to make the network fulfill its purpose (providing a global state for turing complete computation in decentralized p2p environment), it looks nice to me.
Regarding performance, unless we are at the microbenchmarking level, it's quite hard to assess the impact of every operation, so again I'll quote "+1,302 −2,204"... small codes tend to be much easier to review and maintain, therefore, much easier to find the real bottlenecks, in some near future.

@erikzhang
Copy link
Member Author

Maybe we can merge first and optimize it later.

@roman-khimov
Copy link
Contributor

The difference is quite significant and I'm concerned with block time metric which usually is quite stable for C# node, but this change almost doubles it compared to master branch at the end of neo-bench run (with 1M transactions). So I'd rather wait for performance fixes (at least proving that they're possible in this case).

vncoelho
vncoelho previously approved these changes Jan 19, 2021
Copy link
Member

@vncoelho vncoelho left a comment

Choose a reason for hiding this comment

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

I prefer to merge and optimize later in order to keep compatibility and maintenance.

@Tommo-L
Copy link
Contributor

Tommo-L commented Jan 20, 2021

Maybe we can merge first and optimize it later.

Agree, as the change is relatively large, we need to merge it first to update other modules. And we still will continue to investigate the performance.

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

If we make sure it will be added to Preview5, then we should ensure function complete in every repo. Performance can be improved on the second step I think. So maybe we could merge it first and make other repos ready, then we could improve it later together.

shargon
shargon previously approved these changes Jan 20, 2021
@Qiao-Jin
Copy link
Contributor

After retesting it shows TPS between master and this PR is somehow similiar. Difference in previous result is due to test data incompatibility.
image

Qiao-Jin
Qiao-Jin previously approved these changes Jan 20, 2021
@shargon shargon dismissed stale reviews from Qiao-Jin, Tommo-L, vncoelho, and themself via abf0dc3 January 20, 2021 12:01
shargon
shargon previously approved these changes Jan 20, 2021
@erikzhang erikzhang merged commit 7982856 into master Jan 21, 2021
@erikzhang erikzhang deleted the native/ledger-contract branch January 21, 2021 06:08
cloud8little pushed a commit to cloud8little/neo that referenced this pull request Jan 24, 2021
ixje added a commit to CityOfZion/neo-mamba that referenced this pull request Feb 16, 2021
roman-khimov added a commit to nspcc-dev/neo-go that referenced this pull request Jul 27, 2024
This is a bad one.

$ ./bin/neo-go contract testinvokefunction -r https://rpc10.n3.nspcc.ru:10331 0xda65b600f7124ce6c79950c1772a36403104f2be getBlock 5762000
{
  "state": "HALT",
  "gasconsumed": "202812",
  "script": "AtDrVwARwB8MCGdldEJsb2NrDBS+8gQxQDYqd8FQmcfmTBL3ALZl2kFifVtS",
  "stack": [
    {
      "type": "Array",
      "value": [
        {
          "type": "ByteString",
          "value": "vq5IPTPEDRhz0JA4cQKIa6/o97pnJt/HfVkDRknd1rg="
        },
        {
          "type": "Integer",
          "value": "0"
        },
        {
          "type": "ByteString",
          "value": "zFYF3LGaTKdbqVX99shaBUzTq9YjXb0jaPMjk2jdSP4="
        },
        {
          "type": "ByteString",
          "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
        },
        {
          "type": "Integer",
          "value": "1722060076994"
        },
        {
          "type": "Integer",
          "value": "5293295626238767595"
        },
        {
          "type": "Integer",
          "value": "5762000"
        },
        {
          "type": "ByteString",
          "value": "LIt05Fpxhl/kXMX3EAGIASyOSQs="
        },
        {
          "type": "Integer",
          "value": "0"
        }
      ]
    }
  ],
  "exception": null,
  "notifications": []
}

$ ./bin/neo-go contract testinvokefunction -r http://seed3.neo.org:10332 0xda65b600f7124ce6c79950c1772a36403104f2be getBlock 5762000
{
  "state": "HALT",
  "gasconsumed": "202812",
  "script": "AtDrVwARwB8MCGdldEJsb2NrDBS+8gQxQDYqd8FQmcfmTBL3ALZl2kFifVtS",
  "stack": [
    {
      "type": "Array",
      "value": [
        {
          "type": "ByteString",
          "value": "vq5IPTPEDRhz0JA4cQKIa6/o97pnJt/HfVkDRknd1rg="
        },
        {
          "type": "Integer",
          "value": "0"
        },
        {
          "type": "ByteString",
          "value": "zFYF3LGaTKdbqVX99shaBUzTq9YjXb0jaPMjk2jdSP4="
        },
        {
          "type": "ByteString",
          "value": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="
        },
        {
          "type": "Integer",
          "value": "1722060076994"
        },
        {
          "type": "Integer",
          "value": "5293295626238767595"
        },
        {
          "type": "Integer",
          "value": "5762000"
        },
        {
          "type": "Integer",
          "value": "6"
        },
        {
          "type": "ByteString",
          "value": "LIt05Fpxhl/kXMX3EAGIASyOSQs="
        },
        {
          "type": "Integer",
          "value": "0"
        }
      ]
    }
  ],
  "exception": null,
  "notifications": []
}

9 fields vs 10, notice the primary index right after the block number.

Back when ac52765 initially added Ledger I've
used neo-project/neo#2215 as a reference and it was
correct (no primary index). But then neo-project/neo#2296
came into the C# codebase and while it looked like a pure refactoring it
actually did add the primary index as well and this wasn't noticed. It wasn't
noticed even when 3a4e0ca had touched some
nearby code. In short, we had a completely wrong implementation of this call
for more than three years. But looks like it's not a very popular one.

Signed-off-by: Roman Khimov <roman@nspcc.ru>
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.

9 participants