governance_instruction.proto 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. syntax = "proto3";
  2. import "google/protobuf/timestamp.proto";
  3. import "google/protobuf/duration.proto";
  4. import "google/protobuf/empty.proto";
  5. import "dynamic_value.proto";
  6. import "state.proto";
  7. // If any field documented as `[required]` is not present in the instruction,
  8. // the instruction will be rejected.
  9. package pyth_lazer;
  10. // Representation of a complete governance instruction. This value will be signed
  11. // by a governance source.
  12. //
  13. // If the governance source is SingleEd25519, this message will be the payload of LazerTransaction.
  14. //
  15. // If the governance source is Wormhole emitter, this message will be the body of the GovernancePayload which
  16. // is the VAA message Pyth governance sends to Wormhole. The GovernancePayload follows xc-admin spec
  17. // and looks like so:
  18. // <magic:u32><module:u8><action:u8><chain:u16><GovernanceInstruction:bytes>
  19. // You can find the xc-admin spec in: ../../../governance/xc_admin/packages/xc_admin_common/src/governance_payload
  20. message GovernanceInstruction {
  21. // Action requested by this instruction. For the instruction to be accepted, all items
  22. // must be successfully applied. In case of any failure, the whole instruction is reverted.
  23. // However, note that if the instruction targets multiple (or all) shards, each shard will
  24. // accept or reject the instruction independently of other shards.
  25. repeated GovernanceInstructionItem items = 2;
  26. // [optional] If specified, the instruction will be rejected if the current timestamp
  27. // is less than the specified value. In case of rejection, the same instruction can be resubmitted
  28. // and executed later once the time requirement is met.
  29. optional google.protobuf.Timestamp min_execution_timestamp = 3;
  30. // [optional] If specified, the instruction will be rejected if the current timestamp
  31. // is greater than the specified value. After `max_execution_timestamp` is in the past,
  32. // it will no longer be possible to execute this instruction.
  33. optional google.protobuf.Timestamp max_execution_timestamp = 4;
  34. // [optional] Sequence number of this instruction. Required for SingleEd25519 governance source
  35. // and optional for WomrholeEmitter governance source (because Wormhole has its own sequence
  36. // numbers). If set, it must be greater than 0, and always be increasing, but not required to be
  37. // strictly sequential (i.e. gaps are allowed). Each shard separately keeps track of the last
  38. // executed governance instruction and will reject instructions with the same or smaller
  39. // sequence no. Note that if instructions are received out of order, some of them may become
  40. // permanently rejected (e.g. if instruction #3 has been successfully processed before
  41. // instruction #2 was observed, #2 will always be rejected). Sequence numbers are assigned and
  42. // tracked separately for each governance source.
  43. optional uint64 governance_sequence_no = 5;
  44. }
  45. // Specifies which shards the governance instruction applies to.
  46. message ShardFilter {
  47. // The instruction applies to the specified shards.
  48. message ShardNames {
  49. // Must not be empty.
  50. repeated string shard_names = 1;
  51. }
  52. // The instruction applies to the specified shard groups.
  53. message ShardGroups {
  54. // Must not be empty.
  55. repeated string shard_groups = 1;
  56. }
  57. // [required]
  58. oneof filter {
  59. // The instruction applies to all shards.
  60. google.protobuf.Empty all_shards = 1;
  61. ShardNames shard_names = 2;
  62. ShardGroups shard_groups = 3;
  63. }
  64. }
  65. // An item of a governance instruction.
  66. message GovernanceInstructionItem {
  67. // [required] Specifies which shards the governance instruction applies to.
  68. // The instruction applies to each shard independently of other shards and may apply
  69. // at a different time. The instruction may succeed on some shards and fail on other shards.
  70. // Note that each shard has its own list of governance sources and permissions,
  71. // and a `GovernanceInstruction` is issued by a single source, so multiple instructions
  72. // from different sources may be needed to apply a change to multiple shards or shard groups.
  73. optional ShardFilter shard_filter = 1;
  74. // [required]
  75. // Note: when adding a new variant here, update `Permissions` as well.
  76. oneof action {
  77. CreateShard create_shard = 101;
  78. AddGovernanceSource add_governance_source = 102;
  79. UpdateGovernanceSource update_governance_source = 103;
  80. SetShardName set_shard_name = 105;
  81. SetShardGroup set_shard_group = 106;
  82. ResetLastSequenceNo reset_last_sequence_no = 107;
  83. AddPublisher add_publisher = 108;
  84. UpdatePublisher update_publisher = 109;
  85. RemovePublisher remove_publisher = 110;
  86. AddFeed add_feed = 111;
  87. UpdateFeed update_feed = 112;
  88. RemoveFeed remove_feed = 113;
  89. AddFeatureFlag add_feature_flag = 114;
  90. RemoveFeatureFlag remove_feature_flag = 115;
  91. AddAsset add_asset = 116;
  92. UpdateAsset update_asset = 117;
  93. RemoveAsset remove_asset = 118;
  94. }
  95. }
  96. // Create a new shard. A shard is a partially isolated part of Lazer that has its own state and
  97. // cannot be directly influenced by other shards. The main purpose of shards in Lazer is
  98. // to allow horizontal scaling when the number of feeds grows. Feeds can be divided into subsets
  99. // and each subset will be assigned to a shard.
  100. //
  101. // Shard name will be determined by the value of `GovernanceInstructionItem.filter`.
  102. // This action will be rejected unless `GovernanceInstructionItem.filter` specified a single shard.
  103. // Shard name must be unique across all shards in all groups.
  104. // (Warning: it's not possible to enforce this rule within a shard!)
  105. message CreateShard {
  106. // [required] ID of the new shard.
  107. // Shard ID must be unique across all shards in all groups.
  108. // (Warning: it's not possible to enforce this rule within a shard!)
  109. optional uint32 shard_id = 1;
  110. // [required] Shard name. Must be unique. Used for governance instruction targeting and
  111. // for logs, metrics, etc. Example: "shard1.tokyo.staging.pyth-lazer"
  112. optional string shard_name = 4;
  113. // [required] Group name, e.g. "production", "staging", "testing", etc.
  114. // Data from shards belonging to the same group can be joined and served to consumers as a whole.
  115. // Active feed names must be unique within a group, but not across all groups.
  116. optional string shard_group = 2;
  117. // [required] Minimal aggregation rate allowed in this shard.
  118. optional google.protobuf.Duration min_rate = 3;
  119. }
  120. message AddGovernanceSource {
  121. // [required] Governance source that should be added.
  122. optional GovernanceSource new_source = 1;
  123. // [required] Permissions granted to this source.
  124. optional Permissions permissions = 2;
  125. }
  126. message UpdateGovernanceSource {
  127. // [required] Governance source that should be updated. Rejects if there is no such source.
  128. // Rejects if the specified source is the same as the source of the current instruction.
  129. optional GovernanceSource source = 1;
  130. // [required]
  131. // Note: when adding a new variant here, update `Permissions` as well.
  132. oneof action {
  133. SetGovernanceSourcePermissions set_governance_source_permissions = 101;
  134. }
  135. }
  136. message SetGovernanceSourcePermissions {
  137. // [required] Permissions granted to this source. Replaces all previous permissions.
  138. optional Permissions permissions = 1;
  139. }
  140. // Set shard name. This action will be rejected if `GovernanceInstructionItem.shard_names` is empty or contains
  141. // more than one item.
  142. message SetShardName {
  143. // [required] New shard name. Must be unique across all shards in all groups.
  144. // (Warning: it's not possible to enforce this rule within a shard!)
  145. optional string shard_name = 1;
  146. }
  147. // Set shard group. This action will be rejected if `GovernanceInstructionItem.shard_names` is empty or contains
  148. // more than one item.
  149. message SetShardGroup {
  150. // [required] Group name, e.g. "production", "staging", "testing", etc.
  151. // Data from shards belonging to the same group can be joined and served to consumers as a whole.
  152. // Active feed names must be unique within a group, but not across all groups.
  153. optional string shard_group = 1;
  154. }
  155. // Set `last_sequence_no`. This can be used as a workaround in case some updates are lost and
  156. // the services are unable to proceed.
  157. message ResetLastSequenceNo {
  158. optional uint64 last_sequence_no = 1;
  159. }
  160. message AddPublisher {
  161. // [required] Publisher ID. Restricted to uint16. Must be different from existing ids.
  162. optional uint32 publisher_id = 1;
  163. // [required] Publisher name (only for debug/monitoring/management purposes).
  164. // Must be different from existing publisher names.
  165. optional string name = 2;
  166. // Public keys used to sign publisher update transactions.
  167. repeated bytes public_keys = 3;
  168. // [required] If true, the publisher is active, i.e. it's allowed to publish updates.
  169. optional bool is_active = 4;
  170. // IDs of the feeds for which the publisher's price will be included in the aggregate.
  171. repeated uint32 allowed_feed_ids = 5;
  172. }
  173. message UpdatePublisher {
  174. // [required] ID of the publisher that is being updated. Rejects if there is no such publisher.
  175. optional uint32 publisher_id = 1;
  176. // [required]
  177. // Note: when adding a new variant here, update `Permissions` as well.
  178. oneof action {
  179. SetPublisherName set_publisher_name = 101;
  180. AddPublisherPublicKeys add_publisher_public_keys = 102;
  181. RemovePublisherPublicKeys remove_publisher_public_keys = 103;
  182. SetPublisherPublicKeys set_publisher_public_keys = 104;
  183. SetPublisherActive set_publisher_active = 105;
  184. AddPublisherAllowedFeedIds add_publisher_allowed_feed_ids = 106;
  185. RemovePublisherAllowedFeedIds remove_publisher_allowed_feed_ids = 107;
  186. SetPublisherAllowedFeedIds set_publisher_allowed_feed_ids = 108;
  187. }
  188. }
  189. message RemovePublisher {
  190. // [required] ID of the publisher that is being deleted. Rejects if there is no such publisher.
  191. optional uint32 publisher_id = 1;
  192. }
  193. message SetPublisherName {
  194. // [required] New name.
  195. optional string name = 1;
  196. }
  197. // Add new keys.
  198. message AddPublisherPublicKeys {
  199. // Must not be empty.
  200. repeated bytes public_keys = 1;
  201. }
  202. // Remove existing keys.
  203. message RemovePublisherPublicKeys {
  204. // Must not be empty.
  205. repeated bytes public_keys = 1;
  206. }
  207. // Remove all existing public keys and add new keys (if specified).
  208. message SetPublisherPublicKeys {
  209. repeated bytes public_keys = 1;
  210. }
  211. // Allow publisher to publish for the specified feeds.
  212. message AddPublisherAllowedFeedIds {
  213. // Must not be empty.
  214. repeated uint32 allowed_feed_ids_to_add = 1;
  215. }
  216. // Disallow publisher to publish for the specified feeds.
  217. message RemovePublisherAllowedFeedIds {
  218. // Must not be empty.
  219. repeated uint32 allowed_feed_ids_to_remove = 1;
  220. }
  221. // Allow publisher to publish for only the specified feeds.
  222. // Remove all previous allowances.
  223. message SetPublisherAllowedFeedIds {
  224. repeated uint32 allowed_feed_ids = 1;
  225. }
  226. message SetPublisherActive {
  227. // [required]
  228. optional bool is_active = 1;
  229. }
  230. // Add a new feed. Refer to `Feed` message fields documentation.
  231. message AddFeed {
  232. // [required]
  233. optional uint32 feed_id = 1;
  234. // [required]
  235. optional DynamicValue.Map metadata = 3;
  236. // [required]
  237. optional string symbol = 101;
  238. // [required]
  239. optional sint32 exponent = 102;
  240. // [required]
  241. optional uint32 min_publishers = 103;
  242. // [required]
  243. optional Channel min_channel = 104;
  244. // [required]
  245. optional google.protobuf.Duration expiry_time = 105;
  246. // [required]
  247. optional string market_schedule = 106;
  248. // [required]
  249. optional FeedState state = 107;
  250. // [required]
  251. optional FeedKind kind = 108;
  252. // [required]
  253. optional bool is_enabled_in_shard = 201;
  254. // TODO: IDs of publishers enabled for this feed.
  255. // repeated uint32 permissioned_publishers = 3;
  256. }
  257. message UpdateFeed {
  258. // [required] ID of the feed that is being updated. Rejects if there is no such feed.
  259. optional uint32 feed_id = 1;
  260. // [required]
  261. // Note: when adding a new variant here, update `Permissions` as well.
  262. oneof action {
  263. UpdateFeedProperties update_feed_properties = 101;
  264. UpdateFeedMetadata update_feed_metadata = 102;
  265. EnableFeedInShard enable_feed_in_shard = 103;
  266. DisableFeedInShard disable_feed_in_shard = 104;
  267. }
  268. }
  269. message RemoveFeed {
  270. // [required] ID of the feed that is being removed. Rejects if there is no such feed.
  271. optional uint32 feed_id = 1;
  272. }
  273. // Update a feed's properties. The feed will be updated with values present in each field.
  274. // If a value is not supplied, the corresponding property will remain unchanged.
  275. // Refer to `Feed` message fields documentation.
  276. message UpdateFeedProperties {
  277. // [optional]
  278. optional DynamicValue.Map metadata = 3;
  279. // [optional]
  280. optional string symbol = 101;
  281. // [optional]
  282. optional sint32 exponent = 102;
  283. // [optional]
  284. optional uint32 min_publishers = 103;
  285. // [optional]
  286. optional Channel min_channel = 104;
  287. // [optional]
  288. optional google.protobuf.Duration expiry_time = 105;
  289. // [optional]
  290. optional string market_schedule = 106;
  291. // [optional]
  292. optional FeedState state = 107;
  293. // [required]
  294. optional FeedKind kind = 108;
  295. // [optional]
  296. optional bool is_enabled_in_shard = 201;
  297. }
  298. message UpdateFeedMetadata {
  299. // [required] Property name.
  300. optional string name = 1;
  301. // [optional] Property value. If unset, the property will be removed.
  302. optional DynamicValue value = 2;
  303. }
  304. // Set the feed as enabled in this shard or shedule it for a certain timestamp.
  305. // If there was already a pending status change, it will be cleared
  306. // when this governance instruction is processed.
  307. // Warning: there must never be two feeds with the same name enabled at the same time
  308. // within a shard group. This cannot be enforced within a shard. When a feed needs to be
  309. // moved between shards, use `enable_in_shard_timestamp` and `disable_in_shard_timestamp`
  310. // to disable it in the old shard and enable it in the new shard at the same time.
  311. message EnableFeedInShard {
  312. // [required] The feed will be enabled at the specified timestamp.
  313. // If `enable_in_shard_timestamp` is already passed,
  314. // the feed will be enabled immediately when this
  315. // governance instruction is processed.
  316. optional google.protobuf.Timestamp enable_in_shard_timestamp = 1;
  317. }
  318. // Set the feed as disabled in this shard or shedule it for a certain timestamp.
  319. // If there was already a pending status change, it will be cleared
  320. // when this governance instruction is processed.
  321. // See also: `EnableFeedInShard` docs.
  322. message DisableFeedInShard {
  323. // [required] The feed will be disabled at the specified timestamp.
  324. // If `disable_in_shard_timestamp` is already passed,
  325. // the feed will be disabled immediately when this
  326. // governance instruction is processed.
  327. optional google.protobuf.Timestamp disable_in_shard_timestamp = 1;
  328. }
  329. // Add a new feature flag.
  330. message AddFeatureFlag {
  331. // [required] Feature flag to add.
  332. optional string feature_flag = 1;
  333. }
  334. // Remove a feature flag.
  335. message RemoveFeatureFlag {
  336. // [required] Feature flag to remove.
  337. optional string feature_flag = 1;
  338. }
  339. // Add a new asset. Refer to `Asset` message fields documentation.
  340. message AddAsset {
  341. // [required]
  342. optional uint32 asset_id = 1;
  343. // [required]
  344. optional DynamicValue.Map metadata = 2;
  345. }
  346. message UpdateAsset {
  347. // [required] ID of the asset that is being updated. Rejects if there is no such asset.
  348. optional uint32 asset_id = 1;
  349. // [required]
  350. // Note: when adding a new variant here, update `Permissions` as well.
  351. oneof action {
  352. UpdateAssetMetadata update_asset_metadata = 101;
  353. }
  354. }
  355. message RemoveAsset {
  356. // [required] ID of the asset that is being removed. Rejects if there is no such asset.
  357. optional uint32 asset_id = 1;
  358. }
  359. message UpdateAssetMetadata {
  360. // [required] Property name.
  361. optional string name = 1;
  362. // [optional] Property value. If unset, the property will be removed.
  363. optional DynamicValue value = 2;
  364. }