on 8011c59 help sign in
bridge/src/views/SetKeys.js
212 lines 5.4 kB history raw
1import React from 'react';
2import Maybe from 'folktale/maybe';
3import * as azimuth from 'azimuth-js';
4import * as ob from 'urbit-ob';
5import * as need from '../lib/need';
6import * as kg from 'urbit-key-generation/dist';
7import { Row, Col, H1, P, Warning, CheckboxButton } from '../components/Base';
9import StatelessTransaction from '../components/StatelessTransaction';
10import { attemptNetworkSeedDerivation } from '../lib/keys';
12import { addHexPrefix } from '../lib/wallet';
13import { compose } from '../lib/lib';
15import { withNetwork } from '../store/network';
16import { withWallet } from '../store/wallet';
17import { withPointCursor } from '../store/pointCursor';
18import { withPointCache } from '../store/pointCache';
20class SetKeys extends React.Component {
21 constructor(props) {
22 super(props);
24 const point = need.pointCursor(props);
26 this.state = {
27 auth: '',
28 encr: '',
29 newNetworkSeed: '',
30 nondeterministicSeed: false,
31 point: point,
32 cryptoSuiteVersion: 1,
33 discontinuity: false,
34 isManagementSeed: false,
35 };
37 this.toggleDiscontinuity = this.toggleDiscontinuity.bind(this);
38 // Transaction
39 this.createUnsignedTxn = this.createUnsignedTxn.bind(this);
40 }
42 toggleDiscontinuity() {
43 this.setState({ discontinuity: !this.state.discontinuity });
44 }
46 componentDidMount() {
47 const { props } = this;
49 this.deriveSeed();
51 const addr = need.address(props);
53 this.determineManagementSeed(props.contracts.value, addr);
54 }
56 async determineManagementSeed(ctrcs, addr) {
57 const managing = await azimuth.azimuth.getManagerFor(ctrcs, addr);
59 this.setState({
60 isManagementSeed: managing.length !== 0,
61 });
62 }
64 //TODO use web3.utils.randomHex when it gets fixed, see web3.js#1490
65 randomHex(len) {
66 let hex = '';
68 for (var i = 0; i < len; i++) {
69 hex =
70 hex +
71 [
72 '0',
73 '1',
74 '2',
75 '3',
76 '4',
77 '5',
78 '6',
79 '7',
80 '8',
81 '9',
82 'A',
83 'B',
84 'C',
85 'D',
86 'E',
87 'F',
88 ][Math.floor(Math.random() * 16)];
89 }
91 return hex;
92 }
94 async deriveSeed() {
95 const next = true;
96 let nondeterministicSeed = false;
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 });
107 this.setState({
108 newNetworkSeed,
109 nondeterministicSeed,
110 });
111 }
113 createUnsignedTxn() {
114 const { state, props } = this;
116 const validContracts = need.contracts(props);
118 const validPoint = need.pointCursor(props);
120 // TODO: move this to a lib for validating things
121 const hexRegExp = /[0-9A-Fa-f]{64}/g;
123 if (hexRegExp.test(state.newNetworkSeed)) {
124 // derive network keys
125 const pair = kg.deriveNetworkKeys(state.newNetworkSeed);
127 const pencr = addHexPrefix(pair.crypt.public);
128 const pauth = addHexPrefix(pair.auth.public);
130 const txn = azimuth.ecliptic.configureKeys(
131 validContracts,
132 validPoint,
133 pencr,
134 pauth,
135 1,
136 state.discontinuity
137 );
139 return Maybe.Just(txn);
140 }
142 return Maybe.Nothing();
143 }
145 render() {
146 const { props, state } = this;
148 const canGenerate =
149 state.newNetworkSeed.length === 64 && state.newNetworkSeed.length === 64;
151 const pointDetails = need.fromPointCache(props, state.point);
153 return (
154 <Row>
155 <Col>
156 <H1>
157 {'Set Network Keys For '} <code>{`${ob.patp(state.point)}`}</code>
158 </H1>
160 <P className="mt-10">
161 {`Set new authentication and encryption keys for your Arvo ship.`}
162 </P>
164 {state.nondeterministicSeed && (
165 <Warning>
166 <h3 className={'mb-2'}>{'Warning'}</h3>
167 {`Your network seed could not be derived automatically. We've
168 generated a random one for you, so you must download your Arvo
169 keyfile during this session after setting your keys.`}
170 </Warning>
171 )}
173 {pointDetails.keyRevisionNumber === 0 ? (
174 <Warning>
175 <h3 className={'mb-2'}>{'Warning'}</h3>
176 {'Once these keys have been set, your point is considered ' +
177 "'linked'. This operation cannot be undone."}
178 </Warning>
179 ) : (
180 <div />
181 )}
183 <CheckboxButton
184 className="mt-8"
185 onToggle={this.toggleDiscontinuity}
186 state={state.discontinuity}
187 label={`I have lost important off-chain data relating to this point
188 and need to do a hard reset.
189 (For example, rebooting an Arvo ship.)`}
190 />
192 <StatelessTransaction
193 // Upper scope
194 {...props}
195 // Tx
196 canGenerate={canGenerate}
197 createUnsignedTxn={this.createUnsignedTxn}
198 newNetworkSeed={state.newNetworkSeed}
199 newRevision={parseInt(pointDetails.keyRevisionNumber) + 1}
200 />
201 </Col>
202 </Row>
203 );
204 }
207export default compose(
208 withNetwork,
209 withWallet,
210 withPointCursor,
211 withPointCache
212)(SetKeys);