Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
153 commits
Select commit Hold shift + click to select a range
4637a8d
Copy of llo integration test
cll-gg May 26, 2025
7fd9881
Remove other tests
cll-gg May 26, 2025
e5e4522
Remove more unused code
cll-gg May 26, 2025
ee3ded4
Remove a bit more
cll-gg May 26, 2025
1127b9d
Remove more unused code
cll-gg May 26, 2025
49ce867
Just run one test
cll-gg May 26, 2025
6afaa9f
Remove a bit more
cll-gg May 26, 2025
f5e0e48
WIP addSecureMintOCRJobs (fails atm)
cll-gg May 26, 2025
f2f0dea
Add some logging
cll-gg May 27, 2025
ae99fa3
Typo
cll-gg May 27, 2025
08635bc
Create eth key in node to have a transmitter
cll-gg May 27, 2025
4b286e0
Allow no bootstrappers to make the job start up
cll-gg May 27, 2025
dbf220d
Fix parameters (broken two commits ago)
cll-gg May 27, 2025
b9da47b
Use non-zero contract address so that logpoller starts up
cll-gg May 27, 2025
99e2fbe
Bridge is now called and returns data (observation fails)
cll-gg May 27, 2025
798fd95
Add some notes
cll-gg May 27, 2025
580bbc0
WIP: validate jobs running successfully
cll-gg May 27, 2025
3fad5ca
Make test logging more manageable
cll-gg May 28, 2025
586727b
Fix observation
cll-gg May 28, 2025
0418848
Improve logging
cll-gg May 28, 2025
4824ac3
Make it work by not asserting on saved pipeline runs (secure mint pip…
cll-gg May 28, 2025
ae6a8d6
Enable validation
cll-gg May 28, 2025
2a7f400
Use pluginType = securemint now. All parts to update are tagged with …
cll-gg May 28, 2025
b7c5f80
Fix unit test
cll-gg May 28, 2025
3bf8faf
Use plugin config from new plugin repo repo
cll-gg May 29, 2025
2bab28c
Create NewSecureMintServices
cll-gg May 29, 2025
92ed409
Implemented part of the delegate and part of the service
cll-gg May 29, 2025
a3eab0a
Use SecureMintOCR3OnchainKeyringAdapter to make it possible to use th…
cll-gg May 30, 2025
68f87b9
Try to set contract config - plugin doesn't get created otherwise (WIP)
cll-gg May 30, 2025
1e26f1a
Set the onchain config
cll-gg May 30, 2025
25dac5d
Use stub contract transmitter
cll-gg May 30, 2025
467cd23
WIP onchain config
cll-gg May 30, 2025
7e55c47
Use mock dependencies for now
cll-gg Jun 2, 2025
185a0a5
Deploy DF Cache contract and set onchain config on it
cll-gg Jun 2, 2025
509caf0
More clarity on onchain contract usage
cll-gg Jun 2, 2025
65eeb41
Set secureMintOnchainConfigUsingEvmSimpleConfig
cll-gg Jun 3, 2025
e8a397d
Step further in using the simple config
cll-gg Jun 3, 2025
78838f7
Two vibe-coded files to help
cll-gg Jun 3, 2025
d19f016
One step further: configPollerEVMSimple reads on-chain config
cll-gg Jun 3, 2025
62786e3
Bit more print
cll-gg Jun 3, 2025
cdebba4
Use aggregator for onchain ocr config now in the test
cll-gg Jun 4, 2025
04e4799
Got the oracle running!
cll-gg Jun 4, 2025
ec547b2
Make llo part of the test succeed again - to start from a successful …
cll-gg Jun 4, 2025
b23eb2e
Remove a lot of the LLO stuff from the test
cll-gg Jun 4, 2025
40360a5
Remove more unused things
cll-gg Jun 5, 2025
2fb71ea
Cleanup of the implementation (so far)
cll-gg Jun 5, 2025
8a09b97
One more not-needed change
cll-gg Jun 5, 2025
78962f1
Create sm bootstrap job
cll-gg Jun 5, 2025
ffff23c
Make nodes and secure mint job use bootstrap node
cll-gg Jun 5, 2025
7a87cf0
Waiting a bit longer lets the oracle run and generate an outcome
cll-gg Jun 6, 2025
dd88cc0
Add more logging, rename test, start data source
cll-gg Jun 6, 2025
b1b88d0
Pipeline completes now, observation fails in parsing the result
cll-gg Jun 6, 2025
a6f16a9
Make the bridge return por.Mintables and wait for pipeline completion
cll-gg Jun 9, 2025
97976c3
Add a bit more output to the bridge
cll-gg Jun 9, 2025
3a48da1
Use sm plugin second iteration branch
cll-gg Jun 9, 2025
a857f0c
Parse EA response
cll-gg Jun 9, 2025
56fdacc
Updating ea
cll-gg Jun 9, 2025
0a4ebc9
Let bridge respond as real EA with initial and later response + send …
cll-gg Jun 9, 2025
63e32d5
Transmit is called!
cll-gg Jun 9, 2025
b170290
Assert on report being (stub) transmitted
cll-gg Jun 9, 2025
a22161f
Remove duplicate code
cll-gg Jun 9, 2025
a80af5f
Clean up todos
cll-gg Jun 10, 2025
b580d11
Fixes after merging with develop
cll-gg Jun 10, 2025
c8de023
Done: validate secure mint plugin spec
cll-gg Jun 10, 2025
8ba152e
Add test for ea and use intermediate types based on Michael's message
cll-gg Jun 10, 2025
ace3ff2
Clean up EA request/response usage
cll-gg Jun 11, 2025
7740619
Clean up ea.go a bit more
cll-gg Jun 11, 2025
b01868e
Fix some more todos
cll-gg Jun 11, 2025
5af0efb
Small test cleanup
cll-gg Jun 11, 2025
bdba32f
Move all chain-write-related todos out of the PR into a ticket
cll-gg Jun 11, 2025
20cfb2f
Remove temporary tracing
cll-gg Jun 11, 2025
5a76670
Remove newline
cll-gg Jun 11, 2025
ba5ca61
Done: consolidated two securemint packages into one
cll-gg Jun 11, 2025
997dc59
Update plugin to fourth_iteration (commit cdd3409730eb2122d118f8324d2…
cll-gg Jun 11, 2025
8ca74a5
Bit more cleanup
cll-gg Jun 11, 2025
b6c148f
Rename LatestRelevantBlocks to LatestBlocks in EA response
cll-gg Jun 12, 2025
41af4ab
Make 'reserve' and 'platform' configurable through plugin config jobspec
cll-gg Jun 12, 2025
0dc254a
Leave a todo
cll-gg Jun 12, 2025
a39739e
Clean up delegate + services, remove all LOOPP-related things for now
cll-gg Jun 12, 2025
3d3a2ae
Use promwrapper for metrics
cll-gg Jun 12, 2025
660b7f4
Write readme
cll-gg Jun 12, 2025
2a141dd
Last todo done: improve stubContractReader
cll-gg Jun 12, 2025
9d29c56
Remove unrelated change
cll-gg Jun 12, 2025
4866788
Deploy & configure the ocr3 configurator contract
cll-gg Jun 18, 2025
ee4c502
Debug instructions
cll-gg Jun 19, 2025
f34d363
Use llo config provider in bootstrap job
cll-gg Jun 19, 2025
813d24b
Using the public csa key as transmitter, similar to LLO (WIP)
cll-gg Jun 19, 2025
1e81ea3
Made it work with stubs!
cll-gg Jun 19, 2025
d780094
Clean up
cll-gg Jun 19, 2025
65a9a24
Simplify
cll-gg Jun 19, 2025
ac7cb9f
Small cleanup
cll-gg Jun 19, 2025
7f35ac8
Bit more small cleanup
cll-gg Jun 19, 2025
6324cea
Use correct chainlink-common version + temp fixes for that
cll-gg Jun 26, 2025
fa51db2
Use local chainlink-common temporarily to make it work (depends on ht…
cll-gg Jul 4, 2025
03b4262
add skeleton support for secure mint trigger
Tofel Jun 27, 2025
025c948
Copy por plugin to make docker file build ('go mod download' in docke…
cll-gg Jul 2, 2025
9a13ed4
Introduce the cre secure mint transmitter
cll-gg Jul 2, 2025
3776559
Hack: start the transmitter from application to send mock events
cll-gg Jul 2, 2025
e63a101
Add option to disable hack in tests (to not pollute the test results)
cll-gg Jul 2, 2025
08daa41
Use WIP securemint aggregator
cll-gg Jul 3, 2025
1be5b41
Use correct chainlink-common version (from https://github.com/smartco…
cll-gg Jul 4, 2025
9b979c9
Progress on the aggregator (using the securemint workflow test)
cll-gg Jul 4, 2025
c959313
Aggregation seems to work now!
cll-gg Jul 4, 2025
445ed7a
Use existing workflow name so that the consumer contract is set corre…
cll-gg Jul 6, 2025
b57d816
Fix go.mod/go.sum, update feedID in test, add todos
cll-gg Jul 7, 2025
6ad4d13
Fix cl-common version
cll-gg Jul 8, 2025
853b707
Update to latest plugin
cll-gg Jul 8, 2025
1780815
And update the copy
cll-gg Jul 8, 2025
61d447b
Add extra hack to asses the number of workflow triggers + update Readme
cll-gg Jul 8, 2025
af113fe
Add to README
cll-gg Jul 8, 2025
175424d
Add layers of trigger abstraction to README
cll-gg Jul 8, 2025
6148b9e
Fix hack for triggering mock reports
cll-gg Jul 8, 2025
8583c11
Add some temporary logic to the ea translation layer to let the plugi…
cll-gg Jul 8, 2025
8e275bf
Put chainSelectors in the secure mint job spec
cll-gg Jul 8, 2025
03e66a4
Add two TODOs
cll-gg Aug 11, 2025
975e637
Update todo
cll-gg Aug 11, 2025
62e7769
Fix after rebase
cll-gg Aug 11, 2025
94f7df6
Fix
cll-gg Aug 11, 2025
fd90d89
Run make modgraph
cll-gg Aug 11, 2025
4cb1c0a
Fix imports - test succeeds
cll-gg Aug 11, 2025
1249038
Set correct version
cll-gg Aug 12, 2025
a323fd3
Serialize the ocr3Report and use a proper eventId
cll-gg Aug 12, 2025
107c9e5
Add unit tests for transmitter.Transmit()
cll-gg Aug 12, 2025
9ae5736
Merge branch 'develop' into sm-run-in-local-cre-dev-env
cll-gg Aug 14, 2025
3bb0d54
Remove local copy of sm plugin and some local cre-related things
cll-gg Aug 14, 2025
b8397d7
Add git auth in dockerfile to build image with private repo dependency
cll-gg Sep 1, 2025
0f5832b
Merge branch 'develop' into sm-run-in-local-cre-dev-env
cll-gg Sep 1, 2025
f8ab7dc
Remove erroneous copy
cll-gg Sep 1, 2025
fceb4b1
Run make tidy
cll-gg Sep 1, 2025
ccae9cd
Fix values package move
cll-gg Sep 1, 2025
4fc1006
Add todo
cll-gg Sep 4, 2025
9dff5e1
Cursor implements todo
cll-gg Sep 4, 2025
fa8cab2
In the test, check the sm report contents
cll-gg Sep 4, 2025
44c691c
Use temporary repo to run sm plugin as loopp
cll-gg Sep 1, 2025
57d9faa
Only start up the plugin as a loopp
cll-gg Sep 2, 2025
95bfacd
Use the config
cll-gg Sep 2, 2025
8a2a036
Update package
cll-gg Sep 4, 2025
a7e97dc
Pass in external adapter
cll-gg Sep 4, 2025
aa77111
Remove unused code
cll-gg Sep 4, 2025
825d52b
Rename and fix todo
cll-gg Sep 5, 2025
5d8fe48
Remove dependency on tmp-sm-plugin-loopp and depend on cl-common instead
cll-gg Sep 8, 2025
92f457b
Update readme
cll-gg Sep 8, 2025
c900d02
Add todo
cll-gg Sep 8, 2025
4a99d47
Update references after package move
cll-gg Sep 8, 2025
91281a5
Fix todo: wrap plugin factory in prom wrapper
cll-gg Sep 9, 2025
c969709
Use cl-common 33154edc7a38 (latest of https://github.com/smartcontrac…
cll-gg Sep 9, 2025
9266727
Merge branch 'develop' into sm-run-in-local-cre-dev-env
cll-gg Sep 9, 2025
717069d
Don't update to go-plugin 1.7
cll-gg Sep 9, 2025
28f12c9
Remove hack
cll-gg Sep 9, 2025
aa2b058
Clean up PR
cll-gg Sep 9, 2025
00aef42
Fix todos and update Readme
cll-gg Sep 10, 2025
9f305a7
Update to correct and latest cl-common version
cll-gg Sep 10, 2025
13cfda9
Update to use plugin version `0a9a82fddc0e`
cll-gg Sep 10, 2025
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
19 changes: 10 additions & 9 deletions core/config/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,16 @@ var (

// LOOPP commands and vars
var (
MedianPlugin = NewPlugin("median")
MercuryPlugin = NewPlugin("mercury")
AptosPlugin = NewPlugin("aptos")
EVMPlugin = NewPlugin("evm")
CosmosPlugin = NewPlugin("cosmos")
SolanaPlugin = NewPlugin("solana")
StarknetPlugin = NewPlugin("starknet")
TronPlugin = NewPlugin("tron")
TONPlugin = NewPlugin("ton")
MedianPlugin = NewPlugin("median")
MercuryPlugin = NewPlugin("mercury")
AptosPlugin = NewPlugin("aptos")
EVMPlugin = NewPlugin("evm")
CosmosPlugin = NewPlugin("cosmos")
SolanaPlugin = NewPlugin("solana")
StarknetPlugin = NewPlugin("starknet")
TronPlugin = NewPlugin("tron")
TONPlugin = NewPlugin("ton")
SecureMintPlugin = NewPlugin("securemint")
// PrometheusDiscoveryHostName is the externally accessible hostname
// published by the node in the `/discovery` endpoint. Generally, it is expected to match
// the public hostname of node.
Expand Down
4 changes: 2 additions & 2 deletions core/scripts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,12 @@ require (
github.com/shopspring/decimal v1.4.0
github.com/smartcontractkit/chainlink-automation v0.8.1
github.com/smartcontractkit/chainlink-ccip v0.1.1-solana.0.20250825135846-84f0d5167f8f
github.com/smartcontractkit/chainlink-common v0.9.5-0.20250908082700-aa3f5927af8c
github.com/smartcontractkit/chainlink-common v0.9.5-0.20250909120425-33154edc7a38
github.com/smartcontractkit/chainlink-data-streams v0.1.2
github.com/smartcontractkit/chainlink-deployments-framework v0.42.0
github.com/smartcontractkit/chainlink-evm v0.3.3-0.20250903140346-aacd485a7dea
github.com/smartcontractkit/chainlink-evm/gethwrappers v0.0.0-20250827130336-5922343458be
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250829155125-f4655b0b4605
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250905211734-167560f092c1
github.com/smartcontractkit/chainlink-protos/job-distributor v0.13.1
github.com/smartcontractkit/chainlink-testing-framework/framework v0.10.17
github.com/smartcontractkit/chainlink-testing-framework/framework/components/dockercompose v0.1.13
Expand Down
8 changes: 4 additions & 4 deletions core/scripts/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1538,8 +1538,8 @@ github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7
github.com/smartcontractkit/chainlink-ccip/chains/solana v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:Ve1xD71bl193YIZQEoJMmBqLGQJdNs29bwbuObwvbhQ=
github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a h1:38dAlTPRUQHZus5dCnBnQyf/V4oYn0p2svWlbPgHDQ4=
github.com/smartcontractkit/chainlink-ccip/chains/solana/gobindings v0.0.0-20250805210128-7f8a0f403c3a/go.mod h1:xtZNi6pOKdC3sLvokDvXOhgHzT+cyBqH/gWwvxTxqrg=
github.com/smartcontractkit/chainlink-common v0.9.5-0.20250908082700-aa3f5927af8c h1:2cnAGt0nedGS/M0deXRCIJVsxTWi6CzYPXkTxqVwViY=
github.com/smartcontractkit/chainlink-common v0.9.5-0.20250908082700-aa3f5927af8c/go.mod h1:b5KI42+P0ZmUXuvOFzSH9uIB8K83wvXq1GNVoY+ePeg=
github.com/smartcontractkit/chainlink-common v0.9.5-0.20250909120425-33154edc7a38 h1:dCvWsUaZsEkX6iH6CwsmtDORH6rHoAHQ9Vi0H/Zb444=
github.com/smartcontractkit/chainlink-common v0.9.5-0.20250909120425-33154edc7a38/go.mod h1:1diMLMwfIACeqJFt7ySGaBrJIeUwHTLhVVYlb41EyKk=
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.1 h1:ca2z5OXgnbBPQRxpwXwBLJsUA1+cAp5ncfW4Ssvd6eY=
github.com/smartcontractkit/chainlink-common/pkg/chipingress v0.0.1/go.mod h1:NZv/qKYGFRnkjOYBouajnDfFoZ+WDa6H2KNmSf1dnKc=
github.com/smartcontractkit/chainlink-common/pkg/monitoring v0.0.0-20250415235644-8703639403c7 h1:9wh1G+WbXwPVqf0cfSRSgwIcaXTQgvYezylEAfwmrbw=
Expand All @@ -1564,8 +1564,8 @@ github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250729142306-
github.com/smartcontractkit/chainlink-framework/multinode v0.0.0-20250729142306-508e798f6a5d/go.mod h1:2JTBNp3FlRdO/nHc4dsc9bfxxMClMO1Qt8sLJgtreBY=
github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250722225531-876fd6b94976 h1:mF3FiDUoV0QbJcks9R2y7ydqntNL1Z0VCPBJgx/Ms+0=
github.com/smartcontractkit/chainlink-protos/billing/go v0.0.0-20250722225531-876fd6b94976/go.mod h1:HHGeDUpAsPa0pmOx7wrByCitjQ0mbUxf0R9v+g67uCA=
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250829155125-f4655b0b4605 h1:yVH5tLDzW2ZBUpmkHF5nci1SRSXTcU3A1VZ8iS5qudA=
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250829155125-f4655b0b4605/go.mod h1:jUC52kZzEnWF9tddHh85zolKybmLpbQ1oNA4FjOHt1Q=
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250905211734-167560f092c1 h1:HZt/80mhcNw6/MlYBIRracxfHWNqFF0iZ5nZEVZBUgo=
github.com/smartcontractkit/chainlink-protos/cre/go v0.0.0-20250905211734-167560f092c1/go.mod h1:jUC52kZzEnWF9tddHh85zolKybmLpbQ1oNA4FjOHt1Q=
github.com/smartcontractkit/chainlink-protos/job-distributor v0.13.1 h1:PWwLGimBt37eDzpbfZ9V/ZkW4oCjcwKjKiAwKlSfPc0=
github.com/smartcontractkit/chainlink-protos/job-distributor v0.13.1/go.mod h1:/dVVLXrsp+V0AbcYGJo3XMzKg3CkELsweA/TTopCsKE=
github.com/smartcontractkit/chainlink-protos/orchestrator v0.10.0 h1:0eroOyBwmdoGUwUdvMI0/J7m5wuzNnJDMglSOK1sfNY=
Expand Down
4 changes: 2 additions & 2 deletions core/services/job/orm.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ func (o *orm) AssertBridgesExist(ctx context.Context, p pipeline.Pipeline) error
return nil
}

// CreateJob creates the job, and it's associated spec record.
// CreateJob creates the job, and its associated spec record.
// Expects an unmarshalled job spec as the jb argument i.e. output from ValidatedXX.
// Scans all persisted records back into jb
func (o *orm) CreateJob(ctx context.Context, jb *Job) error {
Expand Down Expand Up @@ -647,7 +647,7 @@ func (o *orm) insertGatewaySpec(ctx context.Context, spec *GatewaySpec) (specID
// ValidateKeyStoreMatch confirms that the key has a valid match in the keystore
func ValidateKeyStoreMatch(ctx context.Context, spec *OCR2OracleSpec, keyStore keystore.Master, key string) (err error) {
switch spec.PluginType {
case types.Mercury, types.LLO:
case types.Mercury, types.LLO, types.SecureMint:
_, err = keyStore.CSA().Get(key)
if err != nil {
err = errors.Errorf("no CSA key matching: %q", key)
Expand Down
53 changes: 53 additions & 0 deletions core/services/ocr2/delegate.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/smartcontractkit/chainlink-common/pkg/types"
cciptypes "github.com/smartcontractkit/chainlink-common/pkg/types/ccip"
"github.com/smartcontractkit/chainlink-common/pkg/types/core"
sm "github.com/smartcontractkit/chainlink-common/pkg/types/core/securemint"
llotypes "github.com/smartcontractkit/chainlink-common/pkg/types/llo"
"github.com/smartcontractkit/chainlink-common/pkg/utils/mailbox"
"github.com/smartcontractkit/chainlink-common/pkg/workflows/dontime"
Expand Down Expand Up @@ -79,6 +80,8 @@ import (
ocr2keeper21core "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/core"
vaultocrplugin "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/vault"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/validate"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr3/securemint"
sm_adapter "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/securemint/keyringadapter"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"
Expand Down Expand Up @@ -579,6 +582,8 @@ func (d *Delegate) ServicesForSpec(ctx context.Context, jb job.Job) ([]job.Servi

case types.DonTimePlugin:
return d.newDonTimePlugin(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc)
case types.SecureMint:
return d.newServicesSecureMint(ctx, lggr, jb, bootstrapPeers, kb, ocrDB, lc)

default:
return nil, errors.Errorf("plugin type %s not supported", spec.PluginType)
Expand Down Expand Up @@ -1498,6 +1503,54 @@ func (d *Delegate) newServicesMedian(
return medianServices, err2
}

func (d *Delegate) newServicesSecureMint(
ctx context.Context,
lggr logger.SugaredLogger,
jb job.Job,
bootstrapPeers []commontypes.BootstrapperLocator,
kb ocr2key.KeyBundle,
ocrDB *db,
lc ocrtypes.LocalConfig,
) ([]job.ServiceCtx, error) {
spec := jb.OCR2OracleSpec
rid, err := spec.RelayID()
if err != nil {
return nil, ErrJobSpecNoRelayer{Err: err, PluginName: "securemint"}
}

ocrLogger := ocrcommon.NewOCRWrapper(lggr, d.cfg.OCR2().TraceLogging(), func(ctx context.Context, msg string) {
lggr.ErrorIf(d.jobORM.RecordError(ctx, jb.ID, msg), "unable to record error")
})

oracleArgsNoPlugin := libocr2.OCR3OracleArgs[sm.ChainSelector]{
BinaryNetworkEndpointFactory: d.peerWrapper.Peer2,
V2Bootstrappers: bootstrapPeers,
Database: ocrDB,
LocalConfig: lc,
Logger: ocrLogger,
MonitoringEndpoint: d.monitoringEndpointGen.GenMonitoringEndpoint(rid.Network, rid.ChainID, spec.ContractID, synchronization.OCR2Median),
OffchainKeyring: kb,
OnchainKeyring: sm_adapter.NewSecureMintOCR3OnchainKeyringAdapter(kb),
MetricsRegisterer: prometheus.WrapRegistererWith(map[string]string{"job_name": jb.Name.ValueOrZero()}, prometheus.DefaultRegisterer),
}

smConfig := securemint.NewJobConfig(
d.cfg.JobPipeline().MaxSuccessfulRuns(),
d.cfg.JobPipeline().ResultWriteQueueDepth(),
d.cfg,
)

relayer, err := d.RelayGetter.Get(rid)
if err != nil {
return nil, ErrRelayNotEnabled{Err: err, PluginName: "securemint", Relay: spec.Relay}
}

secureMintServices, err := securemint.NewSecureMintServices(ctx, jb, d.isNewlyCreatedJob, relayer, d.pipelineRunner, lggr, oracleArgsNoPlugin, smConfig, d.capabilitiesRegistry)
secureMintServices = append(secureMintServices, ocrLogger)

return secureMintServices, err
}

func (d *Delegate) newServicesOCR2Keepers(
ctx context.Context,
lggr logger.SugaredLogger,
Expand Down
23 changes: 21 additions & 2 deletions core/services/ocr2/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import (
"github.com/pelletier/go-toml"
pkgerrors "github.com/pkg/errors"

libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"

"github.com/smartcontractkit/chainlink-common/pkg/logger"
"github.com/smartcontractkit/chainlink-common/pkg/loop/reportingplugins"
"github.com/smartcontractkit/chainlink-common/pkg/types"
Expand All @@ -25,11 +23,13 @@ import (
lloconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/llo/config"
mercuryconfig "github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/mercury/config"
"github.com/smartcontractkit/chainlink/v2/core/services/ocr2/plugins/vault"
sm_config "github.com/smartcontractkit/chainlink/v2/core/services/ocr3/securemint/config"
"github.com/smartcontractkit/chainlink/v2/core/services/ocrcommon"
"github.com/smartcontractkit/chainlink/v2/core/services/pipeline"
"github.com/smartcontractkit/chainlink/v2/core/services/relay"
evmtypes "github.com/smartcontractkit/chainlink/v2/core/services/relay/evm/types"
"github.com/smartcontractkit/chainlink/v2/plugins"
libocr2 "github.com/smartcontractkit/libocr/offchainreporting2plus"
)

// ValidatedOracleSpecToml validates an oracle spec that came from TOML
Expand Down Expand Up @@ -132,6 +132,8 @@ func validateSpec(ctx context.Context, tree *toml.Tree, spec job.Job, rc plugins
return validateVaultPluginSpec(spec.OCR2OracleSpec.PluginConfig)
case types.DonTimePlugin:
return validateDonTimePluginSpec(spec.OCR2OracleSpec.PluginConfig)
case types.SecureMint:
return validateSecureMintSpec(spec.OCR2OracleSpec.PluginConfig)
case "":
return errors.New("no plugin specified")
default:
Expand Down Expand Up @@ -405,3 +407,20 @@ func validateOCR2LLOSpec(jsonConfig job.JSONConfig) error {
}
return pkgerrors.Wrap(pluginConfig.Validate(), "LLO PluginConfig is invalid")
}

func validateSecureMintSpec(jsonConfig job.JSONConfig) error {
if jsonConfig == nil {
return errors.New("secure mint plugin config is empty")
}

smConfig, err := sm_config.Parse(jsonConfig.Bytes())
if err != nil {
return pkgerrors.Wrap(err, "error while parsing secure mint plugin config")
}

if err := smConfig.Validate(); err != nil {
return fmt.Errorf("invalid secure mint plugin config: %#v, err: %w", smConfig, err)
}

return nil
}
117 changes: 117 additions & 0 deletions core/services/ocr3/securemint/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# SecureMint Plugin

## Overview

The SecureMint plugin is a plugin that allows for secure minting of tokens.
It's looppified, its implementation can be found in https://github.com/smartcontractkit/chainlink-secure-mint/.
Make sure to install the plugin before running the integration test.

### Secure mint plugin version

The current code works with [v0.1 of the secure mint plugin](https://github.com/smartcontractkit/chainlink-secure-mint/commit/548f7e4753a11b2bcd69f53345ca6a0d696dff9d).

## Validation

Validating whether the SecureMint plugin is working as expected is done by running the integration test.

The test is located in the `core/services/ocr3/securemint` directory.

### Prerequisites:
```bash
docker run --name cl-postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=dbname -p 5432:5432 -d postgres
make setup-testdb
```

### Run test:
```bash
time CL_SECUREMINT_CMD=chainlink-secure-mint CL_DATABASE_URL=postgresql://chainlink_dev:insecurepassword@localhost:5432/chainlink_development_test?sslmode=disable go test -timeout 2m -run ^TestIntegration_SecureMint_happy_path$ github.com/smartcontractkit/chainlink/v2/core/services/ocr3/securemint -v 2>&1 | tee all.log | awk '/DEBUG|INFO|WARN|ERROR/ { print > "node_logs.log"; next }; { print > "other.log" }; tail all.log'
```

### If you change any dependencies:
```bash
go mod tidy && go mod vendor && modvendor -copy="**/*.a **/*.h" -v
```

(the `modvendor` step might not be necessary, but for me it was (see also https://github.com/marcboeker/go-duckdb/issues/174#issuecomment-1979097864))

### Logs

* other.log: Contains all non-node output from the test run, this can be used to quickly see test failures
* node_logs.log: Contains all logs from the nodes started up in the test run, this can be used to see the full output of the test run
* all.log: Contains the complete output of the test run, this can be used to see test failures within the context of the node logs


### Debug test with VSCode:

Create a launch.json file in the .vscode directory with the following content:

```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Secure Mint Integration Test",
"type": "go",
"request": "launch",
"mode": "test",
"program": "${workspaceFolder}/core/services/ocr3/securemint/integrationtest",
"args": [
"-test.run",
"^TestIntegration_SecureMint_happy_path$",
"-test.v",
"-test.timeout",
"2m",
"2>&1",
"|",
"tee",
"all.log",
"|",
"awk '/DEBUG|INFO|WARN|ERROR/ { print > 'node_logs.log'; next }; { print > 'other.log' }'",
],
"env": {
"ENV": "test",
"CL_DATABASE_URL": "postgresql://chainlink_dev:insecurepassword@localhost:5432/chainlink_development_test?sslmode=disable",
"CL_SECUREMINT_CMD": "chainlink-secure-mint",
}
}
]
}
```

Then run the test by Cmd+P: "Start Debugging".

## Hacks


### XXX_SingletonTransmitter

This is a hack to allow the `TestIntegration_SecureMint_happy_path` integration test to assess whether secure mint reports are being transmitted as a trigger to a Workflow.

It gives the integration test access to the SecureMint transmitter, which is used to assert on the number of transmissions.


## Secure Mint Workflow

The Secure Mint plugin's reports are triggers for a CRE Workflow.

The secure mint workflow, and specifically the securemint aggregator (see `chainlink-common/pkg/capabilities/consensus/ocr3/datafeeds/securemint_aggregator.go`) are tested in `core/capabilities/integration_tests/keystone/securemint_workflow_test.go`.

You can run the `Test_runSecureMintWorkflow` test as follows:
```bash
time CL_DATABASE_URL=postgresql://chainlink_dev:insecurepassword@localhost:5432/chainlink_development_test?sslmode=disable go test -timeout 2m -run ^Test_runSecureMintWorkflow$ github.com/smartcontractkit/chainlink/v2/core/capabilities/integration_tests/keystone -v 2>&1 | tee all.log | awk '/DEBUG|INFO|WARN|ERROR/ { print > "node_logs.log"; next }; { print > "other.log" }'; tail all.log
```

### Layers of abstraction in sending a Workflow trigger

When sending a Workflow trigger, the SecureMint report is wrapped in several layers of abstraction.

From top to bottom:

The secure mint transmitter sends a:
- `capabilities.TriggerResponse{Event: capabilities.TriggerEvent, Err}`, which contains a:
- `capabilities.TriggerEvent{TriggerType: 0, ID: "securemint-trigger", Outputs: values.Map, Payload: nil}`, which contains:
- `values.Map{"sigs": signatures, "configDigest": cfgDigest, "seqNr": seqNr, "report": <ocr3types.ReportWithInfo>}`, which contains a
- `ocr3types.ReportWithInfo{Report: json-marshaled PorReport, Info: chainSelector}`, which contains a
- `securemint.Report{ConfigDigest, SeqNr, Block, Mintable}`, which:

is created by the secure mint plugin.
57 changes: 57 additions & 0 deletions core/services/ocr3/securemint/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package config

import (
"encoding/json"

"github.com/pkg/errors"
)

// SecureMintConfig holds secure mint specific configuration
type SecureMintConfig struct {
Token string `json:"token"`
Reserves string `json:"reserves"`
ChainSelectors []string `json:"chainSelectors"`

// Trigger capability configuration
TriggerCapabilityName string `json:"triggerCapabilityName"`
TriggerCapabilityVersion string `json:"triggerCapabilityVersion"`
TriggerTickerMinResolutionMs int `json:"triggerTickerMinResolutionMs"`
TriggerSendChannelBufferSize int `json:"triggerSendChannelBufferSize"`
}

// SecureMintTriggerConfig holds configuration for secure mint trigger subscribers
type SecureMintTriggerConfig struct {
// The interval in milliseconds after which a new trigger event is generated.
MaxFrequencyMs uint64 `json:"maxFrequencyMs" yaml:"maxFrequencyMs" mapstructure:"maxFrequencyMs"`
}

// Parse parses the secure mint configuration from JSON bytes
func Parse(configBytes []byte) (*SecureMintConfig, error) {
if len(configBytes) == 0 {
return nil, errors.New("secure mint config cannot be empty")
}

var config SecureMintConfig
if err := json.Unmarshal(configBytes, &config); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal SecureMintConfig")
}

return &config, nil
}

// Validate validates the secure mint plugin-specific config.
func (cfg *SecureMintConfig) Validate() error {
if cfg == nil {
return errors.New("secure mint plugin config cannot be nil")
}

if cfg.Token == "" {
return errors.New("token cannot be empty")
}

if cfg.Reserves == "" {
return errors.New("reserves cannot be empty")
}

return nil
}
Loading