Skip to content

Commit

Permalink
event visibility config part 2 (#2057)
Browse files Browse the repository at this point in the history
* event visibility config part 2

* add event_type column and comments

* fixing autodetect visibility logic

* fix debug endpoint

* fix bug

* clarify naming
  • Loading branch information
tudor-malene committed Sep 18, 2024
1 parent 0bb1220 commit 3e8c21f
Show file tree
Hide file tree
Showing 7 changed files with 260 additions and 149 deletions.
3 changes: 0 additions & 3 deletions go/common/tracers/debug_logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ type DebugLogs struct {
RelAddress1 *gethcommon.Address `json:"relAddress1"`
RelAddress2 *gethcommon.Address `json:"relAddress2"`
RelAddress3 *gethcommon.Address `json:"relAddress3"`
RelAddress4 *gethcommon.Address `json:"relAddress4"`
LifecycleEvent bool `json:"lifecycleEvent"`

gethtypes.Log
Expand All @@ -37,7 +36,6 @@ func (l DebugLogs) MarshalJSON() ([]byte, error) {
RelAddress1 *gethcommon.Address `json:"relAddress1"`
RelAddress2 *gethcommon.Address `json:"relAddress2"`
RelAddress3 *gethcommon.Address `json:"relAddress3"`
RelAddress4 *gethcommon.Address `json:"relAddress4"`
}{
l.Address.Hex(),
l.Topics,
Expand All @@ -52,6 +50,5 @@ func (l DebugLogs) MarshalJSON() ([]byte, error) {
l.RelAddress1,
l.RelAddress2,
l.RelAddress3,
l.RelAddress4,
})
}
7 changes: 6 additions & 1 deletion go/enclave/core/event_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import (
"github.com/ethereum/go-ethereum/core/types"
)

// EventVisibilityConfig - configuration per event by the dApp developer
// EventVisibilityConfig - configuration per event by the dApp developer(DD)
// There are 4 cases:
// 1. DD doesn't configure anything. - ContractVisibilityConfig.AutoConfig=true
// 2. DD configures and specifies the contract as transparent - ContractVisibilityConfig.Transparent=true
// 3. DD configures and specify the contract as non-transparent, but doesn't configure the event - Contract: false/false , EventVisibilityConfig.AutoConfig=true
// DD configures the contract as non-transparent, and also configures the topics for the event
type EventVisibilityConfig struct {
AutoConfig bool // true for events that have no explicit configuration
Public bool // everyone can see and query for this event
Expand Down
97 changes: 73 additions & 24 deletions go/enclave/storage/enclavedb/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@ const (
" join batch b on rec.batch=b.sequence " +
"join event_type et on e.event_type=et.id " +
" join contract c on et.contract=c.id " +
"left join event_topic t1 on e.topic1=t1.id " +
"left join event_topic t1 on e.topic1=t1.id and et.id=t1.event_type " +
" left join externally_owned_account eoa1 on t1.rel_address=eoa1.id " +
"left join event_topic t2 on e.topic2=t2.id " +
"left join event_topic t2 on e.topic2=t2.id and et.id=t2.event_type " +
" left join externally_owned_account eoa2 on t2.rel_address=eoa2.id " +
"left join event_topic t3 on e.topic3=t3.id" +
"left join event_topic t3 on e.topic3=t3.id and et.id=t1.event_type " +
" left join externally_owned_account eoa3 on t3.rel_address=eoa3.id " +
"where b.is_canonical=true "
)

func WriteEventType(ctx context.Context, dbTX *sql.Tx, et *EventType) (uint64, error) {
res, err := dbTX.ExecContext(ctx, "insert into event_type (contract, event_sig, auto_visibility, public, topic1_can_view, topic2_can_view, topic3_can_view, sender_can_view) values (?, ?, ?, ?, ?, ?, ?, ?)",
et.ContractId, et.EventSignature.Bytes(), et.AutoVisibility, et.Public, et.Topic1CanView, et.Topic2CanView, et.Topic3CanView, et.SenderCanView)
res, err := dbTX.ExecContext(ctx, "insert into event_type (contract, event_sig, auto_visibility,auto_public, config_public, topic1_can_view, topic2_can_view, topic3_can_view, sender_can_view) values (?, ?, ?, ?, ?, ?, ?, ?, ?)",
et.Contract.Id, et.EventSignature.Bytes(), et.AutoVisibility, et.AutoPublic, et.ConfigPublic, et.Topic1CanView, et.Topic2CanView, et.Topic3CanView, et.SenderCanView)
if err != nil {
return 0, err
}
Expand All @@ -47,19 +47,21 @@ func WriteEventType(ctx context.Context, dbTX *sql.Tx, et *EventType) (uint64, e
return uint64(id), nil
}

func ReadEventType(ctx context.Context, dbTX *sql.Tx, contractId uint64, eventSignature gethcommon.Hash) (*EventType, error) {
var et EventType
err := dbTX.QueryRowContext(ctx, "select id, contract, event_sig, auto_visibility, public, topic1_can_view, topic2_can_view, topic3_can_view, sender_can_view from event_type where contract=? and event_sig=?",
contractId, eventSignature.Bytes()).Scan(&et.Id, &et.ContractId, &et.EventSignature, &et.AutoVisibility, &et.Public, &et.Topic1CanView, &et.Topic2CanView, &et.Topic3CanView, &et.SenderCanView)
func ReadEventType(ctx context.Context, dbTX *sql.Tx, contract *Contract, eventSignature gethcommon.Hash) (*EventType, error) {
var et EventType = EventType{Contract: contract}
err := dbTX.QueryRowContext(ctx,
"select id, event_sig, auto_visibility, auto_public, config_public, topic1_can_view, topic2_can_view, topic3_can_view, sender_can_view from event_type where contract=? and event_sig=?",
contract.Id, eventSignature.Bytes(),
).Scan(&et.Id, &et.EventSignature, &et.AutoVisibility, &et.AutoPublic, &et.ConfigPublic, &et.Topic1CanView, &et.Topic2CanView, &et.Topic3CanView, &et.SenderCanView)
if errors.Is(err, sql.ErrNoRows) {
// make sure the error is converted to obscuro-wide not found error
return nil, errutil.ErrNotFound
}
return &et, err
}

func WriteEventTopic(ctx context.Context, dbTX *sql.Tx, topic *gethcommon.Hash, addressId *uint64) (uint64, error) {
res, err := dbTX.ExecContext(ctx, "insert into event_topic (topic, rel_address) values (?, ?)", topic.Bytes(), addressId)
func WriteEventTopic(ctx context.Context, dbTX *sql.Tx, topic *gethcommon.Hash, addressId *uint64, eventTypeId uint64) (uint64, error) {
res, err := dbTX.ExecContext(ctx, "insert into event_topic (event_type, topic, rel_address) values (?, ?, ?)", eventTypeId, topic.Bytes(), addressId)
if err != nil {
return 0, err
}
Expand All @@ -70,22 +72,34 @@ func WriteEventTopic(ctx context.Context, dbTX *sql.Tx, topic *gethcommon.Hash,
return uint64(id), nil
}

func UpdateEventTypeLifecycle(ctx context.Context, dbTx *sql.Tx, etId uint64, isLifecycle bool) error {
_, err := dbTx.ExecContext(ctx, "update event_type set public=? where id=?", isLifecycle, etId)
func UpdateEventTypeAutoPublic(ctx context.Context, dbTx *sql.Tx, etId uint64, isPublic bool) error {
_, err := dbTx.ExecContext(ctx, "update event_type set auto_public=? where id=?", isPublic, etId)
return err
}

func ReadEventTopic(ctx context.Context, dbTX *sql.Tx, topic []byte) (uint64, *uint64, error) {
func ReadEventTopic(ctx context.Context, dbTX *sql.Tx, topic []byte, eventTypeId uint64) (uint64, *uint64, error) {
var id uint64
var address *uint64
err := dbTX.QueryRowContext(ctx, "select id, rel_address from event_topic where topic=? ", topic).Scan(&id, &address)
err := dbTX.QueryRowContext(ctx,
"select id, rel_address from event_topic where topic=? and event_type=?", topic, eventTypeId).Scan(&id, &address)
if errors.Is(err, sql.ErrNoRows) {
// make sure the error is converted to obscuro-wide not found error
return 0, nil, errutil.ErrNotFound
}
return id, address, err
}

func ReadRelevantAddressFromEventTopic(ctx context.Context, dbTX *sql.Tx, id uint64) (*uint64, error) {
var address *uint64
err := dbTX.QueryRowContext(ctx,
"select rel_address from event_topic where id=?", id).Scan(&address)
if errors.Is(err, sql.ErrNoRows) {
// make sure the error is converted to obscuro-wide not found error
return nil, errutil.ErrNotFound
}
return address, err
}

func WriteEventLog(ctx context.Context, dbTX *sql.Tx, eventTypeId uint64, userTopics []*uint64, data []byte, logIdx uint, execTx uint64) error {
_, err := dbTX.ExecContext(ctx, "insert into event_log (event_type, topic1, topic2, topic3, datablob, log_idx, receipt) values (?,?,?,?,?,?,?)",
eventTypeId, userTopics[0], userTopics[1], userTopics[2], data, logIdx, execTx)
Expand Down Expand Up @@ -148,7 +162,8 @@ func FilterLogs(
func DebugGetLogs(ctx context.Context, db *sql.DB, txHash common.TxHash) ([]*tracers.DebugLogs, error) {
var queryParams []any

query := "select eoa1.address, eoa2.address, eoa3.address, et.public, et.event_sig, t1.topic, t2.topic, t3.topic, datablob, b.hash, b.height, tx.hash, tx.idx, log_idx, c.address " +
// todo - should we return the config here?
query := "select eoa1.address, eoa2.address, eoa3.address, et.config_public, et.auto_public, et.event_sig, t1.topic, t2.topic, t3.topic, datablob, b.hash, b.height, tx.hash, tx.idx, log_idx, c.address " +
baseEventsJoin +
" AND tx.hash = ? "

Expand All @@ -172,11 +187,13 @@ func DebugGetLogs(ctx context.Context, db *sql.DB, txHash common.TxHash) ([]*tra

var t0, t1, t2, t3 sql.NullString
var relAddress1, relAddress2, relAddress3 []byte
var config_public, autoPublic bool
err = rows.Scan(
&relAddress1,
&relAddress2,
&relAddress3,
&l.LifecycleEvent,
&config_public,
&autoPublic,
&t0, &t1, &t2, &t3,
&l.Data,
&l.BlockHash,
Expand All @@ -186,6 +203,7 @@ func DebugGetLogs(ctx context.Context, db *sql.DB, txHash common.TxHash) ([]*tra
&l.Index,
&l.Address,
)
l.LifecycleEvent = config_public || autoPublic
if err != nil {
return nil, fmt.Errorf("could not load log entry from db: %w", err)
}
Expand Down Expand Up @@ -229,13 +247,11 @@ func loadLogs(ctx context.Context, db *sql.DB, requestingAccount *gethcommon.Add
query := "select et.event_sig, t1.topic, t2.topic, t3.topic, datablob, b.hash, b.height, tx.hash, tx.idx, log_idx, c.address" + " " + baseEventsJoin
var queryParams []any

// Add relevancy rules
// An event is considered relevant to all account owners whose addresses are used as topics in the event.
// In case there are no account addresses in an event's topics, then the event is considered relevant to everyone (known as a "lifecycle event").
query += " AND (et.public=true OR eoa1.address=? OR eoa2.address=? OR eoa3.address=?) "
queryParams = append(queryParams, requestingAccount.Bytes())
queryParams = append(queryParams, requestingAccount.Bytes())
queryParams = append(queryParams, requestingAccount.Bytes())
// Add visibility rules
visibQuery, visibParams := visibilityQuery(requestingAccount)

query += visibQuery
queryParams = append(queryParams, visibParams...)

query += whereCondition
queryParams = append(queryParams, whereParams...)
Expand Down Expand Up @@ -272,6 +288,39 @@ func loadLogs(ctx context.Context, db *sql.DB, requestingAccount *gethcommon.Add
return result, nil
}

// this function encodes the event log visibility rules
func visibilityQuery(requestingAccount *gethcommon.Address) (string, []any) {
acc := requestingAccount.Bytes()

visibQuery := "AND ("
visibParams := make([]any, 0)

// everyone can query config_public events
visibQuery += " et.config_public=true "

// For event logs that have no explicit configuration, an event is visible be all account owners whose addresses are used in any topic
visibQuery += " OR (et.auto_visibility=true AND (et.auto_public=true OR (eoa1.address=? OR eoa2.address=? OR eoa3.address=?))) "
visibParams = append(visibParams, acc)
visibParams = append(visibParams, acc)
visibParams = append(visibParams, acc)

// Configured events that are not public specify explicitly which event topics are addresses empowered to view that event
visibQuery += " OR (" +
"et.auto_visibility=false AND et.config_public=false AND " +
" (" +
" (et.topic1_can_view AND eoa1.address=?) " +
" OR (et.topic2_can_view AND eoa2.address=?) " +
" OR (et.topic3_can_view AND eoa3.address=?)" +
" )" +
")"
visibParams = append(visibParams, acc)
visibParams = append(visibParams, acc)
visibParams = append(visibParams, acc)

visibQuery += ") "
return visibQuery, visibParams
}

func WriteEoa(ctx context.Context, dbTX *sql.Tx, sender gethcommon.Address) (uint64, error) {
insert := "insert into externally_owned_account (address) values (?)"
res, err := dbTX.ExecContext(ctx, insert, sender.Bytes())
Expand Down
27 changes: 25 additions & 2 deletions go/enclave/storage/enclavedb/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package enclavedb
import (
"context"
"database/sql"
"fmt"

gethcommon "github.com/ethereum/go-ethereum/common"

Expand All @@ -27,13 +28,35 @@ type Contract struct {
Transparent *bool
}

func (contract Contract) IsTransparent() bool {
return contract.Transparent != nil && *contract.Transparent
}

// EventType - maps to the “event_type“ table
type EventType struct {
Id uint64
ContractId uint64
Contract *Contract
EventSignature gethcommon.Hash
AutoVisibility bool
Public bool
AutoPublic *bool // true -when the event is autodetected as public
ConfigPublic bool
Topic1CanView, Topic2CanView, Topic3CanView *bool
SenderCanView *bool
}

func (et EventType) IsPublic() bool {
return (et.Contract.Transparent != nil && *et.Contract.Transparent) || et.ConfigPublic
}

func (et EventType) IsTopicRelevant(topicNo int) bool {
switch topicNo {
case 1:
return et.Topic1CanView != nil && *et.Topic1CanView
case 2:
return et.Topic2CanView != nil && *et.Topic2CanView
case 3:
return et.Topic3CanView != nil && *et.Topic3CanView
}
// this should not happen under any circumstance
panic(fmt.Sprintf("unknown topic no: %d", topicNo))
}
Loading

0 comments on commit 3e8c21f

Please sign in to comment.