@@ -3,11 +3,21 @@ import { SourcifyDatabaseService } from "../../../src/server/services/storageSer
33import config from "config" ;
44import chaiAsPromised from "chai-as-promised" ;
55import { 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
716use ( 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