コード例 #1
0
ファイル: name_tests.cpp プロジェクト: bankonme/namecoin-core
CNameData
NameIterationTester::getNextData ()
{
  const CScript addr = getTestAddress ();
  const valtype name = ValtypeFromString ("dummy");
  const valtype value = ValtypeFromString ("abc");
  const CScript updateScript = CNameScript::buildNameUpdate (addr, name, value);
  const CNameScript nameOp(updateScript);

  CNameData res;
  res.fromScript (++counter, COutPoint (uint256 (), 0), nameOp);

  return res;
}
コード例 #2
0
ファイル: names.cpp プロジェクト: bitcoin8mtest/namecoin-core
UniValue
name_history (const UniValue& params, bool fHelp)
{
  if (fHelp || params.size () != 1)
    throw std::runtime_error (
        "name_history \"name\"\n"
        "\nLook up the current and all past data for the given name."
        "  -namehistory must be enabled.\n"
        "\nArguments:\n"
        "1. \"name\"          (string, required) the name to query for\n"
        "\nResult:\n"
        "[\n"
        + getNameInfoHelp ("  ", ",") +
        "  ...\n"
        "]\n"
        "\nExamples:\n"
        + HelpExampleCli ("name_history", "\"myname\"")
        + HelpExampleRpc ("name_history", "\"myname\"")
      );

  if (!fNameHistory)
    throw std::runtime_error ("-namehistory is not enabled");

  if (IsInitialBlockDownload ())
    throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD,
                       "Namecoin is downloading blocks...");

  const std::string nameStr = params[0].get_str ();
  const valtype name = ValtypeFromString (nameStr);

  CNameData data;
  CNameHistory history;

  {
    LOCK (cs_main);

    if (!pcoinsTip->GetName (name, data))
      {
        std::ostringstream msg;
        msg << "name not found: '" << nameStr << "'";
        throw JSONRPCError (RPC_WALLET_ERROR, msg.str ());
      }

    if (!pcoinsTip->GetNameHistory (name, history))
      assert (history.empty ());
  }

  UniValue res(UniValue::VARR);
  BOOST_FOREACH (const CNameData& entry, history.getData ())
    res.push_back (getNameInfo (name, entry));
  res.push_back (getNameInfo (name, data));

  return res;
}
コード例 #3
0
ファイル: name_tests.cpp プロジェクト: bankonme/namecoin-core
void
NameIterationTester::remove (const std::string& n)
{
  const valtype& name = ValtypeFromString (n);

  assert (data.count (name) == 1);
  data.erase (name);
  hybrid.DeleteName (name);
  cache.DeleteName (name);
  verify ();
}
コード例 #4
0
ファイル: name_tests.cpp プロジェクト: bankonme/namecoin-core
void
NameIterationTester::update (const std::string& n)
{
  const valtype& name = ValtypeFromString (n);
  const CNameData testData = getNextData ();

  assert (data.count (name) == 1);
  data[name] = testData;
  hybrid.SetName (name, testData, false);
  cache.SetName (name, testData, false);
  verify ();
}
コード例 #5
0
ファイル: names.cpp プロジェクト: bitcoin8mtest/namecoin-core
/**
 * Implement the rawtx name operation feature.  This routine interprets
 * the given JSON object describing the desired name operation and then
 * modifies the transaction accordingly.
 * @param tx The transaction to extend.
 * @param obj The name operation "description" as given to the call.
 */
