Skip to content

Commit

Permalink
spec runner merge sanity and operations fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
g11tech committed Nov 8, 2021
1 parent 5c74efd commit 3034117
Show file tree
Hide file tree
Showing 17 changed files with 341 additions and 46 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-sim-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ jobs:
# Install Geth merge interop
- uses: actions/setup-go@v2
- name: Clone Geth merge interop branch
run: git clone -b merge-interop-spec https://github.com/MariusVanDerWijden/go-ethereum.git
run: git clone -b kintsugi-spec https://github.com/MariusVanDerWijden/go-ethereum.git
- name: Build Geth
run: cd go-ethereum && make

Expand Down
35 changes: 35 additions & 0 deletions kintsugi/genesis.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"config": {
"chainId":1,
"homesteadBlock":0,
"eip150Block":0,
"eip155Block":0,
"eip158Block":0,
"byzantiumBlock":0,
"constantinopleBlock":0,
"petersburgBlock":0,
"istanbulBlock":0,
"muirGlacierBlock":0,
"berlinBlock":0,
"londonBlock":0,
"clique": {
"period": 5,
"epoch": 30000
},
"terminalTotalDifficulty":0
},
"nonce":"0x42",
"timestamp":"0x0",
"extraData":"0x0000000000000000000000000000000000000000000000000000000000000000a94f5374fce5edbc8e2a8697c15331677e6ebf0b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit":"0x1C9C380",
"difficulty":"0x400000000",
"mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"coinbase":"0x0000000000000000000000000000000000000000",
"alloc":{
"0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b":{"balance":"0x6d6172697573766477000000"}
},
"number":"0x0",
"gasUsed":"0x0",
"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"baseFeePerGas":"0x7"
}
19 changes: 19 additions & 0 deletions kintsugi/geth/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM golang:1.17-alpine as builder
RUN apk add --no-cache gcc musl-dev linux-headers git
WORKDIR /usr/app

RUN git clone -b kintsugi-spec https://github.com/MariusVanDerWijden/go-ethereum.git
RUN cd /usr/app/go-ethereum && go run build/ci.go install ./cmd/geth


# Pull Geth into a second stage deploy alpine container
FROM alpine:latest
RUN apk add --no-cache bash curl

RUN apk add --no-cache ca-certificates
COPY --from=builder usr/app/go-ethereum/build/bin/geth /usr/local/bin/

WORKDIR /usr/app

EXPOSE 30303 30303/udp
ENTRYPOINT ["geth"]
8 changes: 6 additions & 2 deletions packages/beacon-state-transition/src/merge/block/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@ import {allForks, altair, merge} from "@chainsafe/lodestar-types";

import {CachedBeaconState} from "../../allForks/util";
import {processBlockHeader, processEth1Data, processRandao} from "../../allForks/block";
import {processOperations} from "../../altair/block/processOperations";
import {processOperations} from "./processOperations";
import {processSyncAggregate} from "../../altair/block/processSyncCommittee";
import {processExecutionPayload} from "./processExecutionPayload";
import {ExecutionEngine} from "../executionEngine";
import {isExecutionEnabled} from "../utils";
import {processAttesterSlashing} from "./processAttesterSlashing";
import {processProposerSlashing} from "./processProposerSlashing";

export {processOperations, processAttesterSlashing, processProposerSlashing};

export function processBlock(
state: CachedBeaconState<merge.BeaconState>,
Expand All @@ -23,6 +27,6 @@ export function processBlock(

processRandao(state as CachedBeaconState<allForks.BeaconState>, block, verifySignatures);
processEth1Data(state as CachedBeaconState<allForks.BeaconState>, block.body);
processOperations((state as unknown) as CachedBeaconState<altair.BeaconState>, block.body, verifySignatures);
processOperations(state, block.body, verifySignatures);
processSyncAggregate((state as unknown) as CachedBeaconState<altair.BeaconState>, block, verifySignatures);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {allForks, merge, phase0} from "@chainsafe/lodestar-types";
import {ForkName} from "@chainsafe/lodestar-params";
import {CachedBeaconState} from "../../allForks/util";
import {processAttesterSlashing as processAttesterSlashingAllForks} from "../../allForks/block";

export function processAttesterSlashing(
state: CachedBeaconState<merge.BeaconState>,
attesterSlashing: phase0.AttesterSlashing,
verifySignatures = true
): void {
processAttesterSlashingAllForks(
ForkName.merge,
state as CachedBeaconState<allForks.BeaconState>,
attesterSlashing,
verifySignatures
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {readonlyValues} from "@chainsafe/ssz";
import {altair, merge} from "@chainsafe/lodestar-types";

import {CachedBeaconState} from "../../allForks/util";
import {processProposerSlashing} from "./processProposerSlashing";
import {processAttesterSlashing} from "./processAttesterSlashing";
import {processAttestations} from "../../altair/block/processAttestation";
import {processDeposit} from "../../altair/block/processDeposit";
import {processVoluntaryExit} from "../../altair/block/processVoluntaryExit";
import {MAX_DEPOSITS} from "@chainsafe/lodestar-params";

export function processOperations(
state: CachedBeaconState<merge.BeaconState>,
body: merge.BeaconBlockBody,
verifySignatures = true
): void {
// verify that outstanding deposits are processed up to the maximum number of deposits
const maxDeposits = Math.min(MAX_DEPOSITS, state.eth1Data.depositCount - state.eth1DepositIndex);
if (body.deposits.length !== maxDeposits) {
throw new Error(
`Block contains incorrect number of deposits: depositCount=${body.deposits.length} expected=${maxDeposits}`
);
}

for (const proposerSlashing of readonlyValues(body.proposerSlashings)) {
processProposerSlashing(state, proposerSlashing, verifySignatures);
}
for (const attesterSlashing of readonlyValues(body.attesterSlashings)) {
processAttesterSlashing(state, attesterSlashing, verifySignatures);
}

processAttestations(
(state as unknown) as CachedBeaconState<altair.BeaconState>,
Array.from(readonlyValues(body.attestations)),
verifySignatures
);

for (const deposit of readonlyValues(body.deposits)) {
processDeposit((state as unknown) as CachedBeaconState<altair.BeaconState>, deposit);
}
for (const voluntaryExit of readonlyValues(body.voluntaryExits)) {
processVoluntaryExit((state as unknown) as CachedBeaconState<altair.BeaconState>, voluntaryExit, verifySignatures);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import {allForks, merge, phase0} from "@chainsafe/lodestar-types";
import {ForkName} from "@chainsafe/lodestar-params";
import {CachedBeaconState} from "../../allForks/util";
import {processProposerSlashing as processProposerSlashingAllForks} from "../../allForks/block";

export function processProposerSlashing(
state: CachedBeaconState<merge.BeaconState>,
proposerSlashing: phase0.ProposerSlashing,
verifySignatures = true
): void {
processProposerSlashingAllForks(
ForkName.merge,
state as CachedBeaconState<allForks.BeaconState>,
proposerSlashing,
verifySignatures
);
}
1 change: 1 addition & 0 deletions packages/beacon-state-transition/src/merge/epoch/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export {processSlashings} from "./processSlashings";
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {allForks, merge} from "@chainsafe/lodestar-types";
import {ForkName} from "@chainsafe/lodestar-params";
import {CachedBeaconState, IEpochProcess} from "../../allForks/util";
import {processSlashingsAllForks} from "../../allForks/epoch/processSlashings";

export function processSlashings(state: CachedBeaconState<merge.BeaconState>, epochProcess: IEpochProcess): void {
processSlashingsAllForks(ForkName.merge, state as CachedBeaconState<allForks.BeaconState>, epochProcess);
}
5 changes: 3 additions & 2 deletions packages/beacon-state-transition/src/merge/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export {processBlock} from "./block";
export {upgradeState} from "./upgradeState";
export * from "./block";
export * from "./epoch";
export * from "./upgradeState";
export * from "./utils";

// re-export merge lodestar types for ergonomic usage downstream
Expand Down
2 changes: 1 addition & 1 deletion packages/lodestar/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"test:sim:singleThread": "mocha 'test/sim/singleNodeSingleThread.test.ts'",
"test:sim:singleThreadMultiNode": "mocha 'test/sim/multiNodeSingleThread.test.ts'",
"test:sim:multiThread": "mocha 'test/sim/multiNodeMultiThread.test.ts'",
"test:sim:merge-interop": "mocha 'test/sim/merge-interop.test.ts'",
"test:sim:merge-interop": "mocha 'test/sim/merge-kintsugi.test.ts'",
"check-readme": "typescript-docs-verifier"
},
"dependencies": {
Expand Down
48 changes: 26 additions & 22 deletions packages/lodestar/src/executionEngine/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class ExecutionEngineHttp implements IExecutionEngine {
}

/**
* `engine_executePayload`
* `engine_executePayloadV1`
*
* 1. Client software MUST validate the payload according to the execution environment rule set with modifications to this rule set defined in the Block Validity section of EIP-3675 and respond with the validation result.
* 2. Client software MUST defer persisting a valid payload until the corresponding engine_consensusValidated message deems the payload valid with respect to the proof-of-stake consensus rules.
Expand All @@ -57,7 +57,7 @@ export class ExecutionEngineHttp implements IExecutionEngine {
* If the parent block is a PoS block as per EIP-3675 definition, then the call MAY be responded with SYNCING status and sync process SHOULD be initiated accordingly.
*/
async executePayload(executionPayload: merge.ExecutionPayload): Promise<ExecutePayloadStatus> {
const method = "engine_executePayload";
const method = "engine_executePayloadV1";
const {status} = await this.rpc.fetch<
EngineApiRpcReturnTypes[typeof method],
EngineApiRpcParamTypes[typeof method]
Expand All @@ -84,24 +84,30 @@ export class ExecutionEngineHttp implements IExecutionEngine {
notifyForkchoiceUpdate(
headBlockHash: RootHex,
finalizedBlockHash: RootHex,
_payloadAttributes?: PayloadAttributes
): Promise<PayloadId> {
const method = "engine_forkchoiceUpdated";
return this.rpc.fetch<EngineApiRpcReturnTypes[typeof method], EngineApiRpcParamTypes[typeof method]>({
method,
params: [{headBlockHash, finalizedBlockHash}],
});
payloadAttributes?: PayloadAttributes
): Promise<PayloadId | null> {
const method = "engine_forkchoiceUpdatedV1";
return this.rpc
.fetch<EngineApiRpcReturnTypes[typeof method], EngineApiRpcParamTypes[typeof method]>({
method,
params: [{headBlockHash, safeBlockHash: headBlockHash, finalizedBlockHash}, payloadAttributes],
})
.then(({payloadId}) => {
if ((payloadAttributes && payloadId === "0x") || (!payloadAttributes && payloadId !== "0x"))
throw Error("InvalidPayloadId");
return payloadId !== "0x" ? payloadId : null;
});
}

/**
* `engine_getPayload`
* `engine_getPayloadV1`
*
* 1. Given the payloadId client software MUST respond with the most recent version of the payload that is available in the corresponding building process at the time of receiving the call.
* 2. The call MUST be responded with 5: Unavailable payload error if the building process identified by the payloadId doesn't exist.
* 3. Client software MAY stop the corresponding building process after serving this call.
*/
async getPayload(payloadId: PayloadId): Promise<merge.ExecutionPayload> {
const method = "engine_getPayload";
const method = "engine_getPayloadV1";
const executionPayloadRpc = await this.rpc.fetch<
EngineApiRpcReturnTypes[typeof method],
EngineApiRpcParamTypes[typeof method]
Expand All @@ -120,7 +126,7 @@ type EngineApiRpcParamTypes = {
/**
* 1. Object - Instance of ExecutionPayload
*/
engine_executePayload: [ExecutionPayloadRpc];
engine_executePayloadV1: [ExecutionPayloadRpc];
/**
* 1. Object - Payload validity status with respect to the consensus rules:
* - blockHash: DATA, 32 Bytes - block hash value of the payload
Expand All @@ -132,30 +138,28 @@ type EngineApiRpcParamTypes = {
* - headBlockHash: DATA, 32 Bytes - block hash of the head of the canonical chain
* - finalizedBlockHash: DATA, 32 Bytes - block hash of the most recent finalized block
*/
engine_forkchoiceUpdated: [{headBlockHash: DATA; finalizedBlockHash: DATA}];
/**
* 1. Object - The payload attributes:
*/
engine_preparePayload: [PayloadAttributes];
engine_forkchoiceUpdatedV1: [
{headBlockHash: DATA; safeBlockHash: DATA; finalizedBlockHash: DATA},
{timestamp: QUANTITY; random: DATA; feeRecipient: DATA} | undefined
];
/**
* 1. payloadId: QUANTITY, 64 Bits - Identifier of the payload building process
*/
engine_getPayload: [QUANTITY];
engine_getPayloadV1: [QUANTITY];
};

type EngineApiRpcReturnTypes = {
/**
* Object - Response object:
* - status: String - the result of the payload execution:
*/
engine_executePayload: {status: ExecutePayloadStatus};
engine_executePayloadV1: {status: ExecutePayloadStatus};
engine_consensusValidated: void;
engine_forkchoiceUpdated: QUANTITY;
engine_forkchoiceUpdatedV1: {status: ExecutePayloadStatus; payloadId: QUANTITY};
/**
* payloadId | Error: QUANTITY, 64 Bits - Identifier of the payload building process
*/
engine_preparePayload: {payloadId: QUANTITY};
engine_getPayload: ExecutionPayloadRpc;
engine_getPayloadV1: ExecutionPayloadRpc;
};

type ExecutionPayloadRpc = {
Expand Down
2 changes: 1 addition & 1 deletion packages/lodestar/src/executionEngine/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export interface IExecutionEngine {
headBlockHash: RootHex,
finalizedBlockHash: RootHex,
payloadAttributes?: PayloadAttributes
): Promise<PayloadId>;
): Promise<PayloadId | null>;

/**
* Given the payload_id, get_payload returns the most recent version of the execution payload that has been built
Expand Down
Loading

0 comments on commit 3034117

Please sign in to comment.