Мониторинг событий из нескольких контрактов

Я работаю над проектом, который позволяет пользователям автоматически развертывать определенный контракт, который я создал. Для системы важно иметь возможность прослушивать определенные события (например, новую транзакцию) для ВСЕХ развернутых контрактов.

Примечание. Я использую nodejs через web3 json rpc для мониторинга событий.

Одно из возможных решений, о котором я подумал, — использовать контракт-оболочку, который туннелирует все запросы транзакций и отправляет сами события. Это позволит прослушивать только события из одного контракта, но я не нахожу это решение очень элегантным.

Есть ли эффективный и масштабируемый способ добиться этого без создания прослушивателя для каждого конкретного контракта?

Ответы (2)

Похоже, беспокойство вызывает то, что слушатели могут размножаться таким образом, что это может не масштабироваться. Насколько я знаю, нет серебряной пули, которая позволила бы одному слушателю фильтровать события, как вам нужно. Этот третий способ является вариантом двух вариантов, которые, как я понимаю, вы рассматриваете.

Рассмотрите возможность обработки транзакций так, как вы хотите, и добавьте логически централизованные функции ведения журнала. Например, контрактный завод. Организуйте все так, чтобы контракты, созданные на заводе, полагались на функции централизованного ведения журнала, а не на внутренние генераторы событий.

Если у вас есть:

contract Factory { ...
contract Created {
  event LogSomething(bytes32 Id); 
  ...
  LogSomething(Id);

Переставить как

contract Hub {
  event LogSomething(address contract, bytes32 Id);
  ...
  function logSomething(bytes32 Id);
    LogSomething(msg.sender, Id); // msg.sender will be the "spoke" that called Hub function.

contract Created{ 
   ...
   function important(bytes32 id) {
      .. 
      Hub.logSomething(Id);

Factory, вероятно, следует называть Hub в том случае, если он используется не только для заключения контрактов.

Надеюсь, поможет.

Первоначально я думал, что мы хотели бы также отслеживать события, которые генерируются контрактами, которые были развернуты вне системы, но я думаю, что это может быть слишком много и, возможно, даже не нужно. Так что решение, которое вы предлагаете, может действительно работать для нас. Спасибо!
На самом деле, теперь, когда я задумался об этом, это все еще может быть проблемой, потому что это означает, что любой может отправлять события из хаба без разрешения хаба. Одним из способов решения этой проблемы было бы, чтобы хаб вел список контрактов, которым «разрешено» использовать механизм ведения журнала хаба, но я не уверен, что это то, что принято как чистое решение. Это?
Вы правы насчет обеспечения. После дальнейших размышлений я понял, что трудно сказать, должно ли ваше приложение использовать единый контракт, центральную ось или что-то еще. Я склонен согласиться с тем, что когда это становится слишком запутанным, это признак того, что что-то идет не так.
Есть еще один способ рассмотреть. Вы можете использовать обновляемую структуру контракта, которая передает данные через контракт контроллера данных отдельно от логики приложения. Возможность центральной точки входа в там.
Как правило, регистрируйте все изменения состояния в контрактах, а также предоставляйте геттеры и итерируемые структуры данных. Было бы несложно создать систему разрешений, чтобы только потомки могли получить доступ к централизованной функции.
Да, я думал о центральном контракте данных/регистрации, но проблема безопасности кажется еще более сложной для реализации таким образом - если контракт ведения журнала не является также фабрикой контрактов, он даже не может сказать, каким контрактам разрешено использовать его возможности.
Вы можете иметь реестр авторизованных пользователей. Это естественное продолжение фабрики, которая отслеживает созданные контракты. Этот хаб находится довольно близко: ethereum.stackexchange.com/questions/10878/… . Если бы мы хотели, чтобы функция концентратора была доступна только контрактам-потомкам (Persons в примере), мы могли бы иметь модификатор: modifier onlyPerson() { if(persontIndex[personMap[msg.sender]] != msg.sender) throw ; _; // это будет верно, если хаб создал msg.sender. } Надеюсь, это полезно.
Да, это то, что я имел в виду во втором комментарии, так что тогда это кажется законным решением. Большое спасибо!

web3.eth.filter() (низкоуровневый метод, а не тот, который вы можете получить из объектов контракта) позволяет указать список адресов для прослушивания с одним фильтром. Вам придется вручную интерпретировать темы, но это не должно быть слишком сложно.

Отследить момент создания контракта (чтобы вы знали, какие адреса слушать) несколько сложнее. Вы можете использовать тот же метод без указания списка адресов, а затем использовать topicsаргумент, чтобы убедиться, что вы получаете события только из контрактов , претендующих на то, чтобы быть вашими. Различие важно — любой может заставить событие сказать что угодно, поэтому было бы разумно убедиться, что оно исходит из контракта, в котором есть ваш код.

В моем конкретном случае, я думаю, было бы разумно перехватывать только те события, которые генерируются контрактами, созданными через систему, так что это должно упростить задачу. Тем не менее, прослушивание нескольких адресов по-прежнему не очень удобно, так как в конечном итоге это может увеличиться, и тогда у нас снова возникнет проблема масштабируемости.