// Returns: // false - invalid move tx // true - non-move tx or valid tx bool IsValid(const CTransaction& tx, Move &outMove) { if (!GetNameOfTx(tx, vchName) || !GetValueOfNameTx(tx, vchValue)) return true; std::string sName = stringFromVch(vchName), sValue = stringFromVch(vchValue); if (dup.count(sName)) return error("GameStepValidator: duplicate player name %s", sName.c_str()); dup.insert(sName); Move m; m.Parse(sName, sValue); if (!m) return error("GameStepValidator: cannot parse move %s for player %s", sValue.c_str(), sName.c_str()); if (!m.IsValid(*pstate)) return error("GameStepValidator: invalid move for the game state: move %s for player %s", sValue.c_str(), sName.c_str()); std::string addressLock = m.AddressOperationPermission(*pstate); if (!addressLock.empty()) { // If one of inputs has address equal to addressLock, then that input has been signed by the address owner // and thus authorizes the address change operation bool found = false; if (!pTxDB) { pTxDB = new CTxDB("r"); fOwnTxDB = true; } for (int i = 0; i < tx.vin.size(); i++) { COutPoint prevout = tx.vin[i].prevout; CTransaction txPrev; CTxIndex txindex; if (!pTxDB->ReadTxIndex(prevout.hash, txindex) || txindex.pos == CDiskTxPos(1,1,1)) continue; else if (!txPrev.ReadFromDisk(txindex.pos)) continue; if (prevout.n >= txPrev.vout.size()) continue; const CTxOut &vout = txPrev.vout[prevout.n]; std::string address; if (ExtractDestination(vout.scriptPubKey, address) && address == addressLock) { found = true; break; } } if (!found) return error("GameStepValidator: address operation permission denied: move %s for player %s", sValue.c_str(), sName.c_str()); } outMove = m; return true; }
// Returns: // false - invalid move tx // true - non-move tx or valid tx bool IsValid(const CTransaction& tx, Move &outMove) { if (tx.nVersion != NAMECOIN_TX_VERSION) return true; std::vector<vchType> vvchArgs; int op, nOut; if (!DecodeNameTx (tx, op, nOut, vvchArgs)) return error ("GameStepValidator: could not decode a name tx"); vchType vchName, vchValue; switch (op) { case OP_NAME_FIRSTUPDATE: vchName = vvchArgs[0]; vchValue = vvchArgs[2]; break; case OP_NAME_UPDATE: vchName = vvchArgs[0]; vchValue = vvchArgs[1]; break; case OP_NAME_NEW: return true; default: return error ("GameStepValidator: invalid name tx found"); } const std::string sName = stringFromVch(vchName); const std::string sValue = stringFromVch(vchValue); if (dup.count(sName)) return error ("GameStepValidator: duplicate player name %s", sName.c_str ()); dup.insert(sName); Move m; m.Parse(sName, sValue); if (!m) return error("GameStepValidator: cannot parse move %s for player %s", sValue.c_str(), sName.c_str()); if (!m.IsValid(*pstate)) return error("GameStepValidator: invalid move for the game state: move %s for player %s", sValue.c_str(), sName.c_str()); /* If this is a spawn move, find out the coin's value and set the spawned player's value to it. */ if (m.IsSpawn ()) { if (op != OP_NAME_FIRSTUPDATE) return error ("GameStepValidator: spawn is not firstupdate"); m.coinAmount = tx.vout[nOut].nValue; } else if (op != OP_NAME_UPDATE) return error ("GameStepValidator: name_firstupdate is not spawn"); std::string addressLock = m.AddressOperationPermission(*pstate); if (!addressLock.empty()) { // If one of inputs has address equal to addressLock, then that input has been signed by the address owner // and thus authorizes the address change operation bool found = false; if (!pdbset) { pdbset = new DatabaseSet("r"); fOwnDb = true; } for (int i = 0; i < tx.vin.size(); i++) { COutPoint prevout = tx.vin[i].prevout; CTransaction txPrev; CTxIndex txindex; if (!pdbset->tx ().ReadTxIndex (prevout.hash, txindex) || txindex.pos == CDiskTxPos(1,1,1)) continue; else if (!txPrev.ReadFromDisk(txindex.pos)) continue; if (prevout.n >= txPrev.vout.size()) continue; const CTxOut &vout = txPrev.vout[prevout.n]; std::string address; if (ExtractDestination(vout.scriptPubKey, address) && address == addressLock) { found = true; break; } } if (!found) return error("GameStepValidator: address operation permission denied: move %s for player %s", sValue.c_str(), sName.c_str()); } outMove = m; return true; }