on master help sign in
fix: update pointCursor/networkSeed callsites to fix bugs

1. setPointCursor(string) was being used, but pointCursor expects number 2. local networkSeed was not respected within GenKeys.js

commite00f1f417d75e0502e2cfb017d860927452acebc authorMatt Condon (shrugs) <mattgcondon@gmail.com> dateMon 17 Jun 2019, 14:15 (7 years ago) parent656c219
13 files changed+79−89
.env.development+1 README.md+14−13 src/bridge/Bridge.js+3−5 src/bridge/components/StatelessTransaction.js+2−2 src/bridge/lib/invite.js+10−6 src/bridge/lib/keys.js+9−7 src/bridge/store/pointCursor.js+1 src/bridge/store/wallet.js+2−2 src/bridge/views/GenKeyfile.js+11−9 src/bridge/views/Points.js+7−28 src/bridge/views/SentTransaction.js−3 src/bridge/views/SetKeys.js+17−13 src/bridge/views/ViewPoint.js+2−1
.env.development+1
@@ -2,3 +2,4 @@ REACT_APP_DEV_MNEMONIC='benefit crew supreme gesture quantum web media hazard th
22REACT_APP_DEV_GALAXY_TICKET='~wacfus-dabpex-danted-mosfep-pasrud-lavmer-nodtex-taslus-pactyp-milpub-pildeg-fornev-ralmed-dinfeb-fopbyr-sanbet-sovmyl-dozsut-mogsyx-mapwyc-sorrup-ricnec-marnys-lignex'
33REACT_APP_ROPSTEN_KEY='b7d2af9f01534031ba773374f766ef65'
44REACT_APP_HD_PATH="m/44'/60'/0'/0/0"
5+REACT_APP_STUB_LOCAL='false'
README.md+14−13
@@ -52,14 +52,13 @@ To validate your downloaded file's integrity, compare the lines in checksum.txt
5252
5353### Install / Build
5454
55−Clone the repo, and use a simple `npm install`. You can then use a `npm run
56−build` to create an optimised static build (serve it with e.g. [serve][serv]).
55+Clone the repo, and use a simple `npm install`. You can then use a `npm run build` to create an optimised static build (serve it with e.g. [serve][serv]).
5756
5857### General notes
5958
60−For development, use `npm run pilot` to get going after a `npm install`. This
59+For development, use `npm run pilot` to get going after a `npm install`. This
6160will boot up a Ganache node in the background, deploy the Azimuth contracts to
62−it, and fire up a local webserver. Bridge will be served on `localhost:3000`.
61+it, and fire up a local webserver. Bridge will be served on `localhost:3000`.
6362
6463Note that one of our dependencies itself depends on a library called
6564`handle-thing` which breaks under the Ledger support requirements (see below)
@@ -77,7 +76,7 @@ before running `npm run pilot`.
7776### Useful accounts
7877
7978The ecliptic owner is the only account that's able to create galaxies, so
80−it's a good place to get started. On the testnet, it's the address:
79+it's a good place to get started. On the testnet, it's the address:
8180
8281```
83820x6DEfFb0caFDB11D175F123F6891AA64F01c24F7d
@@ -114,12 +113,15 @@ You can also tweak a couple of things to change your development state
114113somewhat (say, for example, you want to start on the points list screen, instead
115114of having to re-authenticate whenever you make a change or refresh the page):
116115
117−* The `.env.development` file contains environment variables that you can
118− provide to the application when it's running in development. You can access
116+- The `.env.development` file contains environment variables that you can
117+ provide to the application when it's running in development. You can access
119118 them via `process.env.REACT_APP_<whatever>`.
120119
121−* The `componentDidMount` method of the Bridge component in `src/Bridge.js`
122− can be tweaked for setting your initial state. You can provide a specific
120+- Make `REACT_APP_STUB_LOCAL='true'` to enabled stubbing of some methods
121+ in a local development environment.
122+
123+- The top of the Bridge component in `src/Bridge.js`
124+ can be tweaked for setting your initial state. You can provide a specific
123125 wallet, network type, and so on.
124126
125127### HTTPS
@@ -136,15 +138,14 @@ websocket. Do this by going to `about:config` and setting the
136138`network.websocket.allowInsecureFromHTTPS` flag to `true`.
137139
138140Additionally you need to run with the `HTTPS` environment variable set to
139−`true`. Note that `npm run pilot` will handle this automatically.
141+`true`. Note that `npm run pilot` will handle this automatically.
140142
141143### Releases
142144
143−To generate a release `bridge-$VERSION.zip` file, use a simple `npm run
144−release`.
145+To generate a release `bridge-$VERSION.zip` file, use a simple `npm run release`.
145146
146147This will pack the build directory together with the README, `bridge-https.py`
147−script, and also generate a set of checksums for the build directory. You can
148+script, and also generate a set of checksums for the build directory. You can
148149verify the checksums on e.g. OS X via `shasum -c checksums.txt`.
149150
150151[rele]: https://github.com/urbit/bridge/releases/latest
src/bridge/Bridge.js+3−5
@@ -25,10 +25,8 @@ const kInitialNetworkType = isDevelopment
2525 ? NETWORK_TYPES.LOCAL
2626 : NETWORK_TYPES.MAINNET;
2727
28−// NB(shrugs): toggle these variables to change the default local state.
29−// try not to commit changes to this line, but there shouldn't be a problem
30−// if you do because we'll never stub on a production build.
31−const shouldStubLocal = false;
28+// NB(shrugs): modify these variables to change the default local state.
29+const shouldStubLocal = process.env.REACT_APP_STUB_LOCAL === 'true';
3230const kIsStubbed = isDevelopment && shouldStubLocal;
3331const kInitialRoutes = kIsStubbed
3432 ? [
@@ -46,7 +44,7 @@ const kInitialWallet = kIsStubbed
4644 )
4745 : undefined;
4846const kInitialMnemonic = kIsStubbed
49− ? process.env.REACT_APP_DEV_MNEMONIC
47+ ? Just(process.env.REACT_APP_DEV_MNEMONIC)
5048 : Nothing();
5149const kInitialPointCursor = kIsStubbed ? Just(0) : Nothing();
5250
src/bridge/components/StatelessTransaction.js+2−2
@@ -243,12 +243,12 @@ class StatelessTransaction extends React.Component {
243243
244244 let routeData = {};
245245 if (props.newNetworkSeed) {
246− props.setNetworkSeedCache(props.newNetworkSeed);
246+ props.setNetworkSeed(Just(props.newNetworkSeed));
247247 routeData.promptKeyfile = true;
248248 }
249249
250250 if (props.newRevision) {
251− props.setNetworkRevision(props.newRevision);
251+ props.setNetworkRevision(Just(props.newRevision));
252252 }
253253
254254 props.history.popAndPush(ROUTE_NAMES.SENT_TRANSACTION, routeData);
src/bridge/lib/invite.js+10−6
@@ -11,7 +11,7 @@ import saveAs from 'file-saver';
1111
1212import { sendSignedTransaction } from './txn';
1313import { BRIDGE_ERROR } from '../lib/error';
14−import { attemptSeedDerivation } from './keys';
14+import { attemptNetworkSeedDerivation } from './keys';
1515import { addHexPrefix, WALLET_TYPES } from './wallet';
1616
1717const INVITE_STAGES = {
@@ -212,16 +212,20 @@ async function startTransactions(args) {
212212
213213 // configure networking public keys
214214 //TODO feels like more of this logic should live in a lib?
215− let networkSeed = await attemptSeedDerivation(true, {
215+ const seed = await attemptNetworkSeedDerivation(true, {
216216 walletType: WALLET_TYPES.TICKET,
217217 urbitWallet: Just(realWallet),
218218 pointCursor: Just(point),
219219 pointCache: { [point]: { keyRevisionNumber: 0 } },
220220 });
221− if (Nothing.hasInstance(networkSeed)) {
222− throw new Error('wtf network seed not derived');
223− }
224− networkSeed = networkSeed.value;
221+
222+ const networkSeed = seed.matchWith({
223+ Nothing: () => {
224+ throw new Error('network seed not derived');
225+ },
226+ Just: p => p.value,
227+ });
228+
225229 const networkKeys = kg.deriveNetworkKeys(networkSeed);
226230
227231 let keysTx = azimuth.ecliptic.configureKeys(
src/bridge/lib/keys.js+9−7
@@ -55,7 +55,7 @@ const genKey = (networkSeed, point, revision) => {
5555 const bnsec = new BN(pair.crypt.private + pair.auth.private + '42', 'hex'); // '42' is curve parameter
5656
5757 const sed = noun.dwim(
58− noun.Atom.fromString(point),
58+ noun.Atom.fromInt(point),
5959 noun.Atom.fromInt(revision),
6060 noun.Atom.fromString(bnsec.toString()),
6161 noun.Atom.yes
@@ -66,7 +66,7 @@ const genKey = (networkSeed, point, revision) => {
6666
6767// 'next' refers to setting the next set of keys
6868// if false, we use revision - 1
69−const attemptSeedDerivation = async (next, args) => {
69+const attemptNetworkSeedDerivation = async (next, args) => {
7070 const { walletType, urbitWallet, authMnemonic } = args;
7171
7272 // NB (jtobin):
@@ -115,15 +115,17 @@ const attemptSeedDerivation = async (next, args) => {
115115 }
116116 }
117117
118− let networkSeed = Maybe.Nothing();
119−
120118 if (managementSeed !== '') {
121119 const seed = await kg.deriveNetworkSeed(managementSeed, '', revision);
122120
123− networkSeed = Maybe.Just(seed);
121+ if (seed === '') {
122+ return Maybe.Nothing();
123+ }
124+
125+ return Maybe.Just(seed);
124126 }
125127
126− return networkSeed;
128+ return Maybe.Nothing();
127129};
128130
129−export { genKey, attemptSeedDerivation };
131+export { genKey, attemptNetworkSeedDerivation };
src/bridge/store/pointCursor.js+1
@@ -3,6 +3,7 @@ import Maybe from 'folktale/maybe';
33
44export const PointCursorContext = createContext(null);
55
6+// pointCursor is Maybe<number>
67function _usePointCursor(initialPointCursor = Maybe.Nothing()) {
78 const [pointCursor, setPointCursor] = useState(initialPointCursor);
89
src/bridge/store/wallet.js+2−2
@@ -34,7 +34,7 @@ function _useWallet(
3434 const [urbitWallet, _setUrbitWallet] = useState(Maybe.Nothing());
3535 const [authMnemonic, setAuthMnemonic] = useState(initialMnemonic);
3636 const [networkSeed, setNetworkSeed] = useState(Maybe.Nothing());
37− const [networkRevision, setNetowrkRevision] = useState(Maybe.Nothing());
37+ const [networkRevision, setNetworkRevision] = useState(Maybe.Nothing());
3838
3939 const setWalletType = walletType => {
4040 if (!includes(WALLET_TYPES, walletType)) {
@@ -95,7 +95,7 @@ function _useWallet(
9595 networkSeed,
9696 setNetworkSeed,
9797 networkRevision,
98− setNetowrkRevision,
98+ setNetworkRevision,
9999 };
100100}
101101
src/bridge/views/GenKeyfile.js+11−9
@@ -1,5 +1,4 @@
11import React from 'react';
2−import Maybe from 'folktale/maybe';
32import * as need from '../lib/need';
43
54import { Button } from '../components/Base';
@@ -9,7 +8,7 @@ import * as ob from 'urbit-ob';
98import * as kg from 'urbit-key-generation/dist/index';
109import saveAs from 'file-saver';
1110
12−import { attemptSeedDerivation, genKey } from '../lib/keys';
11+import { attemptNetworkSeedDerivation, genKey } from '../lib/keys';
1312import { addHexPrefix } from '../lib/wallet';
1413import { compose } from '../lib/lib';
1514import { withWallet } from '../store/wallet';
@@ -33,8 +32,10 @@ class GenKeyfile extends React.Component {
3332
3433 // in case we did SetKeys earlier this session, make sure to generate the
3534 // newer keyfile, rather than the one that will expire soon
36− const revision =
37− this.props.networkRevision || parseInt(pointDetails.keyRevisionNumber);
35+ const revision = this.props.networkRevision.matchWith({
36+ Nothing: () => parseInt(pointDetails.keyRevisionNumber),
37+ Just: p => p.value,
38+ });
3839
3940 return {
4041 point,
@@ -78,13 +79,14 @@ class GenKeyfile extends React.Component {
7879
7980 async deriveSeed() {
8081 const next = false;
81− let seed = await attemptSeedDerivation(next, this.props);
8282
83− if (seed.getOrElse('') === '' && this.props.networkSeed) {
84− seed = Maybe.Just(this.props.networkSeed);
85− }
83+ const seed = await attemptNetworkSeedDerivation(next, this.props);
8684
87− return seed.getOrElse('');
85+ // either return the derived seed, the cached seed, or empty string
86+ return seed.matchWith({
87+ Nothing: () => this.props.networkSeed.getOrElse(''),
88+ Just: p => p.value,
89+ });
8890 }
8991
9092 render() {
src/bridge/views/Points.js+7−28
@@ -84,7 +84,7 @@ class Points extends React.Component {
8484 }
8585
8686 render() {
87− const { setPointCursor, history, pointCache } = this.props;
87+ const { history, pointCache } = this.props;
8888
8989 const {
9090 points,
@@ -93,8 +93,8 @@ class Points extends React.Component {
9393 voting,
9494 spawning,
9595 loading,
96+ eclipticOwner,
9697 } = this.state;
97− const { eclipticOwner } = this.state;
9898
9999 const lookupPointButton = (
100100 <Row>
@@ -143,11 +143,7 @@ class Points extends React.Component {
143143 {`You own these points until the recipient accepts the incoming
144144 transfer. You may cancel the transfer until accepted.`}
145145 </P>
146− <PointList
147− setPointCursor={setPointCursor}
148− routeHandler={history.push}
149− points={outgoing}
150− />
146+ <PointList routeHandler={history.push} points={outgoing} />
151147 </React.Fragment>
152148 ) : (
153149 <div />
@@ -161,11 +157,7 @@ class Points extends React.Component {
161157 {`You do not own these points until you accept the incoming transfer.
162158 You may reject any incoming transfers.`}
163159 </P>
164− <PointList
165− setPointCursor={setPointCursor}
166− routeHandler={history.push}
167− points={incoming}
168− />
160+ <PointList routeHandler={history.push} points={incoming} />
169161 </React.Fragment>
170162 ) : (
171163 <div />
@@ -179,11 +171,7 @@ class Points extends React.Component {
179171 {`You can configure or set network keys and conduct sponsorship
180172 related operations for these points.`}
181173 </P>
182− <PointList
183− setPointCursor={setPointCursor}
184− routeHandler={history.push}
185− points={managing}
186− />
174+ <PointList routeHandler={history.push} points={managing} />
187175 </React.Fragment>
188176 ) : (
189177 <div />
@@ -197,11 +185,7 @@ class Points extends React.Component {
197185 {`Since you are part of the Galactic Senate, you can cast votes on
198186 new Azimuth proposals on behalf of these points.`}
199187 </P>
200− <PointList
201− setPointCursor={setPointCursor}
202− routeHandler={history.push}
203− points={voting}
204− />
188+ <PointList routeHandler={history.push} points={voting} />
205189 </React.Fragment>
206190 ) : (
207191 <div />
@@ -212,11 +196,7 @@ class Points extends React.Component {
212196 <React.Fragment>
213197 <H2>{'You Are a Spawn Proxy For'}</H2>
214198 <P>{`You can create new child ships under these points.`}</P>
215− <PointList
216− setPointCursor={setPointCursor}
217− routeHandler={history.push}
218− points={spawning}
219− />
199+ <PointList routeHandler={history.push} points={spawning} />
220200 </React.Fragment>
221201 ) : (
222202 <div />
@@ -241,7 +221,6 @@ class Points extends React.Component {
241221 <H2>{'Your Points'}</H2>
242222
243223 <PointList
244− setPointCursor={setPointCursor}
245224 routeHandler={history.push}
246225 points={points}
247226 loading={loading}
src/bridge/views/SentTransaction.js−3
@@ -10,7 +10,6 @@ import { BRIDGE_ERROR, renderTxnError } from '../lib/error';
1010import { NETWORK_TYPES } from '../lib/network';
1111import { useTxnConfirmations } from '../store/txnConfirmations';
1212import { useNetwork } from '../store/network';
13−import { usePointCursor } from '../store/pointCursor';
1413import { useTxnCursor } from '../store/txnCursor';
1514
1615class Success extends React.Component {
@@ -115,7 +114,6 @@ const Failure = props => (
115114function SentTransaction(props) {
116115 const history = useHistory();
117116 const { txnConfirmations } = useTxnConfirmations();
118− const { setPointCursor, pointCursor } = usePointCursor();
119117 const { web3, networkType } = useNetwork();
120118 const { txnCursor } = useTxnCursor();
121119
@@ -148,7 +146,6 @@ function SentTransaction(props) {
148146 <Button
149147 prop-type={'link'}
150148 onClick={() => {
151− setPointCursor(pointCursor);
152149 history.pop();
153150 }}>
154151 {'Ok →'}
src/bridge/views/SetKeys.js+17−13
@@ -7,7 +7,7 @@ import * as kg from 'urbit-key-generation/dist/index';
77import { Row, Col, H1, P, Warning, CheckboxButton } from '../components/Base';
88
99import StatelessTransaction from '../components/StatelessTransaction';
10−import { attemptSeedDerivation } from '../lib/keys';
10+import { attemptNetworkSeedDerivation } from '../lib/keys';
1111
1212import { addHexPrefix } from '../lib/wallet';
1313import { compose } from '../lib/lib';
@@ -26,7 +26,7 @@ class SetKeys extends React.Component {
2626 this.state = {
2727 auth: '',
2828 encr: '',
29− networkSeed: '',
29+ newNetworkSeed: '',
3030 nondeterministicSeed: false,
3131 point: point,
3232 cryptoSuiteVersion: 1,
@@ -93,17 +93,20 @@ class SetKeys extends React.Component {
9393
9494 async deriveSeed() {
9595 const next = true;
96− let seed = await attemptSeedDerivation(next, this.props);
9796 let nondeterministicSeed = false;
9897
99− if (seed.getOrElse('') === '') {
100− seed = Maybe.Just(this.randomHex(64));
101− nondeterministicSeed = true;
102− }
98+ const seed = await attemptNetworkSeedDerivation(next, this.props);
99+ const newNetworkSeed = seed.matchWith({
100+ Nothing: () => {
101+ nondeterministicSeed = true;
102+ return this.randomHex(64);
103+ },
104+ Just: p => p.value,
105+ });
103106
104107 this.setState({
105− networkSeed: seed.getOrElse(''),
106− nondeterministicSeed: nondeterministicSeed,
108+ newNetworkSeed,
109+ nondeterministicSeed,
107110 });
108111 }
109112
@@ -114,11 +117,12 @@ class SetKeys extends React.Component {
114117
115118 const validPoint = need.pointCursor(props);
116119
120+ // TODO: move this to a lib for validating things
117121 const hexRegExp = /[0-9A-Fa-f]{64}/g;
118122
119− if (hexRegExp.test(state.networkSeed)) {
123+ if (hexRegExp.test(state.newNetworkSeed)) {
120124 // derive network keys
121− const pair = kg.deriveNetworkKeys(state.networkSeed);
125+ const pair = kg.deriveNetworkKeys(state.newNetworkSeed);
122126
123127 const pencr = addHexPrefix(pair.crypt.public);
124128 const pauth = addHexPrefix(pair.auth.public);
@@ -142,7 +146,7 @@ class SetKeys extends React.Component {
142146 const { props, state } = this;
143147
144148 const canGenerate =
145− state.networkSeed.length === 64 && state.networkSeed.length === 64;
149+ state.newNetworkSeed.length === 64 && state.newNetworkSeed.length === 64;
146150
147151 const pointDetails = need.fromPointCache(props, state.point);
148152
@@ -191,7 +195,7 @@ class SetKeys extends React.Component {
191195 // Tx
192196 canGenerate={canGenerate}
193197 createUnsignedTxn={this.createUnsignedTxn}
194− newNetworkSeed={state.networkSeed}
198+ newNetworkSeed={state.newNetworkSeed}
195199 newRevision={parseInt(pointDetails.keyRevisionNumber) + 1}
196200 />
197201 </Col>
src/bridge/views/ViewPoint.js+2−1
@@ -71,7 +71,8 @@ class ViewPoint extends React.Component {
7171 className={'mt-8'}
7272 disabled={valid === false}
7373 onClick={() => {
74− setPointCursor(Maybe.Just(ob.patp2dec(pointName)));
74+ setPointCursor(Maybe.Just(parseInt(ob.patp2dec(pointName), 10)));
75+ // ^ pointCursor expects native number type, not string
7576 history.popAndPush(ROUTE_NAMES.SHIP);
7677 }}>
7778 {'Continue →'}