@agoric/fast-usdc 0.1.1-dev-9418efc.0 → 0.1.1-dev-9e5f628.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agoric/fast-usdc",
3
- "version": "0.1.1-dev-9418efc.0+9418efc",
3
+ "version": "0.1.1-dev-9e5f628.0+9e5f628",
4
4
  "description": "CLI and library for Fast USDC product",
5
5
  "type": "module",
6
6
  "files": [
@@ -22,9 +22,9 @@
22
22
  "lint:eslint": "eslint ."
23
23
  },
24
24
  "devDependencies": {
25
- "@agoric/swingset-liveslots": "0.10.3-dev-9418efc.0+9418efc",
26
- "@agoric/vats": "0.15.2-dev-9418efc.0+9418efc",
27
- "@agoric/zone": "0.2.3-dev-9418efc.0+9418efc",
25
+ "@agoric/swingset-liveslots": "0.10.3-dev-9e5f628.0+9e5f628",
26
+ "@agoric/vats": "0.15.2-dev-9e5f628.0+9e5f628",
27
+ "@agoric/zone": "0.2.3-dev-9e5f628.0+9e5f628",
28
28
  "@fast-check/ava": "^2.0.1",
29
29
  "ava": "^5.3.0",
30
30
  "c8": "^10.1.2",
@@ -32,16 +32,16 @@
32
32
  "ts-blank-space": "^0.4.4"
33
33
  },
34
34
  "dependencies": {
35
- "@agoric/client-utils": "0.1.1-dev-9418efc.0+9418efc",
36
- "@agoric/cosmic-proto": "0.4.1-dev-9418efc.0+9418efc",
37
- "@agoric/ertp": "0.16.3-dev-9418efc.0+9418efc",
38
- "@agoric/internal": "0.3.3-dev-9418efc.0+9418efc",
39
- "@agoric/notifier": "0.6.3-dev-9418efc.0+9418efc",
40
- "@agoric/orchestration": "0.1.1-dev-9418efc.0+9418efc",
41
- "@agoric/store": "0.9.3-dev-9418efc.0+9418efc",
42
- "@agoric/vat-data": "0.5.3-dev-9418efc.0+9418efc",
43
- "@agoric/vow": "0.1.1-dev-9418efc.0+9418efc",
44
- "@agoric/zoe": "0.26.3-dev-9418efc.0+9418efc",
35
+ "@agoric/client-utils": "0.1.1-dev-9e5f628.0+9e5f628",
36
+ "@agoric/cosmic-proto": "0.4.1-dev-9e5f628.0+9e5f628",
37
+ "@agoric/ertp": "0.16.3-dev-9e5f628.0+9e5f628",
38
+ "@agoric/internal": "0.3.3-dev-9e5f628.0+9e5f628",
39
+ "@agoric/notifier": "0.6.3-dev-9e5f628.0+9e5f628",
40
+ "@agoric/orchestration": "0.1.1-dev-9e5f628.0+9e5f628",
41
+ "@agoric/store": "0.9.3-dev-9e5f628.0+9e5f628",
42
+ "@agoric/vat-data": "0.5.3-dev-9e5f628.0+9e5f628",
43
+ "@agoric/vow": "0.1.1-dev-9e5f628.0+9e5f628",
44
+ "@agoric/zoe": "0.26.3-dev-9e5f628.0+9e5f628",
45
45
  "@cosmjs/proto-signing": "^0.32.4",
46
46
  "@cosmjs/stargate": "^0.32.4",
47
47
  "@endo/base64": "^1.0.9",
@@ -81,5 +81,5 @@
81
81
  "publishConfig": {
82
82
  "access": "public"
83
83
  },
84
- "gitHead": "9418efc6d8ba27f3361754ea2a55b47a367e06b3"
84
+ "gitHead": "9e5f628a3d953539bcea5e3ba2365367158ec069"
85
85
  }
@@ -12,7 +12,7 @@ const trace = makeTracer('TxOperator');
12
12
 
13
13
  /**
14
14
  * @typedef {object} OperatorPowers
15
- * @property {(evidence: CctpTxEvidence, operatorKit: OperatorKit) => void} submitEvidence
15
+ * @property {(evidence: CctpTxEvidence, operatorId: string) => void} attest
16
16
  */
17
17
 
18
18
  /**
@@ -35,7 +35,7 @@ const OperatorKitI = {
35
35
  }),
36
36
 
37
37
  operator: M.interface('Operator', {
38
- submitEvidence: M.call(CctpTxEvidenceShape).returns(M.promise()),
38
+ submitEvidence: M.call(CctpTxEvidenceShape).returns(),
39
39
  getStatus: M.call().returns(M.record()),
40
40
  }),
41
41
  };
@@ -87,7 +87,7 @@ export const prepareOperatorKit = (zone, staticPowers) =>
87
87
  const { operator } = this.facets;
88
88
  // TODO(bootstrap integration): cause this call to throw and confirm that it
89
89
  // shows up in the the smart-wallet UpdateRecord `error` property
90
- await operator.submitEvidence(evidence);
90
+ operator.submitEvidence(evidence);
91
91
  return staticPowers.makeInertInvitation(
92
92
  'evidence was pushed in the invitation maker call',
93
93
  );
@@ -98,12 +98,12 @@ export const prepareOperatorKit = (zone, staticPowers) =>
98
98
  * submit evidence from this operator
99
99
  *
100
100
  * @param {CctpTxEvidence} evidence
101
+ * @returns {void}
101
102
  */