void
AddRawTxNameOperation (CMutableTransaction& tx, const UniValue& obj)
{
  UniValue val = find_value (obj, "op");
  if (!val.isStr ())
    throw JSONRPCError (RPC_INVALID_PARAMETER, "missing op key");
  const std::string op = val.get_str ();

  if (op != "name_update")
    throw JSONRPCError (RPC_INVALID_PARAMETER,
                        "only name_update is implemented for the rawtx API");

  val = find_value (obj, "name");
  if (!val.isStr ())
    throw JSONRPCError (RPC_INVALID_PARAMETER, "missing name key");
  const valtype name = ValtypeFromString (val.get_str ());

  val = find_value (obj, "value");
  if (!val.isStr ())
    throw JSONRPCError (RPC_INVALID_PARAMETER, "missing value key");
  const valtype value = ValtypeFromString (val.get_str ());

  val = find_value (obj, "address");
  if (!val.isStr ())
    throw JSONRPCError (RPC_INVALID_PARAMETER, "missing address key");
  const CBitcoinAddress toAddress(val.get_str ());
  if (!toAddress.IsValid ())
    throw JSONRPCError (RPC_INVALID_ADDRESS_OR_KEY, "invalid address");
  const CScript addr = GetScriptForDestination (toAddress.Get ());

  tx.SetNamecoin ();

  /* We do not add the name input.  This has to be done explicitly,
     but is easy from the name_show output.  That way, createrawtransaction
     doesn't depend on the chainstate at all.  */

  const CScript outScript = CNameScript::buildNameUpdate (addr, name, value);
  tx.vout.push_back (CTxOut (NAME_LOCKED_AMOUNT, outScript));
}
コード例 #6
0
ファイル: rpcnames.cpp プロジェクト: iswt/namecore
json_spirit::Value
name_scan (const json_spirit::Array& params, bool fHelp)
{
  if (fHelp || params.size () > 2)
    throw std::runtime_error (
        "name_scan (\"start\" (\"count\"))\n"
        "\nList names in the database.\n"
        "\nArguments:\n"
        "1. \"start\"       (string, optional) skip initially to this name\n"
        "2. \"count\"       (numeric, optional, default=500) stop after this many names\n"
        "\nResult:\n"
        "[\n"
        + getNameInfoHelp ("  ", ",") +
        "  ...\n"
        "]\n"
        "\nExamples:\n"
        + HelpExampleCli ("name_scan", "")
        + HelpExampleCli ("name_scan", "\"d/abc\"")
        + HelpExampleCli ("name_scan", "\"d/abc\" 10")
        + HelpExampleRpc ("name_scan", "\"d/abc\"")
      );

  if (IsInitialBlockDownload ())
    throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD,
                       "Namecoin is downloading blocks...");

  valtype start;
  if (params.size () >= 1)
    start = ValtypeFromString (params[0].get_str ());

  int count = 500;
  if (params.size () >= 2)
    count = params[1].get_int ();

  json_spirit::Array res;
  if (count <= 0)
    return res;

  {
    LOCK (cs_main);
    pcoinsTip->Flush ();

    valtype name;
    CNameData data;
    for (std::auto_ptr<CNameIterator> iter(pcoinsTip->IterateNames (start));
         count > 0 && iter->next (name, data); --count)
      res.push_back (getNameInfo (name, data));
  }

  return res;
}
コード例 #7
0
ファイル: name_tests.cpp プロジェクト: bankonme/namecoin-core
void
NameIterationTester::verify (const CCoinsView& view) const
{
  /* Try out everything with all names as "start".  This thoroughly checks
     that also the start implementation is correct.  It also checks using
     a single iterator and seeking vs using a fresh iterator.  */

  valtype start;
  EntryList remaining(data.begin (), data.end ());

  /* Seek the iterator to the end first for "maximum confusion".  This ensures
     that seeking to valtype() works.  */
  std::auto_ptr<CNameIterator> iter(view.IterateNames ());
  const valtype end = ValtypeFromString ("zzzzzzzzzzzzzzzz");
  {
    valtype name;
    CNameData data;

    iter->seek (end);
    BOOST_CHECK (!iter->next (name, data));
  }

  while (true)
    {
      EntryList got = getNamesFromView (view, start);
      BOOST_CHECK (got == remaining);

      iter->seek (start);
      got = getNamesFromIterator (*iter);
      BOOST_CHECK (got == remaining);

      if (remaining.empty ())
        break;

      if (start == remaining.front ().first)
        remaining.pop_front ();

      if (remaining.empty ())
        start = end;
      else
        start = remaining.front ().first;
    }
}
コード例 #8
0
ファイル: names.cpp プロジェクト: bitcoin8mtest/namecoin-core
UniValue
name_show (const UniValue& params, bool fHelp)
{
  if (fHelp || params.size () != 1)
    throw std::runtime_error (
        "name_show \"name\"\n"
        "\nLook up the current data for the given name."
        "  Fails if the name doesn't exist.\n"
        "\nArguments:\n"
        "1. \"name\"          (string, required) the name to query for\n"
        "\nResult:\n"
        + getNameInfoHelp ("", "") +
        "\nExamples:\n"
        + HelpExampleCli ("name_show", "\"myname\"")
        + HelpExampleRpc ("name_show", "\"myname\"")
      );

  if (IsInitialBlockDownload ())
    throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD,
                       "Namecoin is downloading blocks...");

  const std::string nameStr = params[0].get_str ();
  const valtype name = ValtypeFromString (nameStr);

  CNameData data;
  {
    LOCK (cs_main);
    if (!pcoinsTip->GetName (name, data))
      {
        std::ostringstream msg;
        msg << "name not found: '" << nameStr << "'";
        throw JSONRPCError (RPC_WALLET_ERROR, msg.str ());
      }
  }

  return getNameInfo (name, data);
}
コード例 #9
0
ファイル: tx.cpp プロジェクト: fsb4000/huntercore
void
ApplyGameTransactions (const std::vector<CTransaction>& vGameTx,
                       const StepResult& stepResult, unsigned nHeight,
                       CValidationState& state, CCoinsViewCache& view,
                       CBlockUndo& undo)
{
  for (unsigned i = 0; i < vGameTx.size (); ++i)
    {
      undo.vtxundo.push_back (CTxUndo ());
      UpdateCoins (vGameTx[i], state, view, undo.vtxundo.back (), nHeight);
    }

  /* Update name db for killed players.  */
  const PlayerSet& victims = stepResult.GetKilledPlayers ();
  if (!victims.empty ())
    {
      assert (!vGameTx.empty ());
      const CTransaction& txKills = vGameTx.front ();
      assert (txKills.vout.empty ());
      assert (txKills.vin.size () == victims.size ());

      BOOST_FOREACH(const PlayerID& name, victims)
        {
          const valtype& vchName = ValtypeFromString (name);
          LogPrint ("names", "Killing player at height %d: %s\n",
                    nHeight, name.c_str ());

          CNameTxUndo opUndo;
          opUndo.fromOldState (vchName, view);
          undo.vnameundo.push_back (opUndo);

          CNameData data;
          data.setDead (nHeight, txKills.GetHash ());
          view.SetName (vchName, data, false);
        }
    }
コード例 #10
0
ファイル: names.cpp プロジェクト: bitcoin8mtest/namecoin-core
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)
    {
      std::shared_ptr<const CTransaction> tx = mempool.get (*i);
      if (!tx || !tx->IsNamecoin ())
        continue;

      for (const auto& txOut : tx->vout)
        {
          const CNameScript op(txOut.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;
}
コード例 #11
0
ファイル: tx.cpp プロジェクト: fsb4000/huntercore
bool
CreateGameTransactions (const CCoinsView& view, unsigned nHeight,
                        const StepResult& stepResult,
                        std::vector<CTransaction>& vGameTx)
{
  vGameTx.clear ();

  /* Destroy name-coins of killed players.  */

  bool haveTxKills = false;
  CMutableTransaction txKills;
  txKills.SetGameTx ();

  const PlayerSet& killedPlayers = stepResult.GetKilledPlayers ();
  const KilledByMap& killedBy = stepResult.GetKilledBy ();
  txKills.vin.reserve (killedPlayers.size ());
  BOOST_FOREACH(const PlayerID &victim, killedPlayers)
    {
      const valtype vchName = ValtypeFromString (victim);
      CNameData data;
      if (!view.GetName (vchName, data))
        return error ("Game engine killed a non-existing player %s",
                      victim.c_str ());

      CTxIn txin(data.getUpdateOutpoint ());

      /* List all killers, if player was simultaneously killed by several
         other players.  If the reason was not KILLED_DESTRUCT, handle
         it also.  If multiple reasons apply, the game tx is constructed
         for the first reason according to the ordering inside of KilledByMap.
         (Which in turn is determined by the enum values for KILLED_*.)  */

      typedef KilledByMap::const_iterator Iter;
      const std::pair<Iter, Iter> iters = killedBy.equal_range (victim);
      if (iters.first == iters.second)
        return error ("No reason for killed player %s", victim.c_str ());
      const KilledByInfo::Reason reason = iters.first->second.reason;

      /* Unless we have destruct, there should be exactly one entry with
         the "first" reason.  There may be multiple entries for different
         reasons, for instance, killed by poison and staying in spawn
         area at the same time.  */
      {
        Iter it = iters.first;
        ++it;
        if (reason != KilledByInfo::KILLED_DESTRUCT && it != iters.second
            && reason == it->second.reason)
          return error ("Multiple same-reason, non-destruct killed-by"
                        " entries for %s", victim.c_str ());
      }

      switch (reason)
        {
        case KilledByInfo::KILLED_DESTRUCT:
          txin.scriptSig << vchName << GAMEOP_KILLED_BY;
          for (Iter it = iters.first; it != iters.second; ++it)
            {
              if (it->second.reason != KilledByInfo::KILLED_DESTRUCT)
                {
                  assert (it != iters.first);
                  break;
                }
              txin.scriptSig
                << ValtypeFromString (it->second.killer.ToString ());
            }
          break;

        case KilledByInfo::KILLED_SPAWN:
          txin.scriptSig << vchName << GAMEOP_KILLED_BY;
          break;

        case KilledByInfo::KILLED_POISON:
          txin.scriptSig << vchName << GAMEOP_KILLED_POISON;
          break;

        default:
          assert (false);
        }

      txKills.vin.push_back (txin);
      haveTxKills = true;
    }
  if (haveTxKills)
    {
      const CTransaction tx(txKills);
      assert (tx.IsGameTx () && !tx.IsBountyTx ());
      vGameTx.push_back (tx);
    }

  /* Pay bounties to the players who collected them.  The transaction
     inputs are just "dummy" containing informational messages.  */

  bool haveTxBounties = false;
  CMutableTransaction txBounties;
  txBounties.SetGameTx ();

  txBounties.vin.reserve (stepResult.bounties.size ());
  txBounties.vout.reserve (stepResult.bounties.size ());

  BOOST_FOREACH(const CollectedBounty& bounty, stepResult.bounties)
    {
      const valtype vchName = ValtypeFromString (bounty.character.player);
      CNameData data;
      if (!view.GetName (vchName, data))
        return error ("Game engine created bounty for non-existing player");

      CTxOut txout;
      txout.nValue = bounty.loot.nAmount;

      if (!bounty.address.empty ())
        {
          /* Player-provided addresses are validated before accepting them,
             so failing here is ok.  */
          CBitcoinAddress addr(bounty.address);
          if (!addr.IsValid ())
            return error ("Failed to set player-provided address for bounty");
          txout.scriptPubKey = GetScriptForDestination (addr.Get ());
        }
      else
        txout.scriptPubKey = data.getAddress ();

      txBounties.vout.push_back (txout);

      CTxIn txin;
      if (bounty.loot.IsRefund ())
        txin.scriptSig
          << vchName << GAMEOP_REFUND
          << bounty.character.index << bounty.loot.GetRefundHeight ();
      else
        txin.scriptSig
          << vchName << GAMEOP_COLLECTED_BOUNTY
          << bounty.character.index
          << bounty.loot.firstBlock
          << bounty.loot.lastBlock
          << bounty.loot.collectedFirstBlock
          << bounty.loot.collectedLastBlock;
      txBounties.vin.push_back (txin);

      haveTxBounties = true;
    }
  if (haveTxBounties)
    {
      const CTransaction tx(txBounties);
      assert (tx.IsGameTx () && tx.IsBountyTx ());
      vGameTx.push_back (tx);
    }

  /* Print log chatter.  */
  if (haveTxKills || haveTxBounties)
    {
      LogPrint ("game", "Game transactions @%d:\n", nHeight);
      if (haveTxKills)
        LogPrint ("game", "  kills:    %s\n", txKills.GetHash ().ToString ());
      if (haveTxBounties)
        LogPrint ("game", "  bounties: %s\n",
                  txBounties.GetHash ().ToString ());
    }

  return true;
}