on master help sign in
Merge pull request #164 from urbit/feat/extract-network

Extract network + bugfixes

commit23ed93be13f4b3b2a20bec78bde1694e5be51041 authorMatt Condon <mattgcondon@gmail.com> dateMon 17 Jun 2019, 16:12 (7 years ago) parent80d720c12e03e4
11 files changed+73−99
src/bridge/Bridge.js+3−28 src/bridge/components/StatelessTransaction.js+6−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+7 src/bridge/views/GenKeyfile.js+11−10 src/bridge/views/Points.js+7−28 src/bridge/views/SentTransaction.js−3 src/bridge/views/SetKeys.js+17−14 src/bridge/views/ViewPoint.js+2−1
src/bridge/Bridge.js+3−28
@@ -25,9 +25,7 @@ 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.
28+// NB(shrugs): modify these variables to change the default local state.
3129const shouldStubLocal = false;
3230const kIsStubbed = isDevelopment && shouldStubLocal;
3331const kInitialRoutes = kIsStubbed
@@ -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
@@ -93,26 +91,7 @@ const AllProviders = nest([
9391]);
9492
9593class Bridge extends React.Component {
96− constructor(props) {
97− super(props);
98−
99− this.state = {
100− networkSeedCache: null,
101− };
102−
103− this.setNetworkSeedCache = this.setNetworkSeedCache.bind(this);
104− }
105−
106− setNetworkSeedCache(networkSeed, revision) {
107− this.setState({
108− networkSeedCache: networkSeed,
109− networkRevisionCache: revision,
110− });
111− }
112−
11394 render() {
114− const { networkSeedCache, networkRevisionCache } = this.state;
115−
11695 return (
11796 <AllProviders
11897 initialRoutes={kInitialRoutes}
@@ -126,11 +105,7 @@ class Bridge extends React.Component {
126105 <Header />
127106
128107 <Row className={'row wrapper'}>
129− <Router
130− networkSeedCache={networkSeedCache}
131− networkRevisionCache={networkRevisionCache}
132− setNetworkSeedCache={this.setNetworkSeedCache}
133− />
108+ <Router />
134109
135110 <div className={'push'} />
136111 </Row>
src/bridge/components/StatelessTransaction.js+6−2
@@ -242,11 +242,15 @@ class StatelessTransaction extends React.Component {
242242 props.setTxnCursor(Just(Ok(txHash)));
243243
244244 let routeData = {};
245− if (props.networkSeed) {
246− props.setNetworkSeedCache(props.networkSeed);
245+ if (props.newNetworkSeed) {
246+ props.setNetworkSeed(Just(props.newNetworkSeed));
247247 routeData.promptKeyfile = true;
248248 }
249249
250+ if (props.newRevision) {
251+ props.setNetworkRevision(Just(props.newRevision));
252+ }
253+
250254 props.history.popAndPush(ROUTE_NAMES.SENT_TRANSACTION, routeData);
251255 })
252256 .catch(err => {
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+7
@@ -33,6 +33,8 @@ function _useWallet(
3333 const [wallet, _setWallet] = useState(initialWallet);
3434 const [urbitWallet, _setUrbitWallet] = useState(Maybe.Nothing());
3535 const [authMnemonic, setAuthMnemonic] = useState(initialMnemonic);
36+ const [networkSeed, setNetworkSeed] = useState(Maybe.Nothing());
37+ const [networkRevision, setNetworkRevision] = useState(Maybe.Nothing());
3638
3739 const setWalletType = walletType => {
3840 if (!includes(WALLET_TYPES, walletType)) {
@@ -89,6 +91,11 @@ function _useWallet(
8991 setUrbitWallet,
9092 authMnemonic,
9193 setAuthMnemonic,
94+ //
95+ networkSeed,
96+ setNetworkSeed,
97+ networkRevision,
98+ setNetworkRevision,
9299 };
93100}
94101
src/bridge/views/GenKeyfile.js+11−10
@@ -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,9 +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.networkRevisionCache ||
38− parseInt(pointDetails.keyRevisionNumber);
35+ const revision = this.props.networkRevision.matchWith({
36+ Nothing: () => parseInt(pointDetails.keyRevisionNumber),
37+ Just: p => p.value,
38+ });
3939
4040 return {
4141 point,
@@ -79,13 +79,14 @@ class GenKeyfile extends React.Component {
7979
8080 async deriveSeed() {
8181 const next = false;
82− let seed = await attemptSeedDerivation(next, this.props);
8382
84− if (seed.getOrElse('') === '' && this.props.networkSeedCache) {
85− seed = Maybe.Just(this.props.networkSeedCache);
86− }
83+ const seed = await attemptNetworkSeedDerivation(next, this.props);
8784
88− 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+ });
8990 }
9091
9192 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−14
@@ -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,9 +195,8 @@ class SetKeys extends React.Component {
191195 // Tx
192196 canGenerate={canGenerate}
193197 createUnsignedTxn={this.createUnsignedTxn}
194− networkSeed={state.networkSeed}
198+ newNetworkSeed={state.newNetworkSeed}
195199 newRevision={parseInt(pointDetails.keyRevisionNumber) + 1}
196− setNetworkSeedCache={props.setNetworkSeedCache}
197200 />
198201 </Col>
199202 </Row>
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 →'}