@@ -15,6 +15,7 @@ mod keys_proto {
15
15
include ! ( concat!( env!( "OUT_DIR" ) , "/keys_proto.rs" ) ) ;
16
16
}
17
17
18
+ /// Defines the configuration types supported by the API.
18
19
#[ derive( Debug , StructOpt ) ]
19
20
pub enum Profile {
20
21
Test ,
@@ -34,7 +35,7 @@ impl FromStr for Profile {
34
35
}
35
36
}
36
37
37
- /// The way things can go wrong when calling [`initialize `].
38
+ /// The way things can go wrong when calling [`init `].
38
39
#[ derive( Error , Debug ) ]
39
40
pub enum InitializationError {
40
41
#[ error( "repository creation failed: {0}" ) ]
@@ -50,50 +51,29 @@ pub enum InitializationError {
50
51
#[ error( "key encoding failed: {0}" ) ]
51
52
PrivateKeyEncodingFailed ( prost:: EncodeError ) ,
52
53
#[ error( "config serialization failed: {0}" ) ]
53
- ConfigWritingFailed ( serde_json :: Error ) ,
54
+ ConfigWritingFailed ( Box < dyn std :: error :: Error + ' static > ) ,
54
55
}
55
56
56
57
/// Creates the IPFS_PATH directory structure and creates a new compatible configuration file with
57
- /// RSA key of length `bits`.
58
- pub fn initialize (
58
+ /// RSA key of length `bits`. Returns the Peer ID.
59
+ pub fn init (
59
60
ipfs_path : & Path ,
60
61
bits : NonZeroU16 ,
61
62
profiles : Vec < Profile > ,
62
- ) -> Result < ( ) , InitializationError > {
63
- // This check is done here to avoid an empty config file being created in the case of an
64
- // unsupported input.
65
- if profiles. len ( ) != 1 {
66
- unimplemented ! ( "Multiple profiles are currently unsupported!" ) ;
67
- }
68
-
69
- let config_path = ipfs_path. join ( "config" ) ;
70
-
71
- fs:: create_dir_all ( & ipfs_path)
72
- . map_err ( InitializationError :: DirectoryCreationFailed )
73
- . and_then ( |_| {
74
- fs:: File :: create ( & config_path) . map_err ( InitializationError :: ConfigCreationFailed )
75
- } )
76
- . and_then ( |config_file| create ( config_file, bits, profiles) )
77
- }
78
-
79
- fn create (
80
- config : File ,
81
- bits : NonZeroU16 ,
82
- profiles : Vec < Profile > ,
83
- ) -> Result < ( ) , InitializationError > {
63
+ ) -> Result < String , InitializationError > {
84
64
use multibase:: Base :: Base64Pad ;
85
65
use prost:: Message ;
86
- use std:: io:: BufWriter ;
66
+ use std:: fs:: OpenOptions ;
67
+ use std:: io:: { BufWriter , Write } ;
87
68
88
- let api_addr = match profiles[ 0 ] {
89
- Profile :: Test => multiaddr ! ( Ip4 ( [ 127 , 0 , 0 , 1 ] ) , Tcp ( 0u16 ) ) ,
90
- Profile :: Default => multiaddr ! ( Ip4 ( [ 127 , 0 , 0 , 1 ] ) , Tcp ( 4004u16 ) ) ,
91
- } ;
69
+ if profiles. len ( ) != 1 {
70
+ unimplemented ! ( "Multiple profiles are currently unsupported!" )
71
+ }
92
72
93
73
let bits = bits. get ( ) ;
94
74
95
75
if bits < 2048 || bits > 16 * 1024 {
96
- // ring will not accept a less than 2048 key
76
+ // Ring won't accept less than a 2048 bit key.
97
77
return Err ( InitializationError :: InvalidRsaKeyLength ( bits) ) ;
98
78
}
99
79
@@ -135,9 +115,14 @@ fn create(
135
115
136
116
let private_key = Base64Pad . encode ( & private_key) ;
137
117
118
+ let api_addr = match profiles[ 0 ] {
119
+ Profile :: Test => multiaddr ! ( Ip4 ( [ 127 , 0 , 0 , 1 ] ) , Tcp ( 0u16 ) ) ,
120
+ Profile :: Default => multiaddr ! ( Ip4 ( [ 127 , 0 , 0 , 1 ] ) , Tcp ( 4004u16 ) ) ,
121
+ } ;
122
+
138
123
let config_contents = CompatibleConfigFile {
139
124
identity : Identity {
140
- peer_id,
125
+ peer_id : peer_id . clone ( ) ,
141
126
private_key,
142
127
} ,
143
128
addresses : Addresses {
@@ -146,10 +131,38 @@ fn create(
146
131
} ,
147
132
} ;
148
133
149
- serde_json:: to_writer_pretty ( BufWriter :: new ( config) , & config_contents)
150
- . map_err ( InitializationError :: ConfigWritingFailed ) ?;
134
+ let config_path = ipfs_path. join ( "config" ) ;
151
135
152
- Ok ( ( ) )
136
+ let config_file = fs:: create_dir_all ( & ipfs_path)
137
+ . map_err ( InitializationError :: DirectoryCreationFailed )
138
+ . and_then ( |_| {
139
+ OpenOptions :: new ( )
140
+ . write ( true )
141
+ . create_new ( true )
142
+ . open ( & config_path)
143
+ . map_err ( InitializationError :: ConfigCreationFailed )
144
+ } ) ?;
145
+
146
+ let mut writer = BufWriter :: new ( config_file) ;
147
+
148
+ serde_json:: to_writer_pretty ( & mut writer, & config_contents)
149
+ . map_err ( |e| InitializationError :: ConfigWritingFailed ( Box :: new ( e) ) ) ?;
150
+
151
+ writer
152
+ . flush ( )
153
+ . map_err ( |e| InitializationError :: ConfigWritingFailed ( Box :: new ( e) ) ) ?;
154
+
155
+ Ok ( peer_id)
156
+ }
157
+
158
+ /// The facade for the configuration of the API.
159
+ pub struct Config {
160
+ /// Keypair for the ipfs node.
161
+ pub keypair : ipfs:: Keypair ,
162
+ /// Peer addresses for the ipfs node.
163
+ pub swarm : Vec < Multiaddr > ,
164
+ /// Address to run the API daemon on.
165
+ pub api_addr : Multiaddr ,
153
166
}
154
167
155
168
/// Things which can go wrong when loading a `go-ipfs` compatible configuration file.
@@ -172,27 +185,30 @@ pub enum LoadingError {
172
185
/// Returns only the keypair and listening addresses or [`LoadingError`] but this should be
173
186
/// extended to contain the bootstrap nodes at least later when we need to support those for
174
187
/// testing purposes.
175
- pub fn load ( config : File ) -> Result < ( ipfs :: Keypair , Vec < Multiaddr > , Multiaddr ) , LoadingError > {
188
+ pub fn load ( config : File ) -> Result < Config , LoadingError > {
176
189
use std:: io:: BufReader ;
177
190
178
- let CompatibleConfigFile {
179
- identity,
180
- addresses,
181
- } = serde_json:: from_reader ( BufReader :: new ( config) )
191
+ let config_file: CompatibleConfigFile = serde_json:: from_reader ( BufReader :: new ( config) )
182
192
. map_err ( LoadingError :: ConfigurationFileFormat ) ?;
183
193
184
- let kp = identity. load_keypair ( ) ?;
194
+ let kp = config_file . identity . load_keypair ( ) ?;
185
195
186
196
let peer_id = kp. public ( ) . into_peer_id ( ) . to_string ( ) ;
187
197
188
- if peer_id != identity. peer_id {
198
+ if peer_id != config_file . identity . peer_id {
189
199
return Err ( LoadingError :: PeerIdMismatch {
190
200
loaded : peer_id,
191
- stored : identity. peer_id ,
201
+ stored : config_file . identity . peer_id ,
192
202
} ) ;
193
203
}
194
204
195
- Ok ( ( kp, addresses. swarm , addresses. api ) )
205
+ let config = Config {
206
+ keypair : kp,
207
+ swarm : config_file. addresses . swarm ,
208
+ api_addr : config_file. addresses . api ,
209
+ } ;
210
+
211
+ Ok ( config)
196
212
}
197
213
198
214
/// Converts a PEM format to DER where PEM is a container for Base64 data with padding, starting on
0 commit comments