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

(unfinished) load partial verifications too #578

Closed
wants to merge 1 commit into from
Closed
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: 16 additions & 7 deletions analyzer/evmverifier/evmverifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,17 @@ func NewAnalyzer(
)
}

type VerificationState uint8

const (
VerificationStateUnverified VerificationState = iota
VerificationStatePartial
VerificationStateFull
)

type unverifiedContract struct {
Addr string
VerificationState VerificationState
AddrContextIdentifier string
AddrContextVersion int
AddrData []byte
Expand Down Expand Up @@ -136,25 +145,25 @@ func (p *processor) getVerifiableContracts(ctx context.Context) ([]*unverifiedCo
}

// Query Sourcify for list of all verified contracts.
addresses, err := p.source.GetVerifiedContractAddresses(ctx, p.runtime)
response, err := p.source.GetVerifiedContractAddresses(ctx, p.runtime)
if err != nil {
return nil, fmt.Errorf("failed to get verified contract addresses: %w", err)
}
p.logger.Debug("got verified contract addresses", "addresses", addresses)
if len(addresses) == 0 {
p.logger.Debug("got verified contract addresses", "response", response)
if len(response.Full) == 0 && len(response.Partial) == 0 {
p.logger.Debug("no verified contracts found in Sourcify")
return nil, nil
}
// Create a lookup map of verified contract addresses.
sourcifyAddresses := make(map[ethCommon.Address]bool, len(addresses))
for _, address := range addresses {
sourcifyAddresses[address] = true
sourcifyFullAddresses := make(map[ethCommon.Address]bool, len(response.Full))
for _, address := range response.Full {
sourcifyFullAddresses[address] = true
}

// Pick currently unverified contracts that are present in sourcify.
var canBeVerified []*unverifiedContract
for _, contract := range unverified {
if _, ok := sourcifyAddresses[contract.EthAddr]; ok {
if _, ok := sourcifyFullAddresses[contract.EthAddr]; ok {
canBeVerified = append(canBeVerified, contract)
}
}
Expand Down
18 changes: 10 additions & 8 deletions analyzer/evmverifier/sourcify/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ var sourcifyChains = map[common.ChainName]map[common.Runtime]string{
},
}

type ContractsResponse struct {
Full []ethCommon.Address `json:"full"`
Partial []ethCommon.Address `json:"partial"`
}

// SourcifyClient is a client for interacting with the Sourcify Server API,
// providing methods to fetch and parse contract data for supported Oasis runtimes.
type SourcifyClient struct {
Expand Down Expand Up @@ -73,25 +78,22 @@ func (s *SourcifyClient) callAPI(ctx context.Context, method string, url *url.UR
//
// Note: This uses the free, public server API. If it turns out to be unreliable, we could use the repository API (vis IPFS proxy) instead, e.g.:
// http://ipfs.default:8080/ipns/repo.sourcify.dev/contracts/full_match/23294
func (s *SourcifyClient) GetVerifiedContractAddresses(ctx context.Context, runtime common.Runtime) ([]ethCommon.Address, error) {
func (s *SourcifyClient) GetVerifiedContractAddresses(ctx context.Context, runtime common.Runtime) (ContractsResponse, error) {
// Fetch verified contract addresses.
u := *s.serverUrl
u.Path = path.Join(u.Path, "files/contracts", sourcifyChains[s.chain][runtime])
body, err := s.callAPI(ctx, http.MethodGet, &u)
if err != nil {
return nil, fmt.Errorf("failed to fetch verified contract addresses: %w (%s)", err, u.String())
return ContractsResponse{}, fmt.Errorf("failed to fetch verified contract addresses: %w (%s)", err, u.String())
}

// Parse response.
var response struct {
Full []ethCommon.Address `json:"full"`
// XXX: Skip partial matches for now: https://docs.sourcify.dev/docs/full-vs-partial-match/
}
var response ContractsResponse
if err := json.Unmarshal(body, &response); err != nil {
return nil, fmt.Errorf("failed to parse verified contract addresses: %w (%s)", err, u.String())
return ContractsResponse{}, fmt.Errorf("failed to parse verified contract addresses: %w (%s)", err, u.String())
}

return response.Full, nil
return response, nil
}

// GetContractSourceFiles returns the source files for the given contract address that is verified on sourcify.
Expand Down
3 changes: 2 additions & 1 deletion analyzer/evmverifier/sourcify/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ func TestGetVerifiedContractAddresses(t *testing.T) {
addresses, err := testClient.GetVerifiedContractAddresses(context.Background(), common.RuntimeEmerald)
require.NoError(err, "GetVerifiedContractAddresses")

require.Len(addresses, 15, "GetVerifiedContractAddresses")
require.Len(addresses.Full, 15, "GetVerifiedContractAddresses Full")
require.Len(addresses.Partial, 0, "GetVerifiedContractAddresses Partial")
}

func TestGetContractSourceFiles(t *testing.T) {
Expand Down
5 changes: 3 additions & 2 deletions analyzer/queries/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -790,14 +790,15 @@ var (

RuntimeEVMUnverfiedContracts = `
SELECT contracts.contract_address,
contracts.verification_state,
address_preimages.context_identifier,
address_preimages.context_version,
address_preimages.address_data
address_preimages.address_data,
FROM chain.evm_contracts AS contracts
LEFT JOIN chain.address_preimages AS address_preimages ON
address_preimages.address = contracts.contract_address
WHERE
runtime = $1 AND verification_info_downloaded_at IS NULL`
runtime = $1 AND verification_state < 2`

RuntimeEVMVerifyContractUpdate = `
UPDATE chain.evm_contracts
Expand Down
9 changes: 7 additions & 2 deletions storage/migrations/02_runtimes.up.sql
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,14 @@ CREATE TABLE chain.evm_contracts
-- -- Contents of metadata.json, typically produced by the Solidity compiler.
-- compilation_metadata JSONB,
-- -- Each source file is a flat JSON object with keys "name", "content", "path", as returned by Sourcify.
-- source_files JSONB CHECK (jsonb_typeof(source_files)='array');
-- source_files JSONB CHECK (jsonb_typeof(source_files)='array'),

-- Added in 24_evm_contract_partial_verification.up.sql
-- verification_state INTEGER NOT NULL DEFAULT 0,
);
-- CREATE INDEX ix_evm_contracts_unverified ON chain.evm_contracts (runtime) WHERE verification_info_downloaded_at IS NULL; -- Added in 07_evm_contract_verification.up.sql
-- Added in 07_evm_contract_verification.up.sql
-- Modified in 24_evm_contract_partial_verification.up.sql
-- CREATE INDEX ix_evm_contracts_unverified ON chain.evm_contracts (runtime) WHERE verification_state != 2;

-- -- -- -- -- -- -- -- -- -- -- -- -- Module accounts -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
BEGIN;

ALTER TABLE chain.evm_contracts
ADD COLUMN verification_state INTEGER NOT NULL DEFAULT 0; -- See VerificationState in analyzer/evmverifier.

DROP INDEX chain.ix_evm_contracts_unverified;
CREATE INDEX ix_evm_contracts_unverified ON chain.evm_contracts (runtime) WHERE verification_state < 2;

COMMIT;