CCacheNameIterator::CCacheNameIterator (const CNameCache& c, CNameIterator* b) : cache(c), base(b) { /* Add a seek-to-start to ensure that everything is consistent. This call may be superfluous if we seek to another position afterwards anyway, but it should also not hurt too much. */ seek (valtype ()); }
void spn_value_print(const SpnValue *val) { switch (valtype(val)) { case SPN_TTAG_NIL: { fputs("nil", stdout); break; } case SPN_TTAG_BOOL: { fputs(boolvalue(val) ? "true" : "false", stdout); break; } case SPN_TTAG_NUMBER: { if (isfloat(val)) { printf("%.*g", DBL_DIG, floatvalue(val)); } else { printf("%ld", intvalue(val)); } break; } case SPN_TTAG_STRING: { SpnString *s = stringvalue(val); fputs(s->cstr, stdout); break; } case SPN_TTAG_ARRAY: { SpnArray *array = objvalue(val); print_array(array, 0); break; } case SPN_TTAG_HASHMAP: { SpnHashMap *hashmap = objvalue(val); print_hashmap(hashmap, 0); break; } case SPN_TTAG_FUNC: { SpnFunction *func = funcvalue(val); void *p; if (func->native) { p = (void *)(ptrdiff_t)(func->repr.fn); } else { p = func->repr.bc; } printf("<function %p>", p); break; } case SPN_TTAG_USERINFO: { void *ptr = isobject(val) ? objvalue(val) : ptrvalue(val); printf("<userinfo %p>", ptr); break; } default: SHANT_BE_REACHED(); break; } }
void spn_repl_print(const SpnValue *val) { switch (valtype(val)) { case SPN_TTAG_STRING: spn_debug_print(val); break; default: spn_value_print(val); break; } }
int spn_value_equal(const SpnValue *lhs, const SpnValue *rhs) { /* first, make sure that we compare values of the same type * (values of different types cannot possibly be equal) */ if (valtype(lhs) != valtype(rhs)) { return 0; } switch (valtype(lhs)) { case SPN_TTAG_NIL: { return 1; /* nil can only be nil */ } case SPN_TTAG_BOOL: { return boolvalue(lhs) == boolvalue(rhs); } case SPN_TTAG_NUMBER: { return numeric_equal(lhs, rhs); } case SPN_TTAG_STRING: case SPN_TTAG_ARRAY: case SPN_TTAG_HASHMAP: case SPN_TTAG_FUNC: { return spn_object_equal(objvalue(lhs), objvalue(rhs)); } case SPN_TTAG_USERINFO: { /* an object can not equal a non-object */ if (isobject(lhs) != isobject(rhs)) { return 0; } if (isobject(lhs)) { return spn_object_equal(objvalue(lhs), objvalue(rhs)); } else { return ptrvalue(lhs) == ptrvalue(rhs); } } default: SHANT_BE_REACHED(); } return 0; }
unsigned long spn_hash_value(const SpnValue *key) { switch (valtype(key)) { case SPN_TTAG_NIL: { return 0; } case SPN_TTAG_BOOL: { return boolvalue(key); /* 0 or 1 */ } case SPN_TTAG_NUMBER: { if (isfloat(key)) { double f = floatvalue(key); /* only test for integer if it fits into one (anti-UB) */ if (LONG_MIN <= f && f <= LONG_MAX) { long i = f; /* truncate */ if (f == i) { /* it's really an integer. * This takes care of the +/- 0 problem too * (since 0 itself is an integer) */ return i; } } else { return spn_hash_bytes(&f, sizeof f); } } /* the hash value of an integer is itself */ return intvalue(key); } case SPN_TTAG_STRING: case SPN_TTAG_ARRAY: case SPN_TTAG_HASHMAP: case SPN_TTAG_FUNC: { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } case SPN_TTAG_USERINFO: { if (isobject(key)) { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } return (unsigned long)(ptrvalue(key)); } default: SHANT_BE_REACHED(); } return 0; }
unsigned long spn_hash_value(const SpnValue *key) { switch (valtype(key)) { case SPN_TTAG_NIL: { return 0; } case SPN_TTAG_BOOL: { return boolvalue(key); /* 0 or 1 */ } case SPN_TTAG_NUMBER: { if (isfloat(key)) { double f = floatvalue(key); long i = f; /* truncate */ if (f == i) { return i; /* it's really an integer */ } else { return spn_hash_bytes(&f, sizeof f); } } /* the hash value of an integer is itself */ return intvalue(key); } case SPN_TTAG_STRING: case SPN_TTAG_ARRAY: case SPN_TTAG_HASHMAP: case SPN_TTAG_FUNC: { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } case SPN_TTAG_USERINFO: { if (isobject(key)) { SpnObject *obj = objvalue(key); unsigned long (*hashfn)(void *) = obj->isa->hashfn; return hashfn ? hashfn(obj) : (unsigned long)(obj); } return (unsigned long)(ptrvalue(key)); } default: SHANT_BE_REACHED(); } return 0; }
void spn_debug_print(const SpnValue *val) { switch (valtype(val)) { case SPN_TTAG_STRING: /* TODO: do proper escaping */ printf("\""); spn_value_print(val); printf("\""); break; case SPN_TTAG_ARRAY: printf("<array %p>", objvalue(val)); break; case SPN_TTAG_HASHMAP: printf("<hashmap %p>", objvalue(val)); break; default: spn_value_print(val); break; } }
bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, std::vector<std::vector<unsigned char> >& vSolutionsRet) { // Templates static std::multimap<txnouttype, CScript> mTemplates; if (mTemplates.empty()) { // Standard tx, sender provides pubkey, receiver adds signature mTemplates.insert(std::make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG)); // Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey mTemplates.insert(std::make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG)); // Sender provides N pubkeys, receivers provides M signatures mTemplates.insert(std::make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG)); } vSolutionsRet.clear(); // If we have a name script, strip the prefix const CNameScript nameOp(scriptPubKey); const CScript& script1 = nameOp.getAddress(); // Shortcut for pay-to-script-hash, which are more constrained than the other types: // it is always OP_HASH160 20 [20 byte hash] OP_EQUAL if (script1.IsPayToScriptHash(false)) { typeRet = TX_SCRIPTHASH; std::vector<unsigned char> hashBytes(script1.begin()+2, script1.begin()+22); vSolutionsRet.push_back(hashBytes); return true; } int witnessversion; std::vector<unsigned char> witnessprogram; if (scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) { if (witnessversion == 0 && witnessprogram.size() == 20) { typeRet = TX_WITNESS_V0_KEYHASH; vSolutionsRet.push_back(witnessprogram); return true; } if (witnessversion == 0 && witnessprogram.size() == 32) { typeRet = TX_WITNESS_V0_SCRIPTHASH; vSolutionsRet.push_back(witnessprogram); return true; } if (witnessversion != 0) { typeRet = TX_WITNESS_UNKNOWN; vSolutionsRet.push_back(std::vector<unsigned char>{(unsigned char)witnessversion}); vSolutionsRet.push_back(std::move(witnessprogram)); return true; } return false; } // Provably prunable, data-carrying output // // So long as script passes the IsUnspendable() test and all but the first // byte passes the IsPushOnly() test we don't care what exactly is in the // script. if (scriptPubKey.size() >= 1 && scriptPubKey[0] == OP_RETURN && scriptPubKey.IsPushOnly(scriptPubKey.begin()+1)) { typeRet = TX_NULL_DATA; return true; } // Scan templates for (const std::pair<txnouttype, CScript>& tplate : mTemplates) { const CScript& script2 = tplate.second; vSolutionsRet.clear(); opcodetype opcode1, opcode2; std::vector<unsigned char> vch1, vch2; // Compare CScript::const_iterator pc1 = script1.begin(); CScript::const_iterator pc2 = script2.begin(); while (true) { if (pc1 == script1.end() && pc2 == script2.end()) { // Found a match typeRet = tplate.first; if (typeRet == TX_MULTISIG) { // Additional checks for TX_MULTISIG: unsigned char m = vSolutionsRet.front()[0]; unsigned char n = vSolutionsRet.back()[0]; if (m < 1 || n < 1 || m > n || vSolutionsRet.size()-2 != n) return false; } return true; } if (!script1.GetOp(pc1, opcode1, vch1)) break; if (!script2.GetOp(pc2, opcode2, vch2)) break; // Template matching opcodes: if (opcode2 == OP_PUBKEYS) { while (vch1.size() >= 33 && vch1.size() <= 65) { vSolutionsRet.push_back(vch1); if (!script1.GetOp(pc1, opcode1, vch1)) break; } if (!script2.GetOp(pc2, opcode2, vch2)) break; // Normal situation is to fall through // to other if/else statements } if (opcode2 == OP_PUBKEY) { if (vch1.size() < 33 || vch1.size() > 65) break; vSolutionsRet.push_back(vch1); } else if (opcode2 == OP_PUBKEYHASH) { if (vch1.size() != sizeof(uint160)) break; vSolutionsRet.push_back(vch1); } else if (opcode2 == OP_SMALLINTEGER) { // Single-byte small integer pushed onto vSolutions if (opcode1 == OP_0 || (opcode1 >= OP_1 && opcode1 <= OP_16)) { char n = (char)CScript::DecodeOP_N(opcode1); vSolutionsRet.push_back(valtype(1, n)); } else break; } else if (opcode1 != opcode2 || vch1 != vch2) { // Others must match exactly break; } } } vSolutionsRet.clear(); typeRet = TX_NONSTANDARD; return false; }
json_spirit::Value name_filter (const json_spirit::Array& params, bool fHelp) { if (fHelp || params.size () > 5) throw std::runtime_error ( "name_filter (\"regexp\" (\"maxage\" (\"from\" (\"nb\" (\"stat\")))))\n" "\nScan and list names matching a regular expression.\n" "\nArguments:\n" "1. \"regexp\" (string, optional) filter names with this regexp\n" "2. \"maxage\" (numeric, optional, default=36000) only consider names updated in the last \"maxage\" blocks; 0 means all names\n" "3. \"from\" (numeric, optional, default=0) return from this position onward; index starts at 0\n" "4. \"nb\" (numeric, optional, default=0) return only \"nb\" entries; 0 means all\n" "5. \"stat\" (string, optional) if set to the string \"stat\", print statistics instead of returning the names\n" "\nResult:\n" "[\n" + getNameInfoHelp (" ", ",") + " ...\n" "]\n" "\nExamples:\n" + HelpExampleCli ("name_filter", "\"\" 5") + HelpExampleCli ("name_filter", "\"^id/\"") + HelpExampleCli ("name_filter", "\"^id/\" 36000 0 0 \"stat\"") + HelpExampleRpc ("name_scan", "\"^d/\"") ); if (IsInitialBlockDownload ()) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Namecoin is downloading blocks..."); /* ********************** */ /* Interpret parameters. */ bool haveRegexp(false); boost::xpressive::sregex regexp; int maxage(36000), from(0), nb(0); bool stats(false); if (params.size () >= 1) { haveRegexp = true; regexp = boost::xpressive::sregex::compile (params[0].get_str ()); } if (params.size () >= 2) maxage = params[1].get_int (); if (maxage < 0) throw JSONRPCError (RPC_INVALID_PARAMETER, "'maxage' should be non-negative"); if (params.size () >= 3) from = params[2].get_int (); if (from < 0) throw JSONRPCError (RPC_INVALID_PARAMETER, "'from' should be non-negative"); if (params.size () >= 4) nb = params[3].get_int (); if (nb < 0) throw JSONRPCError (RPC_INVALID_PARAMETER, "'nb' should be non-negative"); if (params.size () >= 5) { if (params[4].get_str () != "stat") throw JSONRPCError (RPC_INVALID_PARAMETER, "fifth argument must be the literal string 'stat'"); stats = true; } /* ******************************************* */ /* Iterate over names to build up the result. */ json_spirit::Array names; unsigned count(0); /* The lock must be held throughout the call, since walker.getResult() uses chainActive for the block height in stats mode. */ LOCK (cs_main); pcoinsTip->Flush (); std::auto_ptr<CNameIterator> iter(pcoinsTip->IterateNames (valtype ())); valtype name; CNameData data; while (iter->next (name, data)) { const int age = chainActive.Height () - data.getHeight (); assert (age >= 0); if (maxage != 0 && age >= maxage) continue; if (haveRegexp) { const std::string nameStr = ValtypeToString (name); boost::xpressive::smatch matches; if (!boost::xpressive::regex_search (nameStr, matches, regexp)) continue; } if (from > 0) { --from; continue; } assert (from == 0); if (stats) ++count; else names.push_back (getNameInfo (name, data)); if (nb > 0) { --nb; if (nb == 0) break; } } /* ********************************************************** */ /* Return the correct result (take stats mode into account). */ if (stats) { json_spirit::Object res; res.push_back (json_spirit::Pair ("blocks", chainActive.Height ())); res.push_back (json_spirit::Pair ("count", static_cast<int> (count))); return res; } return names; }