Feature/persistent#179
Conversation
|
Awesome @mhhf, thanks for your work on this. Quick heads up: I'm going to be away from the 13th to the 31st, which means this PR likely won't get merged until after I'm back. I'm sorry for the delay. If you think you can make this production ready by Wednesday, happy to jump on it, however, and do what I can to get it merged. Regardless of timing, TestRPC 3.0 came out last week. Do you think you can remerge with Thanks! |
|
I can make a sprint in the next 2 days: finalizing all features, merging the current master and clean everything up, however I don't think I will solve the problems caused by #81 and solving them is required for a production ready version :( |
|
We should hammer down on that bug then. I suppose this gives us more time. :) |
|
I solved one source of non-deterministic bugs which also might be related to #81 - |
|
from geth 1.5 upwards there is a new |
|
@mhhf 👍 I'll have to look into that new request. About this PR: apologies. I'm spread super thin right now. Perhaps this is something @johnmcdowall might want to look into? (warning: low level testrpc arch stuff) Regardless, I'll see what I can do. |
|
@tcoulter I hear you :) also have very limited resources right now. Did you had a change look on the code? Spend some more time to finishing it as far as I could and here is the outcome: TDLR: Code is working although messy, need to sync up with you on how to proceed. Long version:
Overall: Do you want to schedule a call and go over those points/ plan a merge? |
| "eth_call": "before", | ||
| "eth_getStorageAt": "before", | ||
| "eth_getLogs": "before" | ||
| "eth_getStorageAt": "before" |
There was a problem hiding this comment.
You removed eth_getLogs from here. I remember it being needed to speed things up, if not provide the correct functionality. Are you sure it's no longer required? (I'm basically looking for surety; open to removing it if it's no longer required.)
There was a problem hiding this comment.
I had major trouble with it while working with logs on forked blockchain as some internal logic was triggering something twice. I don't remember fully what the side behavior was but after spending quite some time on debugging provider-engine (which is kind of hard) i just removed it here, and everything worked fine.
| var Blockchain = require('ethereumjs-blockchain'); | ||
| var Log = require("./log.js"); | ||
| var Receipt = require("./receipt.js"); | ||
| // var Receipt = require("./receipt.js"); |
There was a problem hiding this comment.
Looks like this isn't needed. Remove if it.
| block.header.stateRoot = utils.toBuffer(json.stateRoot); | ||
| block.header.difficulty = utils.toBuffer('0x00'); | ||
| block.header.gasLimit = utils.toBuffer(json.gasLimit); | ||
| block.header.number = utils.toBuffer(json.number + 1); |
There was a problem hiding this comment.
Anything here we can pull out and put in BlockchainDouble.createBlock() for consistency? Looks like difficulty might be the only one. For my edification, what was the reason to move away from createBlock() and instead use new Block()?
There was a problem hiding this comment.
BlockchainDouble.createBlock() here is never called, instead BlockchainDouble builds on top of parentBlock, which we want to prevent here as we forking of with a new Block. super.createBlock() is needed for later in the ForkedBlockchain as well, so I cannot override this.
I think the best way is to keeping it here.
| }); | ||
|
|
||
| var receipt = new Receipt(result.tx, result.block, logs, receipt_json.cumulativeGasUsed, receipt_json.contractAddress); | ||
| self.web3.eth.getTransactionReceipt(hash, callback); |
There was a problem hiding this comment.
This blows my mind that we can get rid of all this! The tests pass. Good catch!
|
|
||
| ForkedBlockchain.prototype.getRelativeBlockNumber = function(number) { | ||
| number = this.getEffectiveBlockNumber(number); | ||
| return number - to.number(this.fork_block_number) - 1; |
There was a problem hiding this comment.
Hmm, there was a reason I did this calculation, but I don't remember now exactly. If getRelativeBlockNumber and getEffectiveBlockNumber are synonymous, shouldn't we remove one or the other?
In my head, relative meant relative to our own block store: i.e., 0-based index in memory, which is needed to know if this is our block or the forked block. effective meant to translate things like "latest" to a real number. Have you merged the two?
There was a problem hiding this comment.
We should totally remove one. I was just sloppy on this.
| var relative = this.getRelativeBlockNumber(number); | ||
|
|
||
| if (relative < 0) { | ||
| if (relative <= parseInt(this.fork_block_number)) { |
There was a problem hiding this comment.
Looks like this might answer my above question, as the answer might be "you don't need getRelativeBlockNumber anymore".
There was a problem hiding this comment.
yes, this :)
I don't dig to deep into the relative vs. absolute block number and your code logic, just made enough changes to satisfy my need and make the tests pass. This part and the part above needs more consideration in oder for a clean refactoring.
| var current = block.transactions[i]; | ||
| if (current.hash() == tx.hash()) { | ||
| this.transactionIndex = index; | ||
| this.transactionIndex = i; |
There was a problem hiding this comment.
Hmm, how did that ever work...
There was a problem hiding this comment.
heh - consider some gentle linting
| gasPrice: utils.toBuffer("0x" + json.gasPrice.toString(16)), | ||
| data: utils.toBuffer(json.input) | ||
| }); | ||
| tx._hash = json.hash; |
There was a problem hiding this comment.
I don't generally like variables prefixed with _ that are set outside of the class file/object file itself. Can you tell me why this one is here?
There was a problem hiding this comment.
I just followed the etheruemjs-tx style _from variable here which is faked in the same way. Again that is part of the ugly ethereumjs-tx hack.
| "solc": "0.4.6", | ||
| "web3": "~0.16.0", | ||
| "web3-provider-engine": "~8.1.0", | ||
| "web3-provider-engine": "git+https://github.com/nexusdev/provider-engine.git", |
There was a problem hiding this comment.
I can't rely on these github repositories for a final release. Let's see if we can get your changes merged upstream in provider-engine and ethereumjs-blockchain merged upstream.
There was a problem hiding this comment.
at the very least you can target a specific commit
git+https://github.com/nexusdev/provider-engine.git#commitHash
There was a problem hiding this comment.
merged and published as web3-provider-engine@8.1.15 👍
There was a problem hiding this comment.
@tcoulter I updated the provider engine to the newest version (~8.1.16), However, this lead to the mining and mining_inverval tests failing.
The errors always happens at line like this: https://github.com/ethereumjs/testrpc/blob/master/test/mining.js#L300
I suppose the old provider engine had the feature of throwing an error in case a throwing transaction was send, now its successfully getting included into the new block (I assume the user still pays for a failed gas).
In my fork I skipped tests, which fails out of this reason.
| "eslint-plugin-standard": "~1.3.3", | ||
| "mocha": "~2.2.5" | ||
| "mocha": "~2.2.5", | ||
| "solc": "~0.3.0-1", |
There was a problem hiding this comment.
We should probably update solc here.
|
|
||
| assert(accounts[0].toLowerCase(), expected_address.toLowerCase()); | ||
| done(); | ||
| provider.close(done); |
There was a problem hiding this comment.
Again, we might be able to get around this which would remove the need for any for changes in many of these test files.
|
Alright, added a bunch of comments (I should have probably started a review; sorry for all the emails). Thanks again @mhhf! |
| @@ -73,8 +88,12 @@ ForkedBlockchain.prototype.initialize = function(accounts, callback) { | |||
| self.web3.eth.getBlock(blockNumber, function(err, json) { | |||
There was a problem hiding this comment.
I discovered a weirdness in web3 - if typeof blockNumber === "string" blockNumber is treaded as hash and a eth_getBlockByHash method call is generated which leads to a crash if block number 0 is requested which gets translated to 0x0. Only in the case its an number, its treaded as the blockNumber.
I fixed it in my fork by introducing this line:
if(typeof blockNumber == "string" && blockNumber[1] === "x" && blockNumber.length < 42) blockNumber = parseInt(blockNumber)
However, it doesn't feel clean. Also there is a chance for this happening somewhere else - I haven't scanned the code for other occurrences of this (just noticed it here). Is this line good enough or should I submit a new Issue for this?
|
@tcoulter I submitted a bunch of new corrections, so you can go and have a look on them. |
|
Should I close this? |
|
Absolutely not! I really appreciate your work here, and I apologize for the length of time this has taken me to complete. Merging this is the TestRPC's highest priority, actually. We currently have people using it and noting memory issues which we need to explore. They may be unrelated to this change, but I need to sit down with it and check it out. I expect to do this in the next two weeks. As an aside, I'm spread really thin. This has 100% been blocked by me and I take all the blame for it. I've sent you a message on gitter and would love to chat more. |
|
@mhhf Update: I did some digging into this, and it looks like a) ethereumjs-blockchain adds restrictions that are hard to get around, and b) it's likely etheruemjs-blockchain is going to be rewritten. The general word is, "Ya, it isn't used that much." My impression of the conversation was that it wouldn't be a good idea to use it. So instead, I used your branch as inspiration and rewrote database persistence in a different way, saving all the data in a custom fashion. You can see the PR here. The pros to this branch:
Cons:
I'll probably be moving forward with the |
|
Closing this. Thanks for all your work @mhhf. Merged |
There are a lot of this left to do, but this is a first draft in case anyone want take a look.
Unfortunately I struggle with a non deterministic test failure which might be caused my memdown and a lot bugs look familiar to #81.
However, all tests work fine in isolation.
In the long run the ethereumjs-blockchain dependency can be omitted with including db storage directly into blockchain_double.js