Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F10615130
rpcdump.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
11 KB
Subscribers
None
rpcdump.cpp
View Options
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include
"base58.h"
#include
"rpcserver.h"
#include
"init.h"
#include
"main.h"
#include
"sync.h"
#include
"wallet.h"
#include
<fstream>
#include
<stdint.h>
#include
<boost/algorithm/string.hpp>
#include
<boost/date_time/posix_time/posix_time.hpp>
#include
<boost/lexical_cast.hpp>
#include
"json/json_spirit_value.h"
using
namespace
json_spirit
;
using
namespace
std
;
void
EnsureWalletIsUnlocked
();
std
::
string
static
EncodeDumpTime
(
int64_t
nTime
)
{
return
DateTimeStrFormat
(
"%Y-%m-%"
PRId64
"T%H:%M:%SZ"
,
nTime
);
}
int64_t
static
DecodeDumpTime
(
const
std
::
string
&
str
)
{
static
boost
::
posix_time
::
time_input_facet
facet
(
"%Y-%m-%dT%H:%M:%SZ"
);
static
const
boost
::
posix_time
::
ptime
epoch
=
boost
::
posix_time
::
from_time_t
(
0
);
const
std
::
locale
loc
(
std
::
locale
::
classic
(),
&
facet
);
std
::
istringstream
iss
(
str
);
iss
.
imbue
(
loc
);
boost
::
posix_time
::
ptime
ptime
(
boost
::
date_time
::
not_a_date_time
);
iss
>>
ptime
;
if
(
ptime
.
is_not_a_date_time
())
return
0
;
return
(
ptime
-
epoch
).
total_seconds
();
}
std
::
string
static
EncodeDumpString
(
const
std
::
string
&
str
)
{
std
::
stringstream
ret
;
BOOST_FOREACH
(
unsigned
char
c
,
str
)
{
if
(
c
<=
32
||
c
>=
128
||
c
==
'%'
)
{
ret
<<
'%'
<<
HexStr
(
&
c
,
&
c
+
1
);
}
else
{
ret
<<
c
;
}
}
return
ret
.
str
();
}
std
::
string
DecodeDumpString
(
const
std
::
string
&
str
)
{
std
::
stringstream
ret
;
for
(
unsigned
int
pos
=
0
;
pos
<
str
.
length
();
pos
++
)
{
unsigned
char
c
=
str
[
pos
];
if
(
c
==
'%'
&&
pos
+
2
<
str
.
length
())
{
c
=
(((
str
[
pos
+
1
]
>>
6
)
*
9
+
((
str
[
pos
+
1
]
-
'0'
)
&
15
))
<<
4
)
|
((
str
[
pos
+
2
]
>>
6
)
*
9
+
((
str
[
pos
+
2
]
-
'0'
)
&
15
));
pos
+=
2
;
}
ret
<<
c
;
}
return
ret
.
str
();
}
Value
importprivkey
(
const
Array
&
params
,
bool
fHelp
)
{
if
(
fHelp
||
params
.
size
()
<
1
||
params
.
size
()
>
3
)
throw
runtime_error
(
"importprivkey
\"
bitcoinprivkey
\"
(
\"
label
\"
rescan )
\n
"
"
\n
Adds a private key (as returned by dumpprivkey) to your wallet.
\n
"
"
\n
Arguments:
\n
"
"1.
\"
bitcoinprivkey
\"
(string, required) The private key (see dumpprivkey)
\n
"
"2.
\"
label
\"
(string, optional) an optional label
\n
"
"3. rescan (boolean, optional, default=true) Rescan the wallet for transactions
\n
"
"
\n
Examples:
\n
"
"
\n
Dump a private key
\n
"
+
HelpExampleCli
(
"dumpprivkey"
,
"
\"
myaddress
\"
"
)
+
"
\n
Import the private key
\n
"
+
HelpExampleCli
(
"importprivkey"
,
"
\"
mykey
\"
"
)
+
"
\n
Import using a label
\n
"
+
HelpExampleCli
(
"importprivkey"
,
"
\"
mykey
\"
\"
testing
\"
false"
)
+
"
\n
As a json rpc call
\n
"
+
HelpExampleRpc
(
"importprivkey"
,
"
\"
mykey
\"
,
\"
testing
\"
, false"
)
);
string
strSecret
=
params
[
0
].
get_str
();
string
strLabel
=
""
;
if
(
params
.
size
()
>
1
)
strLabel
=
params
[
1
].
get_str
();
// Whether to perform rescan after import
bool
fRescan
=
true
;
if
(
params
.
size
()
>
2
)
fRescan
=
params
[
2
].
get_bool
();
CBitcoinSecret
vchSecret
;
bool
fGood
=
vchSecret
.
SetString
(
strSecret
);
if
(
!
fGood
)
throw
JSONRPCError
(
RPC_INVALID_ADDRESS_OR_KEY
,
"Invalid private key"
);
CKey
key
=
vchSecret
.
GetKey
();
CPubKey
pubkey
=
key
.
GetPubKey
();
CKeyID
vchAddress
=
pubkey
.
GetID
();
{
LOCK2
(
cs_main
,
pwalletMain
->
cs_wallet
);
pwalletMain
->
MarkDirty
();
pwalletMain
->
SetAddressBook
(
vchAddress
,
strLabel
,
"receive"
);
// Don't throw error in case a key is already there
if
(
pwalletMain
->
HaveKey
(
vchAddress
))
return
Value
::
null
;
if
(
!
pwalletMain
->
AddKeyPubKey
(
key
,
pubkey
))
throw
JSONRPCError
(
RPC_WALLET_ERROR
,
"Error adding key to wallet"
);
if
(
fRescan
)
{
pwalletMain
->
ScanForWalletTransactions
(
chainActive
.
Genesis
(),
true
);
pwalletMain
->
ReacceptWalletTransactions
();
}
}
return
Value
::
null
;
}
Value
importwallet
(
const
Array
&
params
,
bool
fHelp
)
{
if
(
fHelp
||
params
.
size
()
!=
1
)
throw
runtime_error
(
"importwallet
\"
filename
\"\n
"
"
\n
Imports keys from a wallet dump file (see dumpwallet).
\n
"
"
\n
Arguments:
\n
"
"1.
\"
filename
\"
(string, required) The wallet file
\n
"
"
\n
Examples:
\n
"
"
\n
Dump the wallet
\n
"
+
HelpExampleCli
(
"dumpwallet"
,
"
\"
test
\"
"
)
+
"
\n
Import the wallet
\n
"
+
HelpExampleCli
(
"importwallet"
,
"
\"
test
\"
"
)
+
"
\n
Import using the json rpc call
\n
"
+
HelpExampleRpc
(
"importwallet"
,
"
\"
test
\"
"
)
);
EnsureWalletIsUnlocked
();
ifstream
file
;
file
.
open
(
params
[
0
].
get_str
().
c_str
());
if
(
!
file
.
is_open
())
throw
JSONRPCError
(
RPC_INVALID_PARAMETER
,
"Cannot open wallet dump file"
);
int64_t
nTimeBegin
=
chainActive
.
Tip
()
->
nTime
;
bool
fGood
=
true
;
while
(
file
.
good
())
{
std
::
string
line
;
std
::
getline
(
file
,
line
);
if
(
line
.
empty
()
||
line
[
0
]
==
'#'
)
continue
;
std
::
vector
<
std
::
string
>
vstr
;
boost
::
split
(
vstr
,
line
,
boost
::
is_any_of
(
" "
));
if
(
vstr
.
size
()
<
2
)
continue
;
CBitcoinSecret
vchSecret
;
if
(
!
vchSecret
.
SetString
(
vstr
[
0
]))
continue
;
CKey
key
=
vchSecret
.
GetKey
();
CPubKey
pubkey
=
key
.
GetPubKey
();
CKeyID
keyid
=
pubkey
.
GetID
();
if
(
pwalletMain
->
HaveKey
(
keyid
))
{
LogPrintf
(
"Skipping import of %s (key already present)
\n
"
,
CBitcoinAddress
(
keyid
).
ToString
().
c_str
());
continue
;
}
int64_t
nTime
=
DecodeDumpTime
(
vstr
[
1
]);
std
::
string
strLabel
;
bool
fLabel
=
true
;
for
(
unsigned
int
nStr
=
2
;
nStr
<
vstr
.
size
();
nStr
++
)
{
if
(
boost
::
algorithm
::
starts_with
(
vstr
[
nStr
],
"#"
))
break
;
if
(
vstr
[
nStr
]
==
"change=1"
)
fLabel
=
false
;
if
(
vstr
[
nStr
]
==
"reserve=1"
)
fLabel
=
false
;
if
(
boost
::
algorithm
::
starts_with
(
vstr
[
nStr
],
"label="
))
{
strLabel
=
DecodeDumpString
(
vstr
[
nStr
].
substr
(
6
));
fLabel
=
true
;
}
}
LogPrintf
(
"Importing %s...
\n
"
,
CBitcoinAddress
(
keyid
).
ToString
().
c_str
());
if
(
!
pwalletMain
->
AddKeyPubKey
(
key
,
pubkey
))
{
fGood
=
false
;
continue
;
}
pwalletMain
->
mapKeyMetadata
[
keyid
].
nCreateTime
=
nTime
;
if
(
fLabel
)
pwalletMain
->
SetAddressBook
(
keyid
,
strLabel
,
"receive"
);
nTimeBegin
=
std
::
min
(
nTimeBegin
,
nTime
);
}
file
.
close
();
CBlockIndex
*
pindex
=
chainActive
.
Tip
();
while
(
pindex
&&
pindex
->
pprev
&&
pindex
->
nTime
>
nTimeBegin
-
7200
)
pindex
=
pindex
->
pprev
;
LogPrintf
(
"Rescanning last %i blocks
\n
"
,
chainActive
.
Height
()
-
pindex
->
nHeight
+
1
);
pwalletMain
->
ScanForWalletTransactions
(
pindex
);
pwalletMain
->
ReacceptWalletTransactions
();
pwalletMain
->
MarkDirty
();
if
(
!
fGood
)
throw
JSONRPCError
(
RPC_WALLET_ERROR
,
"Error adding some keys to wallet"
);
return
Value
::
null
;
}
Value
dumpprivkey
(
const
Array
&
params
,
bool
fHelp
)
{
if
(
fHelp
||
params
.
size
()
!=
1
)
throw
runtime_error
(
"dumpprivkey
\"
bitcoinaddress
\"\n
"
"
\n
Reveals the private key corresponding to 'bitcoinaddress'.
\n
"
"Then the importprivkey can be used with this output
\n
"
"
\n
Arguments:
\n
"
"1.
\"
bitcoinaddress
\"
(string, required) The bitcoin address for the private key
\n
"
"
\n
Result:
\n
"
"
\"
key
\"
(string) The private key
\n
"
"
\n
Examples:
\n
"
+
HelpExampleCli
(
"dumpprivkey"
,
"
\"
myaddress
\"
"
)
+
HelpExampleCli
(
"importprivkey"
,
"
\"
mykey
\"
"
)
+
HelpExampleRpc
(
"dumpprivkey"
,
"
\"
myaddress
\"
"
)
);
EnsureWalletIsUnlocked
();
string
strAddress
=
params
[
0
].
get_str
();
CBitcoinAddress
address
;
if
(
!
address
.
SetString
(
strAddress
))
throw
JSONRPCError
(
RPC_INVALID_ADDRESS_OR_KEY
,
"Invalid Bitcoin address"
);
CKeyID
keyID
;
if
(
!
address
.
GetKeyID
(
keyID
))
throw
JSONRPCError
(
RPC_TYPE_ERROR
,
"Address does not refer to a key"
);
CKey
vchSecret
;
if
(
!
pwalletMain
->
GetKey
(
keyID
,
vchSecret
))
throw
JSONRPCError
(
RPC_WALLET_ERROR
,
"Private key for address "
+
strAddress
+
" is not known"
);
return
CBitcoinSecret
(
vchSecret
).
ToString
();
}
Value
dumpwallet
(
const
Array
&
params
,
bool
fHelp
)
{
if
(
fHelp
||
params
.
size
()
!=
1
)
throw
runtime_error
(
"dumpwallet
\"
filename
\"\n
"
"
\n
Dumps all wallet keys in a human-readable format.
\n
"
"
\n
Arguments:
\n
"
"1.
\"
filename
\"
(string, required) The filename
\n
"
"
\n
Examples:
\n
"
+
HelpExampleCli
(
"dumpwallet"
,
"
\"
test
\"
"
)
+
HelpExampleRpc
(
"dumpwallet"
,
"
\"
test
\"
"
)
);
EnsureWalletIsUnlocked
();
ofstream
file
;
file
.
open
(
params
[
0
].
get_str
().
c_str
());
if
(
!
file
.
is_open
())
throw
JSONRPCError
(
RPC_INVALID_PARAMETER
,
"Cannot open wallet dump file"
);
std
::
map
<
CKeyID
,
int64_t
>
mapKeyBirth
;
std
::
set
<
CKeyID
>
setKeyPool
;
pwalletMain
->
GetKeyBirthTimes
(
mapKeyBirth
);
pwalletMain
->
GetAllReserveKeys
(
setKeyPool
);
// sort time/key pairs
std
::
vector
<
std
::
pair
<
int64_t
,
CKeyID
>
>
vKeyBirth
;
for
(
std
::
map
<
CKeyID
,
int64_t
>::
const_iterator
it
=
mapKeyBirth
.
begin
();
it
!=
mapKeyBirth
.
end
();
it
++
)
{
vKeyBirth
.
push_back
(
std
::
make_pair
(
it
->
second
,
it
->
first
));
}
mapKeyBirth
.
clear
();
std
::
sort
(
vKeyBirth
.
begin
(),
vKeyBirth
.
end
());
// produce output
file
<<
strprintf
(
"# Wallet dump created by Bitcoin %s (%s)
\n
"
,
CLIENT_BUILD
.
c_str
(),
CLIENT_DATE
.
c_str
());
file
<<
strprintf
(
"# * Created on %s
\n
"
,
EncodeDumpTime
(
GetTime
()).
c_str
());
file
<<
strprintf
(
"# * Best block at time of backup was %i (%s),
\n
"
,
chainActive
.
Height
(),
chainActive
.
Tip
()
->
GetBlockHash
().
ToString
().
c_str
());
file
<<
strprintf
(
"# mined on %s
\n
"
,
EncodeDumpTime
(
chainActive
.
Tip
()
->
nTime
).
c_str
());
file
<<
"
\n
"
;
for
(
std
::
vector
<
std
::
pair
<
int64_t
,
CKeyID
>
>::
const_iterator
it
=
vKeyBirth
.
begin
();
it
!=
vKeyBirth
.
end
();
it
++
)
{
const
CKeyID
&
keyid
=
it
->
second
;
std
::
string
strTime
=
EncodeDumpTime
(
it
->
first
);
std
::
string
strAddr
=
CBitcoinAddress
(
keyid
).
ToString
();
CKey
key
;
if
(
pwalletMain
->
GetKey
(
keyid
,
key
))
{
if
(
pwalletMain
->
mapAddressBook
.
count
(
keyid
))
{
file
<<
strprintf
(
"%s %s label=%s # addr=%s
\n
"
,
CBitcoinSecret
(
key
).
ToString
().
c_str
(),
strTime
.
c_str
(),
EncodeDumpString
(
pwalletMain
->
mapAddressBook
[
keyid
].
name
).
c_str
(),
strAddr
.
c_str
());
}
else
if
(
setKeyPool
.
count
(
keyid
))
{
file
<<
strprintf
(
"%s %s reserve=1 # addr=%s
\n
"
,
CBitcoinSecret
(
key
).
ToString
().
c_str
(),
strTime
.
c_str
(),
strAddr
.
c_str
());
}
else
{
file
<<
strprintf
(
"%s %s change=1 # addr=%s
\n
"
,
CBitcoinSecret
(
key
).
ToString
().
c_str
(),
strTime
.
c_str
(),
strAddr
.
c_str
());
}
}
}
file
<<
"
\n
"
;
file
<<
"# End of dump
\n
"
;
file
.
close
();
return
Value
::
null
;
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 23, 09:58 (1 d, 10 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4546757
Default Alt Text
rpcdump.cpp (11 KB)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment