Skip to content

Commit 36244b2

Browse files
committed
Add tests
1 parent 9be3c13 commit 36244b2

File tree

4 files changed

+474
-3
lines changed

4 files changed

+474
-3
lines changed

services/server/src/server/services/utils/signature-util.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Interface, keccak256, Fragment, JsonFragment } from "ethers";
1+
import { Interface, id as keccak256str, Fragment, JsonFragment } from "ethers";
22

33
export interface SignatureData {
44
signature: string;
@@ -27,7 +27,7 @@ function getSignatureData(fragment: Fragment): SignatureData {
2727
const signature = fragment.format("sighash");
2828
return {
2929
signature,
30-
signatureHash32: keccak256(signature),
30+
signatureHash32: keccak256str(signature),
3131
signatureType: fragment.type as "function" | "event" | "error",
3232
};
3333
}

services/server/test/helpers/helpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ export async function resetDatabase(sourcifyDatabase: Pool) {
291291
);
292292
await sourcifyDatabase.query("DELETE FROM verified_contracts");
293293
await sourcifyDatabase.query("DELETE FROM contract_deployments");
294+
await sourcifyDatabase.query("DELETE FROM compiled_contracts_signatures");
295+
await sourcifyDatabase.query("DELETE FROM signatures");
294296
await sourcifyDatabase.query("DELETE FROM compiled_contracts_sources");
295297
await sourcifyDatabase.query("DELETE FROM sources");
296298
await sourcifyDatabase.query("DELETE FROM compiled_contracts");

services/server/test/integration/storageServices/SourcifyDatabaseService.spec.ts

Lines changed: 135 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,21 @@ import { SourcifyDatabaseService } from "../../../src/server/services/storageSer
33
import config from "config";
44
import chaiAsPromised from "chai-as-promised";
55
import { MockVerificationExport } from "../../helpers/mocks";
6+
import { resetDatabase } from "../../helpers/helpers";
7+
import sinon from "sinon";
8+
import * as signatureUtil from "../../../src/server/services/utils/signature-util";
9+
import { QueryResult } from "pg";
10+
import {
11+
bytesFromString,
12+
type Tables,
13+
} from "../../../src/server/services/utils/database-util";
14+
import { id as keccak256str } from "ethers";
615

716
use(chaiAsPromised);
817

9-
describe("SourcifyDatabaseService", function () {
18+
describe.only("SourcifyDatabaseService", function () {
1019
let databaseService: SourcifyDatabaseService;
20+
const sandbox = sinon.createSandbox();
1121

1222
before(async () => {
1323
process.env.SOURCIFY_POSTGRES_PORT =
@@ -34,6 +44,15 @@ describe("SourcifyDatabaseService", function () {
3444
},
3545
config.get("serverUrl"),
3646
);
47+
await databaseService.init();
48+
});
49+
50+
this.beforeEach(async () => {
51+
await resetDatabase(databaseService.database.pool);
52+
});
53+
54+
afterEach(() => {
55+
sandbox.restore();
3756
});
3857

3958
it("should throw an error if no verified_contracts row can be inserted for a verification update", async () => {
@@ -46,4 +65,119 @@ describe("SourcifyDatabaseService", function () {
4665
await expect(databaseService.storeVerification(MockVerificationExport)).to
4766
.eventually.be.rejected;
4867
});
68+
69+
it("should store signatures correctly when storeVerification is called", async () => {
70+
await databaseService.storeVerification(MockVerificationExport);
71+
72+
const signaturesResult: QueryResult<Tables.Signatures> =
73+
await databaseService.database.pool.query("SELECT * FROM signatures");
74+
75+
expect(signaturesResult.rowCount).to.equal(2);
76+
77+
const signatures = signaturesResult.rows;
78+
const retrieveSignature = signatures.find(
79+
(s) => s.signature === "retrieve()",
80+
);
81+
const storeSignature = signatures.find(
82+
(s) => s.signature === "store(uint256)",
83+
);
84+
85+
expect(retrieveSignature).to.exist;
86+
expect(storeSignature).to.exist;
87+
88+
const expectedRetrieveSignatureHash32 = bytesFromString(
89+
keccak256str(retrieveSignature!.signature),
90+
);
91+
const expectedStoreSignatureHash32 = bytesFromString(
92+
keccak256str(storeSignature!.signature),
93+
);
94+
95+
expect(retrieveSignature!.signature_hash_32).to.be.instanceOf(Buffer);
96+
expect(retrieveSignature!.signature_hash_32.length).to.equal(32);
97+
expect(
98+
retrieveSignature!.signature_hash_32.equals(
99+
expectedRetrieveSignatureHash32,
100+
),
101+
).to.be.true;
102+
expect(retrieveSignature!.signature_hash_4).to.be.instanceOf(Buffer);
103+
expect(retrieveSignature!.signature_hash_4.length).to.equal(4);
104+
expect(retrieveSignature!.signature_hash_4).to.deep.equal(
105+
expectedRetrieveSignatureHash32.subarray(0, 4),
106+
);
107+
108+
expect(storeSignature!.signature_hash_32).to.be.instanceOf(Buffer);
109+
expect(storeSignature!.signature_hash_32.length).to.equal(32);
110+
expect(
111+
storeSignature!.signature_hash_32.equals(expectedStoreSignatureHash32),
112+
).to.be.true;
113+
expect(storeSignature!.signature_hash_4).to.be.instanceOf(Buffer);
114+
expect(storeSignature!.signature_hash_4.length).to.equal(4);
115+
expect(storeSignature!.signature_hash_4).to.deep.equal(
116+
expectedStoreSignatureHash32.subarray(0, 4),
117+
);
118+
119+
const compiledContractSignaturesResult: QueryResult<Tables.CompiledContractsSignatures> =
120+
await databaseService.database.pool.query(
121+
"SELECT * FROM compiled_contracts_signatures",
122+
);
123+
124+
expect(compiledContractSignaturesResult.rowCount).to.equal(2);
125+
126+
const contractSignatures = compiledContractSignaturesResult.rows;
127+
const compiledContractRetrieveSig =
128+
compiledContractSignaturesResult.rows.find((csig) =>
129+
csig.signature_hash_32.equals(expectedRetrieveSignatureHash32),
130+
);
131+
const compiledContractStoreSig = contractSignatures.find((csig) =>
132+
csig.signature_hash_32.equals(expectedStoreSignatureHash32),
133+
);
134+
135+
expect(compiledContractRetrieveSig).to.exist;
136+
expect(compiledContractStoreSig).to.exist;
137+
expect(compiledContractRetrieveSig!.compilation_id).to.equal(
138+
compiledContractStoreSig!.compilation_id,
139+
);
140+
expect(compiledContractRetrieveSig!.signature_type).to.equal("function");
141+
expect(compiledContractStoreSig!.signature_type).to.equal("function");
142+
});
143+
144+
it("should handle duplicate signature storage gracefully", async () => {
145+
// Change mock to be able to store the verification twice
146+
const modifiedVerification = structuredClone(MockVerificationExport);
147+
modifiedVerification.status.creationMatch = "partial";
148+
modifiedVerification.compilation.language = "Vyper";
149+
150+
await databaseService.storeVerification(modifiedVerification);
151+
await expect(databaseService.storeVerification(MockVerificationExport)).to
152+
.not.be.rejected;
153+
154+
const signaturesResult = await databaseService.database.pool.query(
155+
"SELECT COUNT(*) as count FROM signatures",
156+
);
157+
expect(parseInt(signaturesResult.rows[0].count)).to.equal(2);
158+
});
159+
160+
it("should still store verification even if signature storage fails", async () => {
161+
sandbox
162+
.stub(signatureUtil, "extractSignaturesFromAbi")
163+
.throws(new Error("Simulated signature extraction error"));
164+
165+
await expect(databaseService.storeVerification(MockVerificationExport)).to
166+
.not.be.rejected;
167+
168+
const verifiedContractsResult = await databaseService.database.pool.query(
169+
"SELECT COUNT(*) FROM verified_contracts",
170+
);
171+
expect(parseInt(verifiedContractsResult.rows[0].count)).to.equal(1);
172+
173+
const signaturesResult = await databaseService.database.pool.query(
174+
"SELECT COUNT(*) as count FROM signatures",
175+
);
176+
expect(parseInt(signaturesResult.rows[0].count)).to.equal(0);
177+
178+
const contractSignaturesResult = await databaseService.database.pool.query(
179+
"SELECT COUNT(*) as count FROM compiled_contracts_signatures",
180+
);
181+
expect(parseInt(contractSignaturesResult.rows[0].count)).to.equal(0);
182+
});
49183
});

0 commit comments

Comments
 (0)