forked from decenterplace/chainlink
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement networking V2 for libocr (smartcontractkit#4597)
- Loading branch information
Showing
13 changed files
with
476 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
package offchainreporting | ||
|
||
import ( | ||
"context" | ||
"database/sql" | ||
|
||
"github.com/lib/pq" | ||
p2ppeer "github.com/libp2p/go-libp2p-core/peer" | ||
"github.com/pkg/errors" | ||
ocrnetworking "github.com/smartcontractkit/libocr/networking" | ||
"go.uber.org/multierr" | ||
) | ||
|
||
var _ ocrnetworking.DiscovererDatabase = &DiscovererDatabase{} | ||
|
||
type DiscovererDatabase struct { | ||
db *sql.DB | ||
peerID string | ||
} | ||
|
||
func NewDiscovererDatabase(db *sql.DB, peerID p2ppeer.ID) *DiscovererDatabase { | ||
return &DiscovererDatabase{ | ||
db, | ||
peerID.Pretty(), | ||
} | ||
} | ||
|
||
// StoreAnnouncement has key-value-store semantics and stores a peerID (key) and an associated serialized | ||
// announcement (value). | ||
func (d *DiscovererDatabase) StoreAnnouncement(ctx context.Context, peerID string, ann []byte) error { | ||
_, err := d.db.ExecContext(ctx, ` | ||
INSERT INTO offchainreporting_discoverer_announcements (local_peer_id, remote_peer_id, ann, created_at, updated_at) | ||
VALUES ($1,$2,$3,NOW(),NOW()) ON CONFLICT (local_peer_id, remote_peer_id) DO UPDATE SET | ||
ann = EXCLUDED.ann, | ||
updated_at = EXCLUDED.updated_at | ||
;`, d.peerID, peerID, ann) | ||
return errors.Wrap(err, "DiscovererDatabase failed to StoreAnnouncement") | ||
} | ||
|
||
// ReadAnnouncements returns one serialized announcement (if available) for each of the peerIDs in the form of a map | ||
// keyed by each announcement's corresponding peer ID. | ||
func (d *DiscovererDatabase) ReadAnnouncements(ctx context.Context, peerIDs []string) (map[string][]byte, error) { | ||
rows, err := d.db.QueryContext(ctx, ` | ||
SELECT remote_peer_id, ann FROM offchainreporting_discoverer_announcements WHERE remote_peer_id = ANY($1) AND local_peer_id = $2`, pq.Array(peerIDs), d.peerID) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "DiscovererDatabase failed to ReadAnnouncements") | ||
} | ||
results := make(map[string][]byte) | ||
for rows.Next() { | ||
var peerID string | ||
var ann []byte | ||
err := rows.Scan(&peerID, &ann) | ||
if err != nil { | ||
return nil, multierr.Combine(err, rows.Close()) | ||
} | ||
results[peerID] = ann | ||
} | ||
if err := rows.Close(); err != nil { | ||
return nil, errors.WithStack(err) | ||
} | ||
return results, nil | ||
} |
83 changes: 83 additions & 0 deletions
83
core/services/offchainreporting/discoverer_database_test.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package offchainreporting_test | ||
|
||
import ( | ||
"testing" | ||
|
||
"github.com/smartcontractkit/chainlink/core/internal/cltest" | ||
"github.com/smartcontractkit/chainlink/core/services/offchainreporting" | ||
"github.com/stretchr/testify/assert" | ||
"github.com/stretchr/testify/require" | ||
) | ||
|
||
func Test_DiscovererDatabase(t *testing.T) { | ||
store, cleanup := cltest.NewStore(t) | ||
defer cleanup() | ||
|
||
db := store.DB | ||
require.NoError(t, db.Exec(`SET CONSTRAINTS offchainreporting_discoverer_announcements_local_peer_id_fkey DEFERRED`).Error) | ||
|
||
sqlDB := store.MustSQLDB() | ||
|
||
localPeerID1 := cltest.MustRandomP2PPeerID(t) | ||
localPeerID2 := cltest.MustRandomP2PPeerID(t) | ||
|
||
dd1 := offchainreporting.NewDiscovererDatabase(sqlDB, localPeerID1) | ||
dd2 := offchainreporting.NewDiscovererDatabase(sqlDB, localPeerID2) | ||
|
||
t.Run("StoreAnnouncement writes a value", func(t *testing.T) { | ||
ann := []byte{1, 2, 3} | ||
err := dd1.StoreAnnouncement(ctx, "remote1", ann) | ||
assert.NoError(t, err) | ||
|
||
// test upsert | ||
ann = []byte{4, 5, 6} | ||
err = dd1.StoreAnnouncement(ctx, "remote1", ann) | ||
assert.NoError(t, err) | ||
|
||
// write a different value | ||
ann = []byte{7, 8, 9} | ||
err = dd1.StoreAnnouncement(ctx, "remote2", ann) | ||
assert.NoError(t, err) | ||
}) | ||
|
||
t.Run("ReadAnnouncements reads values filtered by given peerIDs", func(t *testing.T) { | ||
announcements, err := dd1.ReadAnnouncements(ctx, []string{"remote1", "remote2"}) | ||
require.NoError(t, err) | ||
|
||
assert.Len(t, announcements, 2) | ||
assert.Equal(t, []byte{4, 5, 6}, announcements["remote1"]) | ||
assert.Equal(t, []byte{7, 8, 9}, announcements["remote2"]) | ||
|
||
announcements, err = dd1.ReadAnnouncements(ctx, []string{"remote1"}) | ||
require.NoError(t, err) | ||
|
||
assert.Len(t, announcements, 1) | ||
assert.Equal(t, []byte{4, 5, 6}, announcements["remote1"]) | ||
}) | ||
|
||
t.Run("is scoped to local peer ID", func(t *testing.T) { | ||
ann := []byte{10, 11, 12} | ||
err := dd2.StoreAnnouncement(ctx, "remote1", ann) | ||
assert.NoError(t, err) | ||
|
||
announcements, err := dd2.ReadAnnouncements(ctx, []string{"remote1"}) | ||
require.NoError(t, err) | ||
assert.Len(t, announcements, 1) | ||
assert.Equal(t, []byte{10, 11, 12}, announcements["remote1"]) | ||
|
||
announcements, err = dd1.ReadAnnouncements(ctx, []string{"remote1"}) | ||
require.NoError(t, err) | ||
assert.Len(t, announcements, 1) | ||
assert.Equal(t, []byte{4, 5, 6}, announcements["remote1"]) | ||
}) | ||
|
||
t.Run("persists data across restarts", func(t *testing.T) { | ||
dd3 := offchainreporting.NewDiscovererDatabase(sqlDB, localPeerID1) | ||
|
||
announcements, err := dd3.ReadAnnouncements(ctx, []string{"remote1"}) | ||
require.NoError(t, err) | ||
assert.Len(t, announcements, 1) | ||
assert.Equal(t, []byte{4, 5, 6}, announcements["remote1"]) | ||
|
||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
31 changes: 31 additions & 0 deletions
31
core/store/migrations/0044_create_table_ocr_discoverer_database.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package migrations | ||
|
||
import ( | ||
"gorm.io/gorm" | ||
) | ||
|
||
const up44 = ` | ||
CREATE TABLE offchainreporting_discoverer_announcements ( | ||
local_peer_id text NOT NULL REFERENCES encrypted_p2p_keys (peer_id) DEFERRABLE INITIALLY IMMEDIATE, | ||
remote_peer_id text NOT NULL, | ||
ann bytea NOT NULL, | ||
created_at timestamptz not null, | ||
updated_at timestamptz not null, | ||
PRIMARY KEY(local_peer_id, remote_peer_id) | ||
); | ||
` | ||
const down44 = ` | ||
DROP TABLE offchainreporting_discoverer_announcements; | ||
` | ||
|
||
func init() { | ||
Migrations = append(Migrations, &Migration{ | ||
ID: "0044_create_table_offchainreporting_discoverer_announcements", | ||
Migrate: func(db *gorm.DB) error { | ||
return db.Exec(up44).Error | ||
}, | ||
Rollback: func(db *gorm.DB) error { | ||
return db.Exec(down44).Error | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.