@ -68,6 +68,7 @@ void AsyncRPCOperation_saplingmigration::main() {
}
}
bool AsyncRPCOperation_saplingmigration : : main_impl ( ) {
bool AsyncRPCOperation_saplingmigration : : main_impl ( ) {
LogPrint ( " zrpcunsafe " , " %s: Beginning AsyncRPCOperation_saplingmigration. \n " , getId ( ) ) ;
std : : vector < CSproutNotePlaintextEntry > sproutEntries ;
std : : vector < CSproutNotePlaintextEntry > sproutEntries ;
std : : vector < SaplingNoteEntry > saplingEntries ;
std : : vector < SaplingNoteEntry > saplingEntries ;
{
{
@ -83,7 +84,9 @@ bool AsyncRPCOperation_saplingmigration::main_impl() {
}
}
// If the remaining amount to be migrated is less than 0.01 ZEC, end the migration.
// If the remaining amount to be migrated is less than 0.01 ZEC, end the migration.
if ( availableFunds < CENT ) {
if ( availableFunds < CENT ) {
setMigrationResult ( 0 , 0 ) ;
LogPrint ( " zrpcunsafe " , " %s: Available Sprout balance (%s) less than required minimum (%s). Stopping. \n " ,
getId ( ) , FormatMoney ( availableFunds ) , FormatMoney ( CENT ) ) ;
setMigrationResult ( 0 , 0 , std : : vector < std : : string > ( ) ) ;
return true ;
return true ;
}
}
@ -95,12 +98,14 @@ bool AsyncRPCOperation_saplingmigration::main_impl() {
// Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds
// Up to the limit of 5, as many transactions are sent as are needed to migrate the remaining funds
int numTxCreated = 0 ;
int numTxCreated = 0 ;
CAmount amountMigrated = 0 ;
CAmount amountMigrated = 0 ;
std : : vector < std : : string > migrationTxIds ;
int noteIndex = 0 ;
int noteIndex = 0 ;
CCoinsViewCache coinsView ( pcoinsTip ) ;
CCoinsViewCache coinsView ( pcoinsTip ) ;
do {
do {
CAmount amountToSend = chooseAmount ( availableFunds ) ;
CAmount amountToSend = chooseAmount ( availableFunds ) ;
auto builder = TransactionBuilder ( consensusParams , targetHeight_ , MIGRATION_EXPIRY_DELTA , pwalletMain , pzcashParams ,
auto builder = TransactionBuilder ( consensusParams , targetHeight_ , MIGRATION_EXPIRY_DELTA , pwalletMain , pzcashParams ,
& coinsView , & cs_main ) ;
& coinsView , & cs_main ) ;
LogPrint ( " zrpcunsafe " , " %s: Beginning creating transaction with Sapling output amount=%s \n " , getId ( ) , FormatMoney ( amountToSend - FEE ) ) ;
std : : vector < CSproutNotePlaintextEntry > fromNotes ;
std : : vector < CSproutNotePlaintextEntry > fromNotes ;
CAmount fromNoteAmount = 0 ;
CAmount fromNoteAmount = 0 ;
while ( fromNoteAmount < amountToSend ) {
while ( fromNoteAmount < amountToSend ) {
@ -110,6 +115,15 @@ bool AsyncRPCOperation_saplingmigration::main_impl() {
}
}
availableFunds - = fromNoteAmount ;
availableFunds - = fromNoteAmount ;
for ( const CSproutNotePlaintextEntry & sproutEntry : fromNotes ) {
for ( const CSproutNotePlaintextEntry & sproutEntry : fromNotes ) {
std : : string data ( sproutEntry . plaintext . memo ( ) . begin ( ) , sproutEntry . plaintext . memo ( ) . end ( ) ) ;
LogPrint ( " zrpcunsafe " , " %s: Adding Sprout note input (txid=%s, vjoinsplit=%d, jsoutindex=%d, amount=%s, memo=%s) \n " ,
getId ( ) ,
sproutEntry . jsop . hash . ToString ( ) . substr ( 0 , 10 ) ,
sproutEntry . jsop . js ,
int ( sproutEntry . jsop . n ) , // uint8_t
FormatMoney ( sproutEntry . plaintext . value ( ) ) ,
HexStr ( data ) . substr ( 0 , 10 )
) ;
libzcash : : SproutNote sproutNote = sproutEntry . plaintext . note ( sproutEntry . address ) ;
libzcash : : SproutNote sproutNote = sproutEntry . plaintext . note ( sproutEntry . address ) ;
libzcash : : SproutSpendingKey sproutSk ;
libzcash : : SproutSpendingKey sproutSk ;
pwalletMain - > GetSproutSpendingKey ( sproutEntry . address , sproutSk ) ;
pwalletMain - > GetSproutSpendingKey ( sproutEntry . address , sproutSk ) ;
@ -128,21 +142,30 @@ bool AsyncRPCOperation_saplingmigration::main_impl() {
builder . AddSaplingOutput ( ovkForShieldingFromTaddr ( seed ) , migrationDestAddress , amountToSend - FEE ) ;
builder . AddSaplingOutput ( ovkForShieldingFromTaddr ( seed ) , migrationDestAddress , amountToSend - FEE ) ;
CTransaction tx = builder . Build ( ) . GetTxOrThrow ( ) ;
CTransaction tx = builder . Build ( ) . GetTxOrThrow ( ) ;
if ( isCancelled ( ) ) {
if ( isCancelled ( ) ) {
LogPrint ( " zrpcunsafe " , " %s: Canceled. Stopping. \n " , getId ( ) ) ;
break ;
break ;
}
}
pwalletMain - > AddPendingSaplingMigrationTx ( tx ) ;
pwalletMain - > AddPendingSaplingMigrationTx ( tx ) ;
LogPrint ( " zrpcunsafe " , " %s: Added pending migration transaction with txid=%s \n " , getId ( ) , tx . GetHash ( ) . ToString ( ) ) ;
+ + numTxCreated ;
+ + numTxCreated ;
amountMigrated + = amountToSend ;
amountMigrated + = amountToSend - FEE ;
migrationTxIds . push_back ( tx . GetHash ( ) . ToString ( ) ) ;
} while ( numTxCreated < 5 & & availableFunds > CENT ) ;
} while ( numTxCreated < 5 & & availableFunds > CENT ) ;
setMigrationResult ( numTxCreated , amountMigrated ) ;
LogPrint ( " zrpcunsafe " , " %s: Created %d transactions with total Sapling output amount=%s \n " , getId ( ) , numTxCreated , FormatMoney ( amountMigrated ) ) ;
setMigrationResult ( numTxCreated , amountMigrated , migrationTxIds ) ;
return true ;
return true ;
}
}
void AsyncRPCOperation_saplingmigration : : setMigrationResult ( int numTxCreated , CAmount amountMigrated ) {
void AsyncRPCOperation_saplingmigration : : setMigrationResult ( int numTxCreated , const CAmount & amountMigrated , const std : : vector < std : : string > & migrationTxIds ) {
UniValue res ( UniValue : : VOBJ ) ;
UniValue res ( UniValue : : VOBJ ) ;
res . push_back ( Pair ( " num_tx_created " , numTxCreated ) ) ;
res . push_back ( Pair ( " num_tx_created " , numTxCreated ) ) ;
res . push_back ( Pair ( " amount_migrated " , FormatMoney ( amountMigrated ) ) ) ;
res . push_back ( Pair ( " amount_migrated " , FormatMoney ( amountMigrated ) ) ) ;
UniValue txIds ( UniValue : : VARR ) ;
for ( const std : : string & txId : migrationTxIds ) {
txIds . push_back ( txId ) ;
}
res . push_back ( Pair ( " migration_txids " , txIds ) ) ;
set_result ( res ) ;
set_result ( res ) ;
}
}