Example #1
0
void
CNameMemPool::removeConflicts (const CTransaction& tx,
                               std::list<CTransaction>& removed)
{
  AssertLockHeld (pool.cs);

  if (!tx.IsNamecoin ())
    return;

  BOOST_FOREACH (const CTxOut& txout, tx.vout)
    {
      const CNameScript nameOp(txout.scriptPubKey);
      if (nameOp.isNameOp () && nameOp.getNameOp () == OP_NAME_FIRSTUPDATE)
        {
          const valtype& name = nameOp.getOpName ();
          const NameTxMap::const_iterator mit = mapNameRegs.find (name);
          if (mit != mapNameRegs.end ())
            {
              const CTxMemPool::txiter mit2 = pool.mapTx.find (mit->second);
              assert (mit2 != pool.mapTx.end ());
              pool.removeRecursive (mit2->GetTx (), removed);
            }
        }
    }
}
Example #2
0
bool
BlockAssembler::TxAllowedForNamecoin (const CTransaction& tx) const
{
  if (!tx.IsNamecoin ())
    return true;

  bool nameOutFound = false;
  CNameScript nameOpOut;
  for (const auto& txOut : tx.vout)
    {
      const CNameScript op(txOut.scriptPubKey);
      if (op.isNameOp ())
        {
          nameOutFound = true;
          nameOpOut = op;
          break;
        }
    }

  if (nameOutFound && nameOpOut.getNameOp () == OP_NAME_FIRSTUPDATE)
    {
      bool nameNewFound = false;
      for (const auto& txIn : tx.vin)
        {
          Coin coin;
          if (!pcoinsTip->GetCoin (txIn.prevout, coin))
            continue;

          const CNameScript op(coin.out.scriptPubKey);
          if (op.isNameOp () && op.getNameOp () == OP_NAME_NEW)
            {
              const int minHeight = coin.nHeight + MIN_FIRSTUPDATE_DEPTH;
              if (minHeight > nHeight)
                return false;
              nameNewFound = true;
            }
        }

      /* If the name_new is not only immature but actually unconfirmed, then
         the GetCoin lookup above fails for it and we never reach the height
         check.  In this case, nameNewFound is false and we should not yet
         include the transaction in a mined block.  */
      if (!nameNewFound)
        return false;
    }

  return true;
}
Example #3
0
bool IsStandardTx(const CTransaction& tx, std::string& reason)
{
    if (!tx.IsNamecoin()
        && (tx.nVersion > CTransaction::CURRENT_VERSION || tx.nVersion < 1)) {
        reason = "version";
        return false;
    }

    // Extremely large transactions with lots of inputs can cost the network
    // almost as much to process as they cost the sender in fees, because
    // computing signature hashes is O(ninputs*txsize). Limiting transactions
    // to MAX_STANDARD_TX_SIZE mitigates CPU exhaustion attacks.
    unsigned int sz = tx.GetSerializeSize(SER_NETWORK, CTransaction::CURRENT_VERSION);
    if (sz >= MAX_STANDARD_TX_SIZE) {
        reason = "tx-size";
        return false;
    }

    BOOST_FOREACH(const CTxIn& txin, tx.vin)
    {
        // Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
        // keys. (remember the 520 byte limit on redeemScript size) That works
        // out to a (15*(33+1))+3=513 byte redeemScript, 513+1+15*(73+1)+3=1627
        // bytes of scriptSig, which we round off to 1650 bytes for some minor
        // future-proofing. That's also enough to spend a 20-of-20
        // CHECKMULTISIG scriptPubKey, though such a scriptPubKey is not
        // considered standard)
        if (txin.scriptSig.size() > 1650) {
            reason = "scriptsig-size";
            return false;
        }
        if (!txin.scriptSig.IsPushOnly()) {
            reason = "scriptsig-not-pushonly";
            return false;
        }
    }

    unsigned int nDataOut = 0;
    txnouttype whichType;
    BOOST_FOREACH(const CTxOut& txout, tx.vout) {
        if (!::IsStandard(txout.scriptPubKey, whichType)) {
            reason = "scriptpubkey";
            return false;
        }

        if (whichType == TX_NULL_DATA)
            nDataOut++;
        else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
            reason = "bare-multisig";
            return false;
        } else if (txout.IsDust(::minRelayTxFee)) {
            reason = "dust";
            return false;
        }
    }

    // only one OP_RETURN txout is permitted
    if (nDataOut > 1) {
        reason = "multi-op-return";
        return false;
    }

    return true;
}
Example #4
0
UniValue
name_pending (const UniValue& params, bool fHelp)
{
  if (fHelp || params.size () > 1)
    throw std::runtime_error (
        "name_pending (\"name\")\n"
        "\nList unconfirmed name operations in the mempool.\n"
        "\nIf a name is given, only check for operations on this name.\n"
        "\nArguments:\n"
        "1. \"name\"        (string, optional) only look for this name\n"
        "\nResult:\n"
        "[\n"
        "  {\n"
        "    \"op\": xxxx       (string) the operation being performed\n"
        "    \"name\": xxxx     (string) the name operated on\n"
        "    \"value\": xxxx    (string) the name's new value\n"
        "    \"txid\": xxxx     (string) the txid corresponding to the operation\n"
        "    \"ismine\": xxxx   (boolean) whether the name is owned by the wallet\n"
        "  },\n"
        "  ...\n"
        "]\n"
        + HelpExampleCli ("name_pending", "")
        + HelpExampleCli ("name_pending", "\"d/domob\"")
        + HelpExampleRpc ("name_pending", "")
      );

#ifdef ENABLE_WALLET
    LOCK2 (pwalletMain ? &pwalletMain->cs_wallet : NULL, mempool.cs);
#else
    LOCK (mempool.cs);
#endif

  std::vector<uint256> txHashes;
  if (params.size () == 0)
    mempool.queryHashes (txHashes);
  else
    {
      const std::string name = params[0].get_str ();
      const valtype vchName = ValtypeFromString (name);
      const uint256 txid = mempool.getTxForName (vchName);
      if (!txid.IsNull ())
        txHashes.push_back (txid);
    }

  UniValue arr(UniValue::VARR);
  for (std::vector<uint256>::const_iterator i = txHashes.begin ();
       i != txHashes.end (); ++i)
    {
      CTransaction tx;
      if (!mempool.lookup (*i, tx) || !tx.IsNamecoin ())
        continue;

      for (unsigned i = 0; i < tx.vout.size (); ++i)
        {
          const CNameScript op(tx.vout[i].scriptPubKey);
          if (!op.isNameOp () || !op.isAnyUpdate ())
            continue;

          const valtype vchName = op.getOpName ();
          const valtype vchValue = op.getOpValue ();

          const std::string name = ValtypeToString (vchName);
          const std::string value = ValtypeToString (vchValue);

          std::string strOp;
          switch (op.getNameOp ())
            {
            case OP_NAME_FIRSTUPDATE:
              strOp = "name_firstupdate";
              break;
            case OP_NAME_UPDATE:
              strOp = "name_update";
              break;
            default:
              assert (false);
            }

          UniValue obj(UniValue::VOBJ);
          obj.push_back (Pair ("op", strOp));
          obj.push_back (Pair ("name", name));
          obj.push_back (Pair ("value", value));
          obj.push_back (Pair ("txid", tx.GetHash ().GetHex ()));

#ifdef ENABLE_WALLET
          isminetype mine = ISMINE_NO;
          if (pwalletMain)
            mine = IsMine (*pwalletMain, op.getAddress ());
          const bool isMine = (mine & ISMINE_SPENDABLE);
          obj.push_back (Pair ("ismine", isMine));
#endif

          arr.push_back (obj);
        }
    }

  return arr;
}