102
- async submitEvidence(evidence) {
103
+ submitEvidence(evidence) {
103
104
  const { state } = this;
104
105
  !state.disabled || Fail`submitEvidence for disabled operator`;
105
- const result = state.powers.submitEvidence(evidence, this.facets);
106
- return result;
106
+ state.powers.attest(evidence, state.operatorId);
107
107
  },
108
108
  /** @returns {OperatorStatus} */
109
109
  getStatus() {
@@ -1,6 +1,7 @@
1
1
  import { makeTracer } from '@agoric/internal';
2
2
  import { prepareDurablePublishKit } from '@agoric/notifier';
3
- import { M } from '@endo/patterns';
3
+ import { keyEQ, M } from '@endo/patterns';
4
+ import { Fail } from '@endo/errors';
4
5
  import { CctpTxEvidenceShape } from '../type-guards.js';
5
6
  import { defineInertInvitation } from '../utils/zoe.js';
6
7
  import { prepareOperatorKit } from './operator-kit.js';
@@ -18,7 +19,7 @@ export const INVITATION_MAKERS_DESC = 'oracle operator invitation';
18
19
 
19
20
  const TransactionFeedKitI = harden({
20
21
  operatorPowers: M.interface('Transaction Feed Admin', {
21
- submitEvidence: M.call(CctpTxEvidenceShape, M.any()).returns(),
22
+ attest: M.call(CctpTxEvidenceShape, M.string()).returns(),
22
23
  }),
23
24
  creator: M.interface('Transaction Feed Creator', {
24
25
  // TODO narrow the return shape to OperatorKit
@@ -118,23 +119,16 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
118
119
  /**
119
120
  * Add evidence from an operator.
120
121
  *
122
+ * NB: the operatorKit is responsible for
123
+ *
121
124
  * @param {CctpTxEvidence} evidence
122
- * @param {OperatorKit} operatorKit
125
+ * @param {string} operatorId
123
126
  */
124
- submitEvidence(evidence, operatorKit) {
125
- const { pending } = this.state;
126
- trace(
127
- 'submitEvidence',
128
- operatorKit.operator.getStatus().operatorId,
129
- evidence,
130
- );
131
- const { operatorId } = operatorKit.operator.getStatus();
132
-
133
- // TODO should this verify that the operator is one made by this exo?
134
- // This doesn't work...
135
- // operatorKit === operators.get(operatorId) ||
136
- // Fail`operatorKit mismatch`;
127
+ attest(evidence, operatorId) {
128
+ const { operators, pending } = this.state;
129
+ trace('submitEvidence', operatorId, evidence);
137
130
 
131
+ // TODO https://github.com/Agoric/agoric-sdk/pull/10720
138
132
  // TODO validate that it's a valid for Fast USDC before accepting
139
133
  // E.g. that the `recipientAddress` is the FU settlement account and that
140
134
  // the EUD is a chain supported by FU.
@@ -154,18 +148,46 @@ export const prepareTransactionFeedKit = (zone, zcf) => {
154
148
  const found = [...pending.values()].filter(store =>
155
149
  store.has(txHash),
156
150
  );
157
- // TODO determine the real policy for checking agreement
158
- if (found.length < pending.getSize()) {
159
- // not all have seen it
151
+ const minAttestations = Math.ceil(operators.getSize() / 2);
152
+ trace(
153
+ 'transaction',
154
+ txHash,
155
+ 'has',
156
+ found.length,
157
+ 'of',
158
+ minAttestations,
159
+ 'necessary attestations',
160
+ );
161
+ if (found.length < minAttestations) {
160
162
  return;
161
163
  }
162
164
 
163
- // TODO verify that all found deep equal
165
+ let lastEvidence;
166
+ for (const store of found) {
167
+ const next = store.get(txHash);
168
+ if (lastEvidence) {
169
+ if (keyEQ(lastEvidence, next)) {
170
+ lastEvidence = next;
171
+ } else {
172
+ trace(
173
+ '🚨 conflicting evidence for',
174
+ txHash,
175
+ ':',
176
+ lastEvidence,
177
+ '!=',
178
+ next,
179
+ );
180
+ Fail`conflicting evidence for ${txHash}`;
181
+ }
182
+ }
183
+ lastEvidence = next;
184
+ }
164
185
 
165
- // all agree, so remove from pending and publish
166
- for (const pendingStore of pending.values()) {
167
- pendingStore.delete(txHash);
186
+ // sufficient agreement, so remove from pending and publish
187
+ for (const store of found) {
188
+ store.delete(txHash);
168
189
  }
190
+ trace('publishing evidence', evidence);
169
191
  publisher.publish(evidence);
170
192
  },
171
193
  },
@@ -156,3 +156,11 @@ export const configurations = {
156
156
  },
157
157
  };
158
158
  harden(configurations);
159
+
160
+ // Constraints on the configurations
161
+ const MAINNET_EXPECTED_ORACLES = 3;
162
+ assert(
163
+ new Set(Object.values(configurations.MAINNET.oracles)).size ===
164
+ MAINNET_EXPECTED_ORACLES,
165
+ `Mainnet must have exactly ${MAINNET_EXPECTED_ORACLES} oracles`,
166
+ );