// 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; }