-
-
Notifications
You must be signed in to change notification settings - Fork 272
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
[Stubbed] Greg/startup #71
Changes from all commits
85b13ad
4a3e66d
1bb235a
090f41f
ec5a234
fde1143
771bcc0
30de574
8e431b2
d2feba4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import Start from './lib'; | ||
|
||
Start(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { ChainStart } from "../interfaces/state"; | ||
import { waitForChainStart } from "./powChain"; | ||
|
||
/** | ||
* Start calls waitForChainStart, until the eth1depoist contract has executed the `ChainStart` log. Once executed, it | ||
* will generate the initial state ("genesis block"). | ||
* @returns {Promise<void>} | ||
* @constructor | ||
*/ | ||
// TODO currently returns a promise due to async calls, probably a better way. | ||
const Start = async (): Promise<void> => { | ||
// NOTE: It is not possible to catch in this implementation, the promise only resolves. | ||
const startConfig: ChainStart = await waitForChainStart(); | ||
// Call getInitialBeaconState() and start the beacon chain. | ||
// const initialState = getInitialBeaconState(); | ||
// TBD... | ||
}; | ||
|
||
export default Start; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { ethers, Contract } from 'ethers'; | ||
import { EtherscanProvider } from 'ethers/providers'; | ||
import { Deposit, DepositData, DepositInput } from '../../interfaces/blocks'; | ||
import { ChainStart } from "../../interfaces/state"; | ||
import { DEPOSIT_CONTRACT_ADDRESS, DEPOSIT_CONTRACT_BLOCK_NUMBER, DEPOSIT_CONTRACT_ABI } from "../../constants/constants"; | ||
|
||
// Type stubs | ||
type uint64 = number; | ||
type hash32 = string; | ||
|
||
|
||
// NOTE: This is stubbed | ||
// TODO: We should find a way to reject the promise somehow. | ||
// TODO: There is porbably a better way to scrape the logs. | ||
/** | ||
* Polls the eth1.x deposit contract for validator deposits. If the ChainStart log is emitted, return the promise with | ||
* intial state data. | ||
* @returns {Promise<ChainStart>} | ||
*/ | ||
const waitForChainStart = () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think its plausible to test this functionality at this point, the notion of waiting for the ChainStart log isn't going to change. Please add tests if you agree. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You know you're actually right. I'll probably have to import the vyper contract? Unless #66 gets closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #66 has been closed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After some thought, you're right I can test this. The tests will only cover the actual chainstart functionality and not the deposits for now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want to add truffle/embark? Before continuing we'll need to discuss if we want a framework for testing smart contracts or not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about etherlime? It uses ethers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. etherlime looks good. Still need to figure out what we want to do. Ultimately, we could do it manually. |
||
return new Promise<ChainStart>((resolve) => { | ||
const deposits: Deposit[] = []; | ||
|
||
// Connect to the network | ||
let provider = ethers.getDefaultProvider(); | ||
|
||
// Deposit Contract | ||
let depositContract: ethers.Contract = new ethers.Contract(DEPOSIT_CONTRACT_ADDRESS, DEPOSIT_CONTRACT_ABI, provider); | ||
|
||
// Eth1Deposit log filter | ||
let depositTopic: string = depositContract.Eth1Deposit(); | ||
let depositFilter: ethers.EventFilter = { | ||
address: DEPOSIT_CONTRACT_ADDRESS, | ||
topics: [ depositTopic ] | ||
}; | ||
|
||
// ChainStart log filter | ||
let chainStartTopic: string = depositContract.ChainStart(); | ||
let chainStartFilter: ethers.EventFilter = { | ||
address: DEPOSIT_CONTRACT_ADDRESS, | ||
topics: [ chainStartTopic ] | ||
}; | ||
|
||
// Listen for Eth1Deposit logs | ||
provider.on(depositFilter, (previousReceiptRoot: hash32[], data: DepositData, totalDepositcount: uint64, log) => { | ||
const newDeposit: Deposit = formatDeposit(previousReceiptRoot, data, totalDepositcount); | ||
deposits.push(newDeposit); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whats the point of storing the deposits here? Should we maybe provide a function to allow their retrieval instead of discarding them in this code block? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure what you mean by discarding... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct me if I'm wrong, deposits will only added until the ChainStart event resolves the promise. ie. future deposits won't be captured here. It does seem a class structure would be a way to resolve this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Correct, that's why I created the deposits helper. Um unsure with the current spec at what point a new deposit needs to be captured. I.e what point in the state transition. |
||
}); | ||
|
||
// Listen for ChainStart log and resolve the promise. | ||
provider.on(chainStartFilter, (receiptRoot, time, log) => { | ||
resolve({ deposits, receiptRoot, time }); | ||
}); | ||
|
||
// Reset filter to start when the contract was mined. | ||
provider.resetEventsBlock(DEPOSIT_CONTRACT_BLOCK_NUMBER); | ||
}); | ||
}; | ||
|
||
// NOTE This is stubbed. | ||
// TODO Create custom type for param data. | ||
// TODO Test against contract | ||
/** | ||
* Helper function for processing the Eth1Deposit event. | ||
* @param {hash32[]} previousReceiptRoot | ||
* @param data | ||
* @param {uint64} totalDepositCount | ||
* @returns {Deposit} | ||
*/ | ||
const formatDeposit = (previousReceiptRoot: hash32[], data: any, totalDepositCount: uint64): Deposit => { | ||
// Reassign values to stay consistent with camel case | ||
const depositInput: DepositInput = { | ||
pubkey: data.deposit_input.pubkey, | ||
proofOfPossession: data.deposit_input.proof_of_possession, | ||
withdrawalCredentials: data.deposit_input.withdrawal_credentials, | ||
randaoCommitment: data.deposit_input.randao_commitment, | ||
pocCommitment: data.deposit_input.poc_commitment | ||
}; | ||
|
||
const depositData: DepositData = { | ||
depositInput: depositInput, | ||
value: data.msg_gwei_bytes8, | ||
timestamp: data.timestamp_bytes8 | ||
}; | ||
|
||
// Formatted Deposit | ||
return { | ||
depositData: depositData, | ||
merkleBranch: previousReceiptRoot, | ||
merkleTreeIndex: totalDepositCount | ||
}; | ||
}; | ||
|
||
export { | ||
waitForChainStart, | ||
}; |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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.
Can you explain the use case for this?
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.
It actually should be stubbed to "tbd". But it's the block at which the contract is deployed, so we can start looking for receipts at that block number, and then work forward.
Will add comments
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.
Isn't that what the ChainStart event is for? As I understand it deposits made after are still valid so I don't see the point in differentiating those made before and from those made after.
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.
MMM good call. Pretty sure I added this earlier in the implementation
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.
Slight confusion, the ChainStart event is not for this. This is to reset to the block at which the contract is created at. This way we can begin looking at all deposits up to the ChainStart event.
As mentioned before, perhaps we need to re-org this a bit.