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

chore: optimize getSlotFromOffset #6941

Merged
merged 2 commits into from
Jul 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions packages/beacon-node/src/util/sszBytes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,24 @@ export function getSlotFromBlobSidecarSerialized(data: Uint8Array): Slot | null
return getSlotFromOffset(data, SLOT_BYTES_POSITION_IN_SIGNED_BLOB_SIDECAR);
}

function getSlotFromOffset(data: Uint8Array, offset: number): Slot {
// TODO: Optimize
const dv = new DataView(data.buffer, data.byteOffset, data.byteLength);
// Read only the first 4 bytes of Slot, max value is 4,294,967,295 will be reached 1634 years after genesis
return dv.getUint32(offset, true);
/**
* Read only the first 4 bytes of Slot, max value is 4,294,967,295 will be reached 1634 years after genesis
*
* If the high bytes are not zero, return null
*/
function getSlotFromOffset(data: Uint8Array, offset: number): Slot | null {
return checkSlotHighBytes(data, offset) ? getSlotFromOffsetTrusted(data, offset) : null;
}

/**
* Read only the first 4 bytes of Slot, max value is 4,294,967,295 will be reached 1634 years after genesis
*/
function getSlotFromOffsetTrusted(data: Uint8Array, offset: number): Slot {
return (data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24)) >>> 0;
}

function checkSlotHighBytes(data: Uint8Array, offset: number): boolean {
return (data[offset + 4] | data[offset + 5] | data[offset + 6] | data[offset + 7]) === 0;
}

function toBase64(data: Uint8Array): string {
Expand Down
29 changes: 29 additions & 0 deletions packages/beacon-node/test/perf/util/dataview.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {itBench} from "@dapplion/benchmark";

describe("dataview", function () {
const data = Uint8Array.from([0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);

itBench({
id: "getUint32 - dataview",
beforeEach: () => {
return 0;
},
fn: (offset) => {
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
view.getUint32(offset, true);
},
});

itBench({
id: "getUint32 - manual",
beforeEach: () => {
return 0;
},
fn: (offset) => {
// check high bytes for non-zero values
(data[offset + 4] | data[offset + 5] | data[offset + 6] | data[offset + 7]) === 0;
// create the uint32
(data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24)) >>> 0;
},
});
});
11 changes: 10 additions & 1 deletion packages/beacon-node/test/unit/util/sszBytes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {fromHex, toHex} from "@lodestar/utils";
import {
getAttDataBase64FromAttestationSerialized,
getAttDataBase64FromSignedAggregateAndProofSerialized,
getAggregationBitsFromAttestationSerialized as getAggregationBitsFromAttestationSerialized,
getAggregationBitsFromAttestationSerialized,
getBlockRootFromAttestationSerialized,
getBlockRootFromSignedAggregateAndProofSerialized,
getSlotFromAttestationSerialized,
Expand Down Expand Up @@ -126,6 +126,15 @@ describe("aggregateAndProof SSZ serialized picking", () => {
expect(getAttDataBase64FromSignedAggregateAndProofSerialized(Buffer.alloc(size))).toBeNull();
}
});
it("getSlotFromSignedAggregateAndProofSerialized - invalid data - large slots", () => {
const serialize = (slot: Slot): Uint8Array => {
const s = ssz.phase0.SignedAggregateAndProof.defaultValue();
s.message.aggregate.data.slot = slot;
return ssz.phase0.SignedAggregateAndProof.serialize(s);
};
expect(getSlotFromSignedAggregateAndProofSerialized(serialize(0xffffffff))).toBe(0xffffffff);
expect(getSlotFromSignedAggregateAndProofSerialized(serialize(0x0100000000))).toBeNull();
});
});

describe("signedBeaconBlock SSZ serialized picking", () => {
Expand Down
Loading