Esempio n. 1
0
/**
 * Loads a CarePackage object from a string.
 */
tABC_CC ABC_CarePackageDecode(tABC_CarePackage **ppSelf,
                              char *szCarePackage,
                              tABC_Error *pError)
{
    tABC_CC cc = ABC_CC_Ok;
    tABC_CarePackage *pSelf = NULL;
    json_t  *pJSON_Root     = NULL;
    json_t  *pJSON_SNRP2    = NULL;
    json_t  *pJSON_SNRP3    = NULL;
    json_t  *pJSON_SNRP4    = NULL;
    int     e;

    // Allocate self:
    ABC_NEW(pSelf, tABC_CarePackage);

    // Parse the JSON:
    json_error_t error;
    pJSON_Root = json_loads(szCarePackage, 0, &error);
    ABC_CHECK_ASSERT(pJSON_Root != NULL, ABC_CC_JSONError, "Error parsing CarePackage JSON");
    ABC_CHECK_ASSERT(json_is_object(pJSON_Root), ABC_CC_JSONError, "Error parsing CarePackage JSON");

    // Unpack the contents:
    e = json_unpack(pJSON_Root, "{s:o, s:o, s:o, s?o}",
                    JSON_ACCT_SNRP2_FIELD, &pJSON_SNRP2,
                    JSON_ACCT_SNRP3_FIELD, &pJSON_SNRP3,
                    JSON_ACCT_SNRP4_FIELD, &pJSON_SNRP4,
                    JSON_ACCT_ERQ_FIELD,   &pSelf->ERQ);
    ABC_CHECK_SYS(!e, "Error parsing CarePackage JSON");

    // Decode SNRP's:
    ABC_CHECK_RET(ABC_CryptoCreateSNRPForServer(&pSelf->pSNRP1, pError));
    ABC_CHECK_RET(ABC_CryptoDecodeJSONObjectSNRP(pJSON_SNRP2, &pSelf->pSNRP2, pError));
    ABC_CHECK_RET(ABC_CryptoDecodeJSONObjectSNRP(pJSON_SNRP3, &pSelf->pSNRP3, pError));
    ABC_CHECK_RET(ABC_CryptoDecodeJSONObjectSNRP(pJSON_SNRP4, &pSelf->pSNRP4, pError));

    // Save everything:
    if (pSelf->ERQ)         json_incref(pSelf->ERQ);
    *ppSelf = pSelf;
    pSelf = NULL;

exit:
    if (pSelf)          ABC_CarePackageFree(pSelf);
    if (pJSON_Root)     json_decref(pJSON_Root);

    return cc;
}
Esempio n. 2
0
/**
 * Loads a LoginPackage object from a string.
 */
tABC_CC ABC_LoginPackageDecode(tABC_LoginPackage **ppSelf,
                               char *szLoginPackage,
                               tABC_Error *pError)
{
    tABC_CC cc = ABC_CC_Ok;
    tABC_LoginPackage *pSelf = NULL;
    json_t  *pJSON_Root     = NULL;
    int     e;

    // Allocate self:
    ABC_NEW(pSelf, tABC_LoginPackage);

    // Parse the JSON:
    json_error_t error;
    pJSON_Root = json_loads(szLoginPackage, 0, &error);
    ABC_CHECK_ASSERT(pJSON_Root != NULL, ABC_CC_JSONError, "Error parsing LoginPackage JSON");
    ABC_CHECK_ASSERT(json_is_object(pJSON_Root), ABC_CC_JSONError, "Error parsing LoginPackage JSON");

    // Unpack the contents:
    e = json_unpack(pJSON_Root, "{s?o, s?o, s:o, s?o, s?o}",
                    JSON_ACCT_EMK_LP2_FIELD,     &pSelf->EMK_LP2,
                    JSON_ACCT_EMK_LRA3_FIELD,    &pSelf->EMK_LRA3,
                    JSON_ACCT_ESYNCKEY_FIELD,    &pSelf->ESyncKey,
                    JSON_ACCT_ELP1_FIELD,        &pSelf->ELP1,
                    JSON_ACCT_ELRA1_FIELD,       &pSelf->ELRA1);
    ABC_CHECK_SYS(!e, "Error parsing LoginPackage JSON");

    // Save everything:
    if (pSelf->EMK_LP2)     json_incref(pSelf->EMK_LP2);
    if (pSelf->EMK_LRA3)    json_incref(pSelf->EMK_LRA3);
    if (pSelf->ESyncKey)    json_incref(pSelf->ESyncKey);
    if (pSelf->ELP1)        json_incref(pSelf->ELP1);
    if (pSelf->ELRA1)       json_incref(pSelf->ELRA1);
    *ppSelf = pSelf;
    pSelf = NULL;

exit:
    if (pSelf)          ABC_LoginPackageFree(pSelf);
    if (pJSON_Root)     json_decref(pJSON_Root);

    return cc;
}
Esempio n. 3
0
static
tABC_CC ABC_BridgeDoSweep(WatcherInfo *watcherInfo,
                          PendingSweep& sweep,
                          tABC_Error *pError)
{
    tABC_CC cc = ABC_CC_Ok;
    char *szID = NULL;
    char *szAddress = NULL;
    uint64_t funds = 0;
    abcd::unsigned_transaction utx;
    bc::transaction_output_type output;
    abcd::key_table keys;
    std::string malTxId, txId;

    // Find utxos for this address:
    auto utxos = watcherInfo->watcher.get_utxos(sweep.address);

    // Bail out if there are no funds to sweep:
    if (!utxos.size())
    {
        // Tell the GUI if there were funds in the past:
        if (watcherInfo->watcher.db().has_history(sweep.address))
        {
            if (sweep.fCallback)
            {
                sweep.fCallback(ABC_CC_Ok, NULL, 0);
            }
            else
            {
                if (watcherInfo->fAsyncCallback)
                {
                    tABC_AsyncBitCoinInfo info;
                    info.eventType = ABC_AsyncEventType_IncomingSweep;
                    info.sweepSatoshi = 0;
                    info.szTxID = NULL;
                    watcherInfo->fAsyncCallback(&info);
                }
            }
            sweep.done = true;
        }
        return ABC_CC_Ok;
    }

    // There are some utxos, so send them to ourselves:
    tABC_TxDetails details;
    memset(&details, 0, sizeof(tABC_TxDetails));
    details.amountSatoshi = 0;
    details.amountCurrency = 0;
    details.amountFeesAirbitzSatoshi = 0;
    details.amountFeesMinersSatoshi = 0;
    details.szName = const_cast<char*>("");
    details.szCategory = const_cast<char*>("");
    details.szNotes = const_cast<char*>("");
    details.attributes = 0x2;

    // Create a new receive request:
    ABC_CHECK_RET(ABC_TxCreateReceiveRequest(watcherInfo->wallet,
        &details, &szID, false, pError));
    ABC_CHECK_RET(ABC_TxGetRequestAddress(watcherInfo->wallet, szID,
        &szAddress, pError));

    // Build a transaction:
    utx.tx.version = 1;
    utx.tx.locktime = 0;
    for (auto &utxo : utxos)
    {
        bc::transaction_input_type input;
        input.sequence = 0xffffffff;
        input.previous_output = utxo.point;
        funds += utxo.value;
        utx.tx.inputs.push_back(input);
    }
    if (10000 < funds)
        funds -= 10000; // Ugh, hard-coded mining fee
    ABC_CHECK_ASSERT(!outputIsDust(funds), ABC_CC_InsufficientFunds, "Not enough funds");
    output.value = funds;
    ABC_CHECK_NEW(outputScriptForAddress(output.script, szAddress));
    utx.tx.outputs.push_back(output);

    // Now sign that:
    keys[sweep.address] = sweep.key;
    ABC_CHECK_SYS(abcd::gather_challenges(utx, watcherInfo->watcher), "gather_challenges");
    ABC_CHECK_SYS(abcd::sign_tx(utx, keys), "sign_tx");

    // Send:
    {
        bc::data_chunk raw_tx(satoshi_raw_size(utx.tx));
        bc::satoshi_save(utx.tx, raw_tx.begin());
        ABC_CHECK_NEW(broadcastTx(raw_tx));
    }

    // Save the transaction in the database:
    malTxId = bc::encode_hash(bc::hash_transaction(utx.tx));
    txId = ABC_BridgeNonMalleableTxId(utx.tx);
    ABC_CHECK_RET(ABC_TxSweepSaveTransaction(watcherInfo->wallet,
        txId.c_str(), malTxId.c_str(), funds, &details, pError));

    // Done:
    if (sweep.fCallback)
    {
        sweep.fCallback(ABC_CC_Ok, txId.c_str(), output.value);
    }
    else
    {
        if (watcherInfo->fAsyncCallback)
        {
            tABC_AsyncBitCoinInfo info;
            info.eventType = ABC_AsyncEventType_IncomingSweep;
            info.sweepSatoshi = output.value;
            info.szTxID = stringCopy(txId);
            watcherInfo->fAsyncCallback(&info);
            ABC_FREE_STR(info.szTxID);
        }
    }
    sweep.done = true;
    watcherInfo->watcher.send_tx(utx.tx);

exit:
    ABC_FREE_STR(szID);
    ABC_FREE_STR(szAddress);

    return cc;
}