CScript ParseScript(string s) { CScript result; static map<string, opcodetype> mapOpNames; if (mapOpNames.size() == 0) { for (int op = 0; op <= OP_NOP10; op++) { // Allow OP_RESERVED to get into mapOpNames if (op < OP_NOP && op != OP_RESERVED) continue; const char* name = GetOpName((opcodetype)op); if (strcmp(name, "OP_UNKNOWN") == 0) continue; string strName(name); mapOpNames[strName] = (opcodetype)op; // Convenience: OP_ADD and just ADD are both recognized: replace_first(strName, "OP_", ""); mapOpNames[strName] = (opcodetype)op; } } vector<string> words; split(words, s, is_any_of(" \t\n"), token_compress_on); BOOST_FOREACH(string w, words) { if (all(w, is_digit()) || (starts_with(w, "-") && all(string(w.begin()+1, w.end()), is_digit()))) { // Number int64 n = atoi64(w); result << n; } else if (starts_with(w, "0x") && IsHex(string(w.begin()+2, w.end()))) { // Raw hex data, inserted NOT pushed onto stack: std::vector<unsigned char> raw = ParseHex(string(w.begin()+2, w.end())); result.insert(result.end(), raw.begin(), raw.end()); } else if (w.size() >= 2 && starts_with(w, "'") && ends_with(w, "'")) { // Single-quoted string, pushed as data. NOTE: this is poor-man's // parsing, spaces/tabs/newlines in single-quoted strings won't work. std::vector<unsigned char> value(w.begin()+1, w.end()-1); result << value; } else if (mapOpNames.count(w)) { // opcode, e.g. OP_ADD or ADD: result << mapOpNames[w]; } else { BOOST_ERROR("Parse error: " << s); return CScript(); } } return result; }
/** * Sign scriptPubKey using signature made with creator. * Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed), * unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script. * Returns false if scriptPubKey could not be completely satisfied. */ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey, std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion, SignatureData& sigdata) { CScript scriptRet; uint160 h160; ret.clear(); std::vector<unsigned char> sig; std::vector<valtype> vSolutions; if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) return false; switch (whichTypeRet) { case TX_NONSTANDARD: case TX_NULL_DATA: case TX_WITNESS_UNKNOWN: return false; case TX_PUBKEY: if (!CreateSig(creator, sigdata, provider, sig, CPubKey(vSolutions[0]), scriptPubKey, sigversion)) return false; ret.push_back(std::move(sig)); return true; case TX_PUBKEYHASH: { CKeyID keyID = CKeyID(uint160(vSolutions[0])); CPubKey pubkey; GetPubKey(provider, sigdata, keyID, pubkey); if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false; ret.push_back(std::move(sig)); ret.push_back(ToByteVector(pubkey)); return true; } case TX_SCRIPTHASH: if (GetCScript(provider, sigdata, uint160(vSolutions[0]), scriptRet)) { ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end())); return true; } return false; case TX_MULTISIG: { size_t required = vSolutions.front()[0]; ret.push_back(valtype()); // workaround CHECKMULTISIG bug for (size_t i = 1; i < vSolutions.size() - 1; ++i) { CPubKey pubkey = CPubKey(vSolutions[i]); if (ret.size() < required + 1 && CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) { ret.push_back(std::move(sig)); } } bool ok = ret.size() == required + 1; for (size_t i = 0; i + ret.size() < required + 1; ++i) { ret.push_back(valtype()); } return ok; } case TX_WITNESS_V0_KEYHASH: ret.push_back(vSolutions[0]); return true; case TX_WITNESS_V0_SCRIPTHASH: CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin()); if (GetCScript(provider, sigdata, h160, scriptRet)) { ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end())); return true; } return false; default: return false; } }
bool CSector::r_LoadVal( CScript &s ) { ADDTOCALLSTACK("CSector::r_LoadVal"); EXC_TRY("LoadVal"); switch ( FindTableSorted( s.GetKey(), sm_szLoadKeys, COUNTOF( sm_szLoadKeys )-1 )) { case SC_COLDCHANCE: SetWeatherChance( false, s.HasArgs() ? s.GetArgVal() : -1 ); return( true ); case SC_FLAGS: m_dwFlags = s.GetArgVal(); return true; case SC_LIGHT: if ( g_Cfg.m_bAllowLightOverride ) m_Env.m_Light = static_cast<unsigned char>(s.GetArgVal() | LIGHT_OVERRIDE); return true; case SC_RAINCHANCE: SetWeatherChance( true, s.HasArgs() ? s.GetArgVal() : -1 ); return( true ); case SC_SEASON: SetSeason(s.HasArgs() ? static_cast<SEASON_TYPE>(s.GetArgVal()) : SEASON_Summer); return (true); case SC_WEATHER: SetWeather(s.HasArgs() ? static_cast<WEATHER_TYPE>(s.GetArgVal()) : WEATHER_DRY); return( true ); } EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPT; EXC_DEBUG_END; return false; }
bool CDialogDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on this object as a target { ADDTOCALLSTACK("CDialogDef::r_Verb"); EXC_TRY("Verb"); // The first part of the key is GUMPCTL_TYPE lpctstr pszKey = s.GetKey(); int index = FindTableSorted( pszKey, sm_szLoadKeys, CountOf(sm_szLoadKeys)-1 ); if ( index < 0 ) { CSString sVal; CScriptTriggerArgs Args(s.GetArgRaw()); if ( r_Call(s.GetKey(), pSrc, &Args, &sVal) ) return true; if (!m_pObj) return CResourceLink::r_Verb(s, pSrc); return m_pObj->r_Verb(s, pSrc); } lpctstr pszArgs = s.GetArgStr(); switch( index ) { case GUMPCTL_PAGE: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; GET_ABSOLUTE( page ); if ( page <= 0 ) return true; int iNewPage; if ( m_wPage == 0 || page > m_wPage || page == 0 ) iNewPage = page; else if ( page == m_wPage ) iNewPage = 1; else iNewPage = page + 1; m_sControls[m_uiControls].Format( "page %d", iNewPage ); ++m_uiControls; return true; } case GUMPCTL_BUTTON: // 7 = X,Y,Down gump,Up gump,pressable(1/0),page,id case GUMPCTL_BUTTONTILEART: // 11 = X,Y,Down gump,Up gump,pressable(1/0),page,id,tileart,hue,X,Y { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( down ); GET_ABSOLUTE( up ); GET_ABSOLUTE( press ); GET_ABSOLUTE( page ); GET_ABSOLUTE( id ); int iNewPage; if ( m_wPage == 0 || page > m_wPage || page == 0 ) iNewPage = page; else if ( page == m_wPage ) iNewPage = 1; else iNewPage = page + 1; if (index == GUMPCTL_BUTTON) m_sControls[m_uiControls].Format( "button %d %d %d %d %d %d %d", x, y, down, up, press, iNewPage, id ); else { GET_ABSOLUTE( tileId ); GET_ABSOLUTE( tileHue ); GET_ABSOLUTE( tileX ); GET_ABSOLUTE( tileY ); m_sControls[m_uiControls].Format( "buttontileart %d %d %d %d %d %d %d %d %d %d %d", x, y, down, up, press, iNewPage, id, tileId, tileHue, tileX, tileY ); } ++m_uiControls; return true; } case GUMPCTL_GUMPPIC: { GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( id ); SKIP_ALL( pszArgs ); m_sControls[m_uiControls].Format( "gumppic %d %d %d%s%s", x, y, id, *pszArgs ? " hue=" : "", *pszArgs ? pszArgs : "" ); ++m_uiControls; return true; } case GUMPCTL_GUMPPICTILED: { GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( sX ); GET_ABSOLUTE( sY ); GET_ABSOLUTE( id ); m_sControls[m_uiControls].Format( "gumppictiled %d %d %d %d %d", x, y, sX, sY, id ); ++m_uiControls; return true; } case GUMPCTL_RESIZEPIC: { GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( id ); GET_ABSOLUTE( sX ); GET_ABSOLUTE( sY ); m_sControls[m_uiControls].Format( "resizepic %d %d %d %d %d", x, y, id, sX, sY ); ++m_uiControls; return true; } case GUMPCTL_TILEPIC: case GUMPCTL_TILEPICHUE: { GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( id ); SKIP_ALL( pszArgs ); // TilePic don't use args, TilePicHue yes :) if ( index == GUMPCTL_TILEPIC ) m_sControls[m_uiControls].Format( "tilepic %d %d %d", x, y, id ); else m_sControls[m_uiControls].Format( "tilepichue %d %d %d%s%s", x, y, id, *pszArgs ? " " : "", *pszArgs ? pszArgs : "" ); ++m_uiControls; return true; } case GUMPCTL_DTEXT: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; if ( m_uiTexts >= (CountOf(m_sText) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( hue ); SKIP_ALL( pszArgs ) if ( *pszArgs == '.' ) pszArgs++; uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); m_sControls[m_uiControls].Format( "text %d %d %d %u", x, y, hue, iText ); ++m_uiControls; return true; } case GUMPCTL_DCROPPEDTEXT: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; if ( m_uiTexts >= (CountOf(m_sText) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( w ); GET_ABSOLUTE( h ); GET_ABSOLUTE( hue ); SKIP_ALL( pszArgs ) if ( *pszArgs == '.' ) pszArgs++; uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); m_sControls[m_uiControls].Format( "croppedtext %d %d %d %d %d %u", x, y, w, h, hue, iText ); ++m_uiControls; return true; } case GUMPCTL_DHTMLGUMP: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; if ( m_uiTexts >= (CountOf(m_sText) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( w ); GET_ABSOLUTE( h ); GET_ABSOLUTE( bck ); GET_ABSOLUTE( options ); SKIP_ALL( pszArgs ) uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); m_sControls[m_uiControls].Format( "htmlgump %d %d %d %d %u %d %d", x, y, w, h, iText, bck, options ); ++m_uiControls; return true; } case GUMPCTL_DTEXTENTRY: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; if ( m_uiTexts >= (CountOf(m_sText) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( w ); GET_ABSOLUTE( h ); GET_ABSOLUTE( hue ); GET_ABSOLUTE( id ); SKIP_ALL( pszArgs ) uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); m_sControls[m_uiControls].Format( "textentry %d %d %d %d %d %d %u", x, y, w, h, hue, id, iText ); ++m_uiControls; return true; } case GUMPCTL_DTEXTENTRYLIMITED: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; if ( m_uiTexts >= (CountOf(m_sText) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( w ); GET_ABSOLUTE( h ); GET_ABSOLUTE( hue ); GET_ABSOLUTE( id ); GET_ABSOLUTE( charLimit ); SKIP_ALL( pszArgs ) uint iText = GumpAddText( *pszArgs ? pszArgs : "" ); m_sControls[m_uiControls].Format( "textentrylimited %d %d %d %d %d %d %u %d", x, y, w, h, hue, id, iText, charLimit ); ++m_uiControls; return true; } case GUMPCTL_CHECKBOX: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( down ); GET_ABSOLUTE( up ); GET_ABSOLUTE( state ); GET_ABSOLUTE( id ); m_sControls[m_uiControls].Format( "checkbox %d %d %d %d %d %d", x, y, down, up, state, id ); ++m_uiControls; return true; } case GUMPCTL_RADIO: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( down ); GET_ABSOLUTE( up ); GET_ABSOLUTE( state ); GET_ABSOLUTE( id ); m_sControls[m_uiControls].Format( "radio %d %d %d %d %d %d", x, y, down, up, state, id ); ++m_uiControls; return true; } case GUMPCTL_CHECKERTRANS: { if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( width ); GET_ABSOLUTE( height ); m_sControls[m_uiControls].Format( "checkertrans %d %d %d %d", x, y, width, height ); ++m_uiControls; return true; } case GUMPCTL_DORIGIN: { // GET_RELATIVE( x, m_iOriginX ); // GET_RELATIVE( y, m_iOriginY ); // m_iOriginX = x; // m_iOriginY = y; SKIP_ALL( pszArgs ); if ( *pszArgs == '-' && (IsSpace( pszArgs[1] ) || !pszArgs[1]) ) pszArgs++; else if ( *pszArgs == '*' ) m_iOriginX += Exp_GetSingle( ++pszArgs ); else m_iOriginX = Exp_GetSingle( pszArgs ); SKIP_ALL( pszArgs ); if ( *pszArgs == '-' && (IsSpace( pszArgs[1] ) || !pszArgs[1]) ) pszArgs++; else if ( *pszArgs == '*' ) m_iOriginY += Exp_GetSingle( ++pszArgs ); else m_iOriginY = Exp_GetSingle( pszArgs ); return true; } case GUMPCTL_NODISPOSE: m_fNoDispose = true; break; case GUMPCTL_CROPPEDTEXT: case GUMPCTL_TEXT: case GUMPCTL_TEXTENTRY: case GUMPCTL_TEXTENTRYLIMITED: break; case GUMPCTL_XMFHTMLGUMP: // 7 = x,y,sx,sy, cliloc(1003000) hasBack canScroll case GUMPCTL_XMFHTMLGUMPCOLOR: // 7 + color. { GET_RELATIVE( x, m_iOriginX ); GET_RELATIVE( y, m_iOriginY ); GET_ABSOLUTE( sX ); GET_ABSOLUTE( sY ); GET_ABSOLUTE( cliloc ); GET_ABSOLUTE( hasBack ); GET_ABSOLUTE( canScroll ); //SKIP_ALL( pszArgs ) if ( index == GUMPCTL_XMFHTMLGUMP ) // xmfhtmlgump doesn't use color m_sControls[m_uiControls].Format( "xmfhtmlgump %d %d %d %d %d %d %d" , x, y, sX, sY, cliloc, hasBack, canScroll ); else m_sControls[m_uiControls].Format( "xmfhtmlgumpcolor %d %d %d %d %d %d %d%s%s", x, y, sX, sY, cliloc, hasBack, canScroll, *pszArgs ? " " : "", *pszArgs ? pszArgs : "" ); ++m_uiControls; return true; } case GUMPCTL_XMFHTMLTOK: // 9 = x y width height has_background has_scrollbar color cliloc_id @args { GET_RELATIVE(x, m_iOriginX); GET_RELATIVE(y, m_iOriginY); GET_ABSOLUTE(sX); GET_ABSOLUTE(sY); GET_ABSOLUTE(hasBack); GET_ABSOLUTE(canScroll); GET_ABSOLUTE(color); GET_ABSOLUTE(cliloc); SKIP_ALL(pszArgs); m_sControls[m_uiControls].Format("xmfhtmltok %d %d %d %d %d %d %d %d %s", x, y, sX, sY, hasBack, canScroll, color, cliloc, *pszArgs ? pszArgs : ""); ++m_uiControls; return true; } default: break; } if ( m_uiControls >= (CountOf(m_sControls) - 1) ) return false; m_sControls[m_uiControls].Format("%s %s", pszKey, pszArgs); ++m_uiControls; return true; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPTSRC; EXC_DEBUG_END; return false; }
CScript ParseScript(std::string s) { CScript result; static map<string, opcodetype> mapOpNames; if (mapOpNames.empty()) { for (int op = 0; op <= OP_NOP10; op++) { // Allow OP_RESERVED to get into mapOpNames if (op < OP_NOP && op != OP_RESERVED) continue; const char* name = GetOpName((opcodetype)op); if (strcmp(name, "OP_UNKNOWN") == 0) continue; string strName(name); mapOpNames[strName] = (opcodetype)op; // Convenience: OP_ADD and just ADD are both recognized: replace_first(strName, "OP_", ""); mapOpNames[strName] = (opcodetype)op; } } vector<string> words; split(words, s, is_any_of(" \t\n"), token_compress_on); for (std::vector<std::string>::const_iterator w = words.begin(); w != words.end(); ++w) { if (w->empty()) { // Empty string, ignore. (boost::split given '' will return one word) } else if (all(*w, is_digit()) || (starts_with(*w, "-") && all(string(w->begin()+1, w->end()), is_digit()))) { // Number int64_t n = atoi64(*w); result << n; } else if (starts_with(*w, "0x") && (w->begin()+2 != w->end()) && IsHex(string(w->begin()+2, w->end()))) { // Raw hex data, inserted NOT pushed onto stack: std::vector<unsigned char> raw = ParseHex(string(w->begin()+2, w->end())); result.insert(result.end(), raw.begin(), raw.end()); } else if (w->size() >= 2 && starts_with(*w, "'") && ends_with(*w, "'")) { // Single-quoted string, pushed as data. NOTE: this is poor-man's // parsing, spaces/tabs/newlines in single-quoted strings won't work. std::vector<unsigned char> value(w->begin()+1, w->end()-1); result << value; } else if (mapOpNames.count(*w)) { // opcode, e.g. OP_ADD or ADD: result << mapOpNames[*w]; } else { throw runtime_error("script parse error"); } } return result; }
// Old script.cpp SignatureHash function uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType) { static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); if (nIn >= txTo.vin.size()) { printf("ERROR: SignatureHash(): nIn=%d out of range\n", nIn); return one; } CMutableTransaction txTmp(txTo); // In case concatenating two scripts ends up with two codeseparators, // or an extra one at the end, this prevents all those possible incompatibilities. scriptCode.FindAndDelete(CScript(OP_CODESEPARATOR)); // Blank out other inputs' signatures for (unsigned int i = 0; i < txTmp.vin.size(); i++) txTmp.vin[i].scriptSig = CScript(); txTmp.vin[nIn].scriptSig = scriptCode; // Blank out some of the outputs if ((nHashType & 0x1f) == SIGHASH_NONE) { // Wildcard payee txTmp.vout.clear(); // Let the others update at will for (unsigned int i = 0; i < txTmp.vin.size(); i++) if (i != nIn) txTmp.vin[i].nSequence = 0; } else if ((nHashType & 0x1f) == SIGHASH_SINGLE) { // Only lock-in the txout payee at same index as txin unsigned int nOut = nIn; if (nOut >= txTmp.vout.size()) { printf("ERROR: SignatureHash(): nOut=%d out of range\n", nOut); return one; } txTmp.vout.resize(nOut+1); for (unsigned int i = 0; i < nOut; i++) txTmp.vout[i].SetNull(); // Let the others update at will for (unsigned int i = 0; i < txTmp.vin.size(); i++) if (i != nIn) txTmp.vin[i].nSequence = 0; } // Blank out other inputs completely, not recommended for open transactions if (nHashType & SIGHASH_ANYONECANPAY) { txTmp.vin[0] = txTmp.vin[nIn]; txTmp.vin.resize(1); } // Blank out the joinsplit signature. memset(&txTmp.joinSplitSig[0], 0, txTmp.joinSplitSig.size()); // Serialize and hash CHashWriter ss(SER_GETHASH, 0); ss << txTmp << nHashType; return ss.GetHash(); }
bool CWebPageDef::r_Verb( CScript & s, CTextConsole * pSrc ) // some command on this object as a target { ADDTOCALLSTACK("CWebPageDef::r_Verb"); EXC_TRY("Verb"); ASSERT(pSrc); sm_iListIndex = 0; TCHAR *pszTmp2 = Str_GetTemp(); WV_TYPE iHeadKey = (WV_TYPE) FindTableSorted( s.GetKey(), sm_szVerbKeys, COUNTOF(sm_szVerbKeys)-1 ); switch ( iHeadKey ) { case WV_WEBPAGE: { // serv a web page to the pSrc CClient *pClient = dynamic_cast<CClient *>(pSrc); if ( !pClient ) return false; return ServPage(pClient, s.GetArgStr(), NULL); } case WV_CLIENTLIST: { ClientIterator it; for ( CClient *pClient = it.next(); pClient != NULL; pClient = it.next() ) { CChar *pChar = pClient->GetChar(); if ( !pChar ) continue; if ( pChar->IsStatFlag(STATF_Insubstantial) && (pClient->GetPrivLevel() > PLEVEL_Player) ) continue; sm_iListIndex++; LPCTSTR pszArgs = s.GetArgStr(); if ( pszArgs[0] == '\0' ) pszArgs = "<tr><td>%NAME%</td><td>%REGION.NAME%</td></tr>\n"; strcpy(pszTmp2, pszArgs); pChar->ParseText(Str_MakeFiltered(pszTmp2), &g_Serv, 1); pSrc->SysMessage(pszTmp2); } break; } case WV_GUILDLIST: case WV_TOWNLIST: { if ( !s.HasArgs() ) return false; IT_TYPE needtype = (iHeadKey == WV_GUILDLIST) ? IT_STONE_GUILD : IT_STONE_TOWN; for ( size_t i = 0; i < g_World.m_Stones.GetCount(); i++ ) { CItemStone *pStone = g_World.m_Stones[i]; if ( !pStone || !pStone->IsType(needtype) ) continue; sm_iListIndex++; strcpy(pszTmp2, s.GetArgStr()); pStone->ParseText(Str_MakeFiltered(pszTmp2), &g_Serv, 1); pSrc->SysMessage(pszTmp2); } break; } case WV_GMPAGELIST: { if ( !s.HasArgs() ) return false; CGMPage *pPage = static_cast<CGMPage *>(g_World.m_GMPages.GetHead()); for ( ; pPage != NULL; pPage = pPage->GetNext() ) { sm_iListIndex++; strcpy(pszTmp2, s.GetArgStr()); pPage->ParseText(Str_MakeFiltered(pszTmp2), &g_Serv, 1); pSrc->SysMessage(pszTmp2); } break; } default: return CResourceLink::r_Verb(s, pSrc); } return true; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPTSRC; EXC_DEBUG_END; return false; }
void ProcessMessageMasternode(CNode* pfrom, std::string& strCommand, CDataStream& vRecv) { if (strCommand == "dsee") { //DarkSend Election Entry if(fLiteMode) return; //disable all darksend/masternode related functionality bool fIsInitialDownload = IsInitialBlockDownload(); if(fIsInitialDownload) return; CTxIn vin; CService addr; CPubKey pubkey; CPubKey pubkey2; vector<unsigned char> vchSig; int64_t sigTime; int count; int current; int64_t lastUpdated; int protocolVersion; std::string strMessage; // 70047 and greater vRecv >> vin >> addr >> vchSig >> sigTime >> pubkey >> pubkey2 >> count >> current >> lastUpdated >> protocolVersion; // make sure signature isn't in the future (past is OK) if (sigTime > GetAdjustedTime() + 60 * 60) { printf("dsee - Signature rejected, too far into the future %s\n", vin.ToString().c_str()); return; } bool isLocal = addr.IsRFC1918() || addr.IsLocal(); //if(Params().MineBlocksOnDemand()) isLocal = false; std::string vchPubKey(pubkey.vchPubKey.begin(), pubkey.vchPubKey.end()); std::string vchPubKey2(pubkey2.vchPubKey.begin(), pubkey2.vchPubKey.end()); strMessage = addr.ToString() + boost::lexical_cast<std::string>(sigTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(protocolVersion); if(protocolVersion < MIN_MN_PROTO_VERSION) { printf("dsee - ignoring outdated masternode %s protocol version %d\n", vin.ToString().c_str(), protocolVersion); return; } CScript pubkeyScript; pubkeyScript =GetScriptForDestination(pubkey.GetID()); if(pubkeyScript.size() != 25) { printf("dsee - pubkey the wrong size\n"); pfrom->Misbehaving(100); return; } CScript pubkeyScript2; pubkeyScript2 =GetScriptForDestination(pubkey2.GetID()); if(pubkeyScript2.size() != 25) { printf("dsee - pubkey2 the wrong size\n"); pfrom->Misbehaving(100); return; } std::string errorMessage = ""; if(!darkSendSigner.VerifyMessage(pubkey, vchSig, strMessage, errorMessage)){ printf("dsee - Got bad masternode address signature\n"); pfrom->Misbehaving(100); return; } //search existing masternode list, this is where we update existing masternodes with new dsee broadcasts LOCK(cs_masternodes); BOOST_FOREACH(CMasterNode& mn, vecMasternodes) { if(mn.vin.prevout == vin.prevout) { // count == -1 when it's a new entry // e.g. We don't want the entry relayed/time updated when we're syncing the list // mn.pubkey = pubkey, IsVinAssociatedWithPubkey is validated once below, // after that they just need to match if(count == -1 && mn.pubkey == pubkey && !mn.UpdatedWithin(MASTERNODE_MIN_DSEE_SECONDS)){ mn.UpdateLastSeen(); if(mn.now < sigTime){ //take the newest entry printf("dsee - Got updated entry for %s\n", addr.ToString().c_str()); mn.pubkey2 = pubkey2; mn.now = sigTime; mn.sig = vchSig; mn.protocolVersion = protocolVersion; mn.addr = addr; RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion); } } return; } } // make sure the vout that was signed is related to the transaction that spawned the masternode // - this is expensive, so it's only done once per masternode if(!darkSendSigner.IsVinAssociatedWithPubkey(vin, pubkey)) { printf("dsee - Got mismatched pubkey and vin\n"); pfrom->Misbehaving(100); return; } if(fDebug) printf("dsee - Got NEW masternode entry %s\n", addr.ToString().c_str()); // make sure it's still unspent // - this is checked later by .check() in many places and by ThreadCheckDarkSendPool() CTransaction tx = CTransaction(); CTxOut vout = CTxOut(24999*COIN, darkSendPool.collateralPubKey); tx.vin.push_back(vin); tx.vout.push_back(vout); //if(AcceptableInputs(mempool, state, tx)){ bool* pfMissingInputs = false; if(AcceptableInputs(mempool, tx, false, pfMissingInputs)){ if(fDebug) printf("dsee - Accepted masternode entry %i %i\n", count, current); if(GetInputAge(vin) < MASTERNODE_MIN_CONFIRMATIONS){ printf("dsee - Input must have least %d confirmations\n", MASTERNODE_MIN_CONFIRMATIONS); pfrom->Misbehaving(20); return; } // use this as a peer addrman.Add(CAddress(addr), pfrom->addr, 2*60*60); // add our masternode CMasterNode mn(addr, vin, pubkey, vchSig, sigTime, pubkey2, protocolVersion); mn.UpdateLastSeen(lastUpdated); vecMasternodes.push_back(mn); // if it matches our masternodeprivkey, then we've been remotely activated if(pubkey2 == activeMasternode.pubKeyMasternode && protocolVersion == PROTOCOL_VERSION){ activeMasternode.EnableHotColdMasterNode(vin, addr); } if(count == -1 && !isLocal) RelayDarkSendElectionEntry(vin, addr, vchSig, sigTime, pubkey, pubkey2, count, current, lastUpdated, protocolVersion); } else { printf("dsee - Rejected masternode entry %s\n", addr.ToString().c_str()); int nDoS = 0; /* if (state.IsInvalid(nDoS)) { printf("dsee - %s from %s %s was not accepted into the memory pool\n", tx.GetHash().ToString().c_str(), pfrom->addr.ToString().c_str(), pfrom->cleanSubVer.c_str()); if (nDoS > 0) pfrom->Misbehaving(nDoS); }*/ } } else if (strCommand == "dseep") { //DarkSend Election Entry Ping
void CreateMultiSigAddrDialog::create() { int nRequired = ui->comboBoxRequire->itemData(ui->comboBoxRequire->currentIndex()).toInt(); int total = ui->comboBoxTotal->itemData(ui->comboBoxTotal->currentIndex()).toInt(); QString pubkeyHex[3]; pubkeyHex[0] = ui->pubkeyEdit0->text(); pubkeyHex[1] = ui->pubkeyEdit1->text(); if ( 3 == total ) pubkeyHex[2] = ui->pubkeyEdit2->text(); int myKeyNum = 0; //std::vector<CPubKey> pubkeys; std::vector<CKey> pubkeys; pubkeys.resize(total); for (unsigned int i = 0; i < total; i++) { const std::string& ks = pubkeyHex[i].toStdString(); if (IsHex(ks)) { CPubKey vchPubKey(ParseHex(ks)); //if (!vchPubKey.IsFullyValid()) if (!vchPubKey.IsValid() || !pubkeys[i].SetPubKey(vchPubKey)) { QMessageBox::warning(this, windowTitle(), tr("Invalid public key \"%1\" ").arg(pubkeyHex[i]), QMessageBox::Ok, QMessageBox::Ok); return; } //pubkeys[i] = vchPubKey; if (IsMine(*pwalletMain, vchPubKey.GetID())) myKeyNum += 1; } else { QMessageBox::warning(this, windowTitle(), tr("Invalid public key \"%1\" ").arg(pubkeyHex[i]), QMessageBox::Ok, QMessageBox::Ok); return; } } /* if ( 0 == myKeyNum ) { QMessageBox::warning(this, windowTitle(), tr("No public key belongs to this wallet!"), QMessageBox::Ok, QMessageBox::Ok); return; } */ if ( total == myKeyNum ) { QMessageBox::warning(this, windowTitle(), tr("All public keys belong to this wallet!"), QMessageBox::Ok, QMessageBox::Ok); return; } CScript inner; inner.SetMultisig(nRequired, pubkeys); CScriptID innerID = inner.GetID(); pwalletMain->AddCScript(inner); std::string strAccount; //pwalletMain->SetAddressBookName(innerID, strAccount); std::string purpose; pwalletMain->SetAddressBook(innerID, strAccount, purpose); accept(); }
//////////////////////////////////////////////////////////////////////////////// // 트랜스 서버용 선거 클래스 CTElection::CTElection( CLord* pLord ) : IElection( pLord ), #ifdef __INTERNALSERVER m_bRun( FALSE ) // 내부 서버는 군주 프로세스 비활성 #else // __INTERNALSERVER m_bRun( TRUE ) #endif // __INTERNALSERVER { } CTElection::~CTElection() { } BOOL CTElection::Initialize( const char* szFile ) { // 초기화 if( !ReadIni( szFile ) ) // 스크립트 로드 { election::OutputDebugString( "CTElection::Initialize(): LoadScript(): file not found: %s", szFile ); return FALSE; } return TRUE; } BOOL CTElection::ReadIni( const char* szFile ) { // 스크립트 로드 CScript s; if( s.Load( szFile ) == FALSE ) return FALSE; s.GetToken(); while( s.tok != FINISHED ) { if( s.Token == _T( "property" ) ) { s.GetToken(); // { s.GetToken(); while( *s.token != '}' ) { if( s.Token == _T( "nDayOfWeek" ) ) property.nDayOfWeek = s.GetNumber(); else if( s.Token == _T( "nHour" ) ) property.nHour = s.GetNumber(); else if( s.Token == _T( "tCandidacy" ) ) property.tCandidacy = s.GetNumber(); else if( s.Token == _T( "tVote" ) ) property.tVote = s.GetNumber(); else if( s.Token == _T( "nDays" ) ) property.nDays = s.GetNumber(); s.GetToken(); } } else if( s.Token == _T( "rate" ) ) { s.GetToken(); // { float fRate = s.GetFloat(); while( *s.token != '}' ) { property.m_vReturnDepositRates.push_back( fRate ); fRate = s.GetFloat(); } } else if( s.Token == _T( "fRequirementFactor" ) ) { property.fRequirementFactor = s.GetFloat(); } else if( s.Token == _T( "item" ) ) { int iIndex = s.GetNumber(); s.GetToken(); // { int nItem = s.GetNumber(); while( *s.token != '}' ) { property.m_vItems[iIndex].push_back( nItem ); nItem = s.GetNumber(); } } s.GetToken(); } return TRUE; }
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); if ((flags & SCRIPT_VERIFY_SIGPUSHONLY) != 0 && !scriptSig.IsPushOnly()) { return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY); } vector<vector<unsigned char> > stack, stackCopy; if (!EvalScript(stack, scriptSig, flags, checker, serror)) // serror is set return false; if (flags & SCRIPT_VERIFY_P2SH) stackCopy = stack; if (!EvalScript(stack, scriptPubKey, flags, checker, serror)) // serror is set return false; if (stack.empty()) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); if (CastToBool(stack.back()) == false) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); // Additional validation for spend-to-script-hash transactions: if ((flags & SCRIPT_VERIFY_P2SH) && scriptPubKey.IsPayToScriptHash()) { // scriptSig must be literals-only or validation fails if (!scriptSig.IsPushOnly()) return set_error(serror, SCRIPT_ERR_SIG_PUSHONLY); // Restore stack. swap(stack, stackCopy); // stack cannot be empty here, because if it was the // P2SH HASH <> EQUAL scriptPubKey would be evaluated with // an empty stack and the EvalScript above would return false. assert(!stack.empty()); const valtype& pubKeySerialized = stack.back(); CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end()); popstack(stack); if (!EvalScript(stack, pubKey2, flags, checker, serror)) // serror is set return false; if (stack.empty()) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); if (!CastToBool(stack.back())) return set_error(serror, SCRIPT_ERR_EVAL_FALSE); } // The CLEANSTACK check is only performed after potential P2SH evaluation, // as the non-P2SH evaluation of a P2SH script will obviously not result in // a clean stack (the P2SH inputs remain). if ((flags & SCRIPT_VERIFY_CLEANSTACK) != 0) { // Disallow CLEANSTACK without P2SH, as otherwise a switch CLEANSTACK->P2SH+CLEANSTACK // would be possible, which is not a softfork (and P2SH should be one). assert((flags & SCRIPT_VERIFY_P2SH) != 0); if (stack.size() != 1) { return set_error(serror, SCRIPT_ERR_CLEANSTACK); } } return set_success(serror); }
bool CResourceRefArray::r_LoadVal( CScript & s, RES_TYPE restype ) { ADDTOCALLSTACK("CResourceRefArray::r_LoadVal"); EXC_TRY("LoadVal"); bool fRet = false; // A bunch of CResourceLink (CResourceDef) pointers. // Add or remove from the list. // RETURN: false = it failed. // ? "TOWN" and "REGION" are special ! TCHAR * pszCmd = s.GetArgStr(); TCHAR * ppBlocks[128]; // max is arbitrary size_t iArgCount = Str_ParseCmds( pszCmd, ppBlocks, COUNTOF(ppBlocks)); for ( size_t i = 0; i < iArgCount; i++ ) { pszCmd = ppBlocks[i]; if ( pszCmd[0] == '-' ) { // remove a frag or all frags. pszCmd ++; if ( pszCmd[0] == '0' || pszCmd[0] == '*' ) { RemoveAll(); fRet = true; continue; } CResourceLink * pResourceLink = dynamic_cast<CResourceLink *>( g_Cfg.ResourceGetDefByName( restype, pszCmd )); if ( pResourceLink == NULL ) { fRet = false; continue; } int iIndex = RemovePtr(pResourceLink); fRet = ( iIndex >= 0 ); } else { // Add a single knowledge fragment or appropriate group item. if ( pszCmd[0] == '+' ) pszCmd ++; CResourceLink * pResourceLink = dynamic_cast<CResourceLink *>( g_Cfg.ResourceGetDefByName( restype, pszCmd )); if ( pResourceLink == NULL ) { fRet = false; DEBUG_ERR(( "Unknown '%s' Resource '%s'\n", CResourceBase::GetResourceBlockName(restype), pszCmd )); continue; } // Is it already in the list ? fRet = true; if ( ContainsPtr(pResourceLink) ) { continue; } if ( g_Cfg.m_pEventsPetLink.ContainsPtr(pResourceLink) ) { DEBUG_ERR(("'%s' already defined in sphere.ini - skipping\n", pResourceLink->GetName())); continue; } else if ( g_Cfg.m_pEventsPlayerLink.ContainsPtr(pResourceLink) ) { DEBUG_ERR(("'%s' already defined in sphere.ini - skipping\n", pResourceLink->GetName())); continue; } else if ( restype == RES_REGIONTYPE && g_Cfg.m_pEventsRegionLink.ContainsPtr(pResourceLink) ) { DEBUG_ERR(("'%s' already defined in sphere.ini - skipping\n", pResourceLink->GetName())); continue; } else if ( g_Cfg.m_iEventsItemLink.ContainsPtr(pResourceLink) ) { DEBUG_ERR(("'%s' already defined in sphere.ini - skipping\n", pResourceLink->GetName())); continue; } Add( pResourceLink ); } } return fRet; EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPT; EXC_DEBUG_END; return false; }
bool CBaseBaseDef::r_LoadVal( CScript & s ) { ADDTOCALLSTACK("CBaseBaseDef::r_LoadVal"); EXC_TRY("LoadVal"); if ( s.IsKeyHead( "TAG.", 4 )) { bool fQuoted = false; m_TagDefs.SetStr( s.GetKey()+4, fQuoted, s.GetArgStr( &fQuoted ), false ); return( true ); } if ( s.IsKeyHead( "TAG0.", 5 )) { bool fQuoted = false; m_TagDefs.SetStr( s.GetKey()+5, fQuoted, s.GetArgStr( &fQuoted ), true ); return( true ); } switch ( FindTableSorted( s.GetKey(), sm_szLoadKeys, COUNTOF( sm_szLoadKeys )-1 )) { //Set as Strings case OBC_HITSPELL: case OBC_SLAYER: case OBC_SLAYERLESSER: case OBC_SLAYERMISC: case OBC_SLAYERSUPER: case OBC_ABILITYPRIMARY: case OBC_ABILITYSECONDARY: case OBC_MANABURST: { bool fQuoted = false; SetDefStr(s.GetKey(), s.GetArgStr( &fQuoted ), fQuoted); } break; //Set as number only case OBC_BALANCED: case OBC_BANE: case OBC_BATTLELUST: case OBC_BLOODDRINKER: case OBC_CASTINGFOCUS: case OBC_DAMCHAOS: case OBC_DAMCOLD: case OBC_DAMDIRECT: case OBC_DAMENERGY: case OBC_DAMFIRE: case OBC_DAMMODIFIER: case OBC_DAMPHYSICAL: case OBC_DECREASEHITCHANCE: case OBC_DAMPOISON: case OBC_EATERCOLD: case OBC_EATERDAM: case OBC_EATERENERGY: case OBC_EATERFIRE: case OBC_EATERKINETIC: case OBC_EATERPOISON: case OBC_ENHANCEPOTIONS: case OBC_EXPANSION: case OBC_FASTERCASTING: case OBC_FASTERCASTRECOVERY: case OBC_HITAREACOLD: case OBC_HITAREAENERGY: case OBC_HITAREAFIRE: case OBC_HITAREAPHYSICAL: case OBC_HITAREAPOISON: case OBC_HITCURSE: case OBC_HITDISPEL: case OBC_HITFATIGUE: case OBC_HITFIREBALL: case OBC_HITHARM: case OBC_HITLEECHLIFE: case OBC_HITLEECHMANA: case OBC_HITLEECHSTAM: case OBC_HITLIGHTNING: case OBC_HITLOWERATK: case OBC_HITLOWERDEF: case OBC_HITMAGICARROW: case OBC_HITMANADRAIN: case OBC_INCREASEDAM: case OBC_INCREASEDEFCHANCE: case OBC_INCREASEDEFCHANCEMAX: case OBC_INCREASEHITCHANCE: case OBC_INCREASEGOLD: case OBC_INCREASEKARMALOSS: case OBC_INCREASESPELLDAM: case OBC_INCREASESWINGSPEED: case OBC_LOWERAMMOCOST: case OBC_LOWERMANACOST: case OBC_LOWERREAGENTCOST: case OBC_LOWERREQ: case OBC_LUCK: case OBC_MANABURSTFREQUENCY: case OBC_MANABURSTKARMA: case OBC_NIGHTSIGHT: case OBC_RAGEFOCUS: case OBC_REACTIVEPARALYZE: case OBC_REFLECTPHYSICALDAM: case OBC_REGENFOOD: case OBC_REGENHITS: case OBC_REGENMANA: case OBC_REGENSTAM: case OBC_REGENVALFOOD: case OBC_REGENVALHITS: case OBC_REGENVALMANA: case OBC_REGENVALSTAM: case OBC_RESCOLD: case OBC_RESFIRE: case OBC_RESENERGY: case OBC_RESPHYSICAL: case OBC_RESPOISON: case OBC_RESCOLDMAX: case OBC_RESFIREMAX: case OBC_RESENERGYMAX: case OBC_RESPHYSICALMAX: case OBC_RESPOISONMAX: case OBC_RESONANCECOLD: case OBC_RESONANCEENERGY: case OBC_RESONANCEFIRE: case OBC_RESONANCEKINETIC: case OBC_RESONANCEPOISON: case OBC_SOULCHARGE: case OBC_SOULCHARGECOLD: case OBC_SOULCHARGEENERGY: case OBC_SOULCHARGEFIRE: case OBC_SOULCHARGEKINETIC: case OBC_SOULCHARGEPOISON: case OBC_SPELLCONSUMPTION: case OBC_SPELLFOCUSING: case OBC_SPLINTERINGWEAPON: case OBC_VELOCITY: case OBC_SPELLCHANNELING: case OBC_NAMELOC: case OBC_HITSPELLSTR: case OBC_WEIGHTREDUCTION: case OBC_COMBATBONUSSTAT: case OBC_COMBATBONUSPERCENT: { SetDefNum(s.GetKey(),s.GetArgVal()); return true; } case OBC_CATEGORY://* case OBC_SUBSECTION://* case OBC_DESCRIPTION://* { bool fQuoted = false; SetDefStr(s.GetKey(), s.GetArgStr( &fQuoted ), fQuoted); if ( !strcmpi(GetDefStr(sm_szLoadKeys[OBC_DESCRIPTION]), "@") ) SetDefStr(sm_szLoadKeys[OBC_DESCRIPTION], GetDefStr(sm_szLoadKeys[OBC_SUBSECTION])); } return true; case OBC_ARMOR: { INT64 piVal[2]; size_t iQty = Str_ParseCmds( s.GetArgStr(), piVal, COUNTOF(piVal)); m_defenseBase = static_cast<unsigned char>(piVal[0]); if ( iQty > 1 ) { m_defenseRange = static_cast<unsigned char>(piVal[1]) - m_defenseBase; } else { m_defenseRange = 0; } } return( true ); case OBC_DAM: { INT64 piVal[2]; size_t iQty = Str_ParseCmds( s.GetArgStr(), piVal, COUNTOF(piVal)); m_attackBase = static_cast<unsigned char>(piVal[0]); if ( iQty > 1 ) { m_attackRange = static_cast<unsigned char>(piVal[1]) - m_attackBase; } else { m_attackRange = 0; } } return( true ); case OBC_BASEID: return( false ); case OBC_CAN: m_Can = s.GetArgVal();// | ( m_Can & ( CAN_C_INDOORS|CAN_C_EQUIP|CAN_C_USEHANDS|CAN_C_NONHUMANOID )); //Fixed #2326 ? return( true ); case OBC_DEFNAME: case OBC_DEFNAME2: return SetResourceName( s.GetArgStr()); case OBC_HEIGHT: m_Height = static_cast<height_t>(s.GetArgVal()); return( true ); case OBC_INSTANCES: return( false ); case OBC_NAME: SetTypeName( s.GetArgStr()); return( true ); case OBC_RANGE: { INT64 piVal[2]; size_t iQty = Str_ParseCmds( s.GetArgStr(), piVal, COUNTOF(piVal)); if ( iQty > 1 ) { INT64 iRange = ((piVal[0] & 0xff) << 8) & 0xff00; iRange |= (piVal[1] & 0xff); SetDefNum(s.GetKey(),iRange, false); //m_range = ((piVal[0] & 0xff) << 8) & 0xff00; //m_range |= (piVal[1] & 0xff); } else { SetDefNum(s.GetKey(),piVal[0], false); //m_range = static_cast<WORD>(piVal[0]); } } return( true ); case OBC_RESOURCES: m_BaseResources.Load( s.GetArgStr()); return( true ); case OBC_RESLEVEL: return( SetResLevel(static_cast<unsigned char>(s.GetArgVal())) ); case OBC_RESDISPDNHUE: SetResDispDnHue(static_cast<HUE_TYPE>(s.GetArgVal())); return( true ); case OBC_TEVENTS: return( m_TEvents.r_LoadVal( s, RES_EVENTS )); } return( CScriptObj::r_LoadVal(s)); EXC_CATCH; EXC_DEBUG_START; EXC_ADD_SCRIPT; EXC_DEBUG_END; return false; }
void AddEditStormNode::on_okButton_clicked() { if(ui->aliasLineEdit->text() == "") { QMessageBox msg; msg.setText("Please enter an alias."); msg.exec(); return; } else if(ui->addressLineEdit->text() == "") { QMessageBox msg; msg.setText("Please enter an address."); msg.exec(); return; } else { CStormNodeConfig c; c.sAlias = ui->aliasLineEdit->text().toStdString(); c.sAddress = ui->addressLineEdit->text().toStdString(); CKey secret; secret.MakeNewKey(false); c.sStormnodePrivKey = CBitcoinSecret(secret).ToString(); CWalletDB walletdb(pwalletMain->strWalletFile); CAccount account; walletdb.ReadAccount(c.sAlias, account); bool bKeyUsed = false; bool bForceNew = false; // Check if the current key has been used if (account.vchPubKey.IsValid()) { CScript scriptPubKey; scriptPubKey.SetDestination(account.vchPubKey.GetID()); for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end() && account.vchPubKey.IsValid(); ++it) { const CWalletTx& wtx = (*it).second; BOOST_FOREACH(const CTxOut& txout, wtx.vout) if (txout.scriptPubKey == scriptPubKey) bKeyUsed = true; } } // Generate a new key if (!account.vchPubKey.IsValid() || bForceNew || bKeyUsed) { if (!pwalletMain->GetKeyFromPool(account.vchPubKey)) { QMessageBox msg; msg.setText("Keypool ran out, please call keypoolrefill first."); msg.exec(); return; } pwalletMain->SetAddressBookName(account.vchPubKey.GetID(), c.sAlias); walletdb.WriteAccount(c.sAlias, account); } c.sCollateralAddress = CBitcoinAddress(account.vchPubKey.GetID()).ToString(); pwalletMain->mapMyStormNodes.insert(make_pair(c.sAddress, c)); walletdb.WriteStormNodeConfig(c.sAddress, c); uiInterface.NotifyStormNodeChanged(c); accept(); }
bool CScript::init(char* scr) { char* tmp = scr; while(*tmp=='\n' || *tmp==' ' || *tmp=='\t' || *tmp==',') //whitespace trim { tmp++; if(*tmp=='\0') //whitespace went straight to eos return false; } if (*tmp!='<') //if we didn't get a tag we got an argument save as arg and exit { children=NULL; value=scr; //get rid of | | for strings (DO LATER) return true; } else //otherwise we parse tag and all it's arguments(passing downwards) { children = new LinkedList<CScript>(); tmp = safeGoto('>',tmp); if(*tmp=='\0') return false; char* buffer = new char[tmp-scr+2]; memcpy(buffer,scr,tmp-scr+2); buffer[tmp-scr+1]='\0'; value=buffer; //tag should now be <something> //cerr << value << endl; //get beginning { skip whitespace and other stuff tmp = safeGoto('{',tmp); if(*tmp=='\0') return false; tmp++; //go past { if(*tmp=='\0') //nothing after { (segfault protection) return false; //start getting child arguments past '{' (if there are any) bool notDone=true; while(notDone) { while(*tmp=='\n' || *tmp==' ' || *tmp=='\t' || *tmp==',') //whitespace trim { tmp++; if(*tmp=='\0') //whitespace went straight to eos return false; } if (*tmp=='<') //make a new recursing child { char* startPosition = tmp; tmp = safeGoto('>',tmp); if(*tmp=='\0') return false; tmp = safeGoto('{',tmp); if(*tmp=='\0') //never found { flag an error return false; tmp = cursePastBrackets(tmp); if(*tmp=='\0') return false; char* buffer=new char[tmp-startPosition+2]; memcpy(buffer,startPosition,tmp-startPosition+2); buffer[tmp-startPosition+1]='\0'; CScript *script = new CScript(); children->insert(script); script->init(buffer); //new script will span out here }//end of current child is recursive if block else //if child wasn't recursive then it was just an argument { char* startPosition = tmp; //will catch empty tags here(ie <destroy> { } while(*tmp!='}' && *tmp!=',') { tmp++; if(*tmp=='\0') //no end to argument flag error return false; } char* buffer=new char[tmp-startPosition+1]; //no +1 because we don't want the } or , memcpy(buffer,startPosition,tmp-startPosition+1); //but it does actually copy and the terminator doesn't so.. buffer[tmp-startPosition]='\0';//terminate it CScript *script = new CScript(); children->insert(script); //add to list of children //std::cerr << "\t" << buffer << std::endl; script->init(buffer); //script will store argument }//end of current child was non recursive handle block while(*tmp=='\n' || *tmp==' ' || *tmp=='\t' || *tmp==',') //whitespace trim { tmp++; if(*tmp=='\0') //whitespace went straight to eos return false; } if(*tmp=='}') //found the end notDone=false; }//end of looping of argument parsing return true; }//end of main else block(handling a tag script) return false; //should never be hit }
void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) { if (!model) return; // nPayAmount qint64 nPayAmount = 0; bool fLowOutput = false; bool fDust = false; CTransaction txDummy; BOOST_FOREACH(const PAIRTYPE(QString, qint64) &payee, CoinControlDialog::payAddresses) { qint64 amount = payee.second; nPayAmount += amount; if (amount > 0) { if (amount < CENT) fLowOutput = true; } } QString sPriorityLabel = ""; int64 nAmount = 0; int64 nPayFee = 0; int64 nAfterFee = 0; int64 nChange = 0; unsigned int nBytes = 0; unsigned int nBytesInputs = 0; double dPriority = 0; double dPriorityInputs = 0; unsigned int nQuantity = 0; vector<COutPoint> vCoinControl; vector<COutput> vOutputs; coinControl->ListSelected(vCoinControl); model->getOutputs(vCoinControl, vOutputs); nPayFee = nTransactionFee; loop { txDummy.vin.clear(); txDummy.vout.clear(); nQuantity = 0; nAmount = 0; dPriorityInputs = 0; nBytesInputs = 0; // Inputs BOOST_FOREACH(const COutput& out, vOutputs) { // Quantity nQuantity++; // Amount nAmount += out.tx->vout[out.i].nValue; // Priority dPriorityInputs += (double)out.tx->vout[out.i].nValue * (out.nDepth+1); // Bytes txDummy.vin.push_back(CTxIn(out.tx->vout[out.i].GetHash(), out.tx->vout[out.i].nValue)); nBytesInputs += 73; // Future ECDSA signature in DER format } // Outputs BOOST_FOREACH(const PAIRTYPE(QString, qint64) &payee, CoinControlDialog::payAddresses) { QString address = payee.first; qint64 amount = payee.second; CScript scriptPubKey; scriptPubKey.SetDestination(CBitcoinAddress(address.toStdString()).Get()); CTxOut txout(amount, scriptPubKey); txDummy.vout.push_back(txout); } // calculation if (nQuantity > 0) { nChange = nAmount - nPayAmount - nPayFee; // if sub-cent change is required, the fee must be raised to at least MIN_TX_FEE // or until nChange becomes zero // NOTE: this depends on the exact behaviour of GetMinFee if (nPayFee < MIN_TX_FEE && nChange > 0 && nChange < CENT) { int64 nMoveToFee = min(nChange, MIN_TX_FEE - nPayFee); nChange -= nMoveToFee; nPayFee += nMoveToFee; } // Tamcoin: sub-cent change is moved to fee if (nChange > 0 && nChange < MIN_TXOUT_AMOUNT) { nPayFee += nChange; nChange = 0; } if (nChange > 0) { // Add a change address in the outputs CTxOut txout(0, (CScript)vector<unsigned char>(24, 0)); txDummy.vout.push_back(txout); } // Bytes nBytes = nBytesInputs + GetSerializeSize(*(CTransaction*)&txDummy, SER_NETWORK, PROTOCOL_VERSION); // Priority dPriority = dPriorityInputs / nBytes; sPriorityLabel = CoinControlDialog::getPriorityLabel(dPriority); // Fee int64 nFee = nTransactionFee * (1 + (int64)nBytes / 1000); // Min Fee int64 nMinFee = txDummy.GetMinFee(1, false, GMF_SEND, nBytes); if (nPayFee < max(nFee, nMinFee)) { nPayFee = max(nFee, nMinFee); continue; } // after fee nAfterFee = nAmount - nPayFee; if (nAfterFee < 0) nAfterFee = 0; } break; }
bool CActiveMasternode::Register(CTxIn vin, CService service, CKey keyCollateralAddress, CPubKey pubKeyCollateralAddress, CKey keyMasternode, CPubKey pubKeyMasternode, CScript donationAddress, int donationPercentage, std::string &retErrorMessage) { std::string errorMessage; std::vector<unsigned char> vchMasterNodeSignature; std::string strMasterNodeSignMessage; int64_t masterNodeSignatureTime = GetAdjustedTime(); std::string vchPubKey(pubKeyCollateralAddress.begin(), pubKeyCollateralAddress.end()); std::string vchPubKey2(pubKeyMasternode.begin(), pubKeyMasternode.end()); std::string strMessage = service.ToString() + boost::lexical_cast<std::string>(masterNodeSignatureTime) + vchPubKey + vchPubKey2 + boost::lexical_cast<std::string>(PROTOCOL_VERSION) + donationAddress.ToString() + boost::lexical_cast<std::string>(donationPercentage); if(!darkSendSigner.SignMessage(strMessage, errorMessage, vchMasterNodeSignature, keyCollateralAddress)) { retErrorMessage = "sign message failed: " + errorMessage; LogPrintf("CActiveMasternode::Register() - Error: %s\n", retErrorMessage.c_str()); return false; } if(!darkSendSigner.VerifyMessage(pubKeyCollateralAddress, vchMasterNodeSignature, strMessage, errorMessage)) { retErrorMessage = "Verify message failed: " + errorMessage; LogPrintf("CActiveMasternode::Register() - Error: %s\n", retErrorMessage.c_str()); return false; } CMasternode* pmn = mnodeman.Find(vin); if(pmn == NULL) { LogPrintf("CActiveMasternode::Register() - Adding to masternode list service: %s - vin: %s\n", service.ToString().c_str(), vin.ToString().c_str()); CMasternode mn(service, vin, pubKeyCollateralAddress, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyMasternode, PROTOCOL_VERSION, donationAddress, donationPercentage); mn.UpdateLastSeen(masterNodeSignatureTime); mnodeman.Add(mn); } //send to all peers LogPrintf("CActiveMasternode::Register() - RelayElectionEntry vin = %s\n", vin.ToString().c_str()); mnodeman.RelayMasternodeEntry(vin, service, vchMasterNodeSignature, masterNodeSignatureTime, pubKeyCollateralAddress, pubKeyMasternode, -1, -1, masterNodeSignatureTime, PROTOCOL_VERSION, donationAddress, donationPercentage); return true; }
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror) { static const CScriptNum bnZero(0); static const CScriptNum bnOne(1); static const CScriptNum bnFalse(0); static const CScriptNum bnTrue(1); static const valtype vchFalse(0); static const valtype vchZero(0); static const valtype vchTrue(1, 1); CScript::const_iterator pc = script.begin(); CScript::const_iterator pend = script.end(); CScript::const_iterator pbegincodehash = script.begin(); opcodetype opcode; valtype vchPushValue; vector<bool> vfExec; vector<valtype> altstack; set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); if (script.size() > 10000) return set_error(serror, SCRIPT_ERR_SCRIPT_SIZE); int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; try { while (pc < pend) { bool fExec = !count(vfExec.begin(), vfExec.end(), false); // // Read instruction // if (!script.GetOp(pc, opcode, vchPushValue)) return set_error(serror, SCRIPT_ERR_BAD_OPCODE); if (vchPushValue.size() > MAX_SCRIPT_ELEMENT_SIZE) return set_error(serror, SCRIPT_ERR_PUSH_SIZE); // Note how OP_RESERVED does not count towards the opcode limit. if (opcode > OP_16 && ++nOpCount > 201) return set_error(serror, SCRIPT_ERR_OP_COUNT); if (opcode == OP_CAT || opcode == OP_SUBSTR || opcode == OP_LEFT || opcode == OP_RIGHT || opcode == OP_INVERT || opcode == OP_AND || opcode == OP_OR || opcode == OP_XOR || opcode == OP_2MUL || opcode == OP_2DIV || opcode == OP_MUL || opcode == OP_DIV || opcode == OP_MOD || opcode == OP_LSHIFT || opcode == OP_RSHIFT) return set_error(serror, SCRIPT_ERR_DISABLED_OPCODE); // Disabled opcodes. if (fExec && 0 <= opcode && opcode <= OP_PUSHDATA4) { if (fRequireMinimal && !CheckMinimalPush(vchPushValue, opcode)) { return set_error(serror, SCRIPT_ERR_MINIMALDATA); } stack.push_back(vchPushValue); } else if (fExec || (OP_IF <= opcode && opcode <= OP_ENDIF)) switch (opcode) { // // Push value // case OP_1NEGATE: case OP_1: case OP_2: case OP_3: case OP_4: case OP_5: case OP_6: case OP_7: case OP_8: case OP_9: case OP_10: case OP_11: case OP_12: case OP_13: case OP_14: case OP_15: case OP_16: { // ( -- value) CScriptNum bn((int)opcode - (int)(OP_1 - 1)); stack.push_back(bn.getvch()); // The result of these opcodes should always be the minimal way to push the data // they push, so no need for a CheckMinimalPush here. } break; // // Control // case OP_NOP: break; case OP_NOP1: case OP_NOP2: case OP_NOP3: case OP_NOP4: case OP_NOP5: case OP_NOP6: case OP_NOP7: case OP_NOP8: case OP_NOP9: case OP_NOP10: { if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS) return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_NOPS); } break; case OP_IF: case OP_NOTIF: { // <expression> if [statements] [else [statements]] endif bool fValue = false; if (fExec) { if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); valtype& vch = stacktop(-1); fValue = CastToBool(vch); if (opcode == OP_NOTIF) fValue = !fValue; popstack(stack); } vfExec.push_back(fValue); } break; case OP_ELSE: { if (vfExec.empty()) return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); vfExec.back() = !vfExec.back(); } break; case OP_ENDIF: { if (vfExec.empty()) return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); vfExec.pop_back(); } break; case OP_VERIFY: { // (true -- ) or // (false -- false) and return if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); bool fValue = CastToBool(stacktop(-1)); if (fValue) popstack(stack); else return set_error(serror, SCRIPT_ERR_VERIFY); } break; case OP_RETURN: { return set_error(serror, SCRIPT_ERR_OP_RETURN); } break; // // Stack ops // case OP_TOALTSTACK: { if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); altstack.push_back(stacktop(-1)); popstack(stack); } break; case OP_FROMALTSTACK: { if (altstack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_ALTSTACK_OPERATION); stack.push_back(altstacktop(-1)); popstack(altstack); } break; case OP_2DROP: { // (x1 x2 -- ) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); popstack(stack); popstack(stack); } break; case OP_2DUP: { // (x1 x2 -- x1 x2 x1 x2) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch1 = stacktop(-2); valtype vch2 = stacktop(-1); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_3DUP: { // (x1 x2 x3 -- x1 x2 x3 x1 x2 x3) if (stack.size() < 3) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch1 = stacktop(-3); valtype vch2 = stacktop(-2); valtype vch3 = stacktop(-1); stack.push_back(vch1); stack.push_back(vch2); stack.push_back(vch3); } break; case OP_2OVER: { // (x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2) if (stack.size() < 4) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch1 = stacktop(-4); valtype vch2 = stacktop(-3); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_2ROT: { // (x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2) if (stack.size() < 6) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch1 = stacktop(-6); valtype vch2 = stacktop(-5); stack.erase(stack.end()-6, stack.end()-4); stack.push_back(vch1); stack.push_back(vch2); } break; case OP_2SWAP: { // (x1 x2 x3 x4 -- x3 x4 x1 x2) if (stack.size() < 4) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); swap(stacktop(-4), stacktop(-2)); swap(stacktop(-3), stacktop(-1)); } break; case OP_IFDUP: { // (x - 0 | x x) if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch = stacktop(-1); if (CastToBool(vch)) stack.push_back(vch); } break; case OP_DEPTH: { // -- stacksize CScriptNum bn(stack.size()); stack.push_back(bn.getvch()); } break; case OP_DROP: { // (x -- ) if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); popstack(stack); } break; case OP_DUP: { // (x -- x x) if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch = stacktop(-1); stack.push_back(vch); } break; case OP_NIP: { // (x1 x2 -- x2) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); stack.erase(stack.end() - 2); } break; case OP_OVER: { // (x1 x2 -- x1 x2 x1) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch = stacktop(-2); stack.push_back(vch); } break; case OP_PICK: case OP_ROLL: { // (xn ... x2 x1 x0 n - xn ... x2 x1 x0 xn) // (xn ... x2 x1 x0 n - ... x2 x1 x0 xn) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); int n = CScriptNum(stacktop(-1), fRequireMinimal).getint(); popstack(stack); if (n < 0 || n >= (int)stack.size()) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch = stacktop(-n-1); if (opcode == OP_ROLL) stack.erase(stack.end()-n-1); stack.push_back(vch); } break; case OP_ROT: { // (x1 x2 x3 -- x2 x3 x1) // x2 x1 x3 after first swap // x2 x3 x1 after second swap if (stack.size() < 3) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); swap(stacktop(-3), stacktop(-2)); swap(stacktop(-2), stacktop(-1)); } break; case OP_SWAP: { // (x1 x2 -- x2 x1) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); swap(stacktop(-2), stacktop(-1)); } break; case OP_TUCK: { // (x1 x2 -- x2 x1 x2) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype vch = stacktop(-1); stack.insert(stack.end()-2, vch); } break; case OP_SIZE: { // (in -- in size) if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); CScriptNum bn(stacktop(-1).size()); stack.push_back(bn.getvch()); } break; // // Bitwise logic // case OP_EQUAL: case OP_EQUALVERIFY: //case OP_NOTEQUAL: // use OP_NUMNOTEQUAL { // (x1 x2 - bool) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype& vch1 = stacktop(-2); valtype& vch2 = stacktop(-1); bool fEqual = (vch1 == vch2); // OP_NOTEQUAL is disabled because it would be too easy to say // something like n != 1 and have some wiseguy pass in 1 with extra // zero bytes after it (numerically, 0x01 == 0x0001 == 0x000001) //if (opcode == OP_NOTEQUAL) // fEqual = !fEqual; popstack(stack); popstack(stack); stack.push_back(fEqual ? vchTrue : vchFalse); if (opcode == OP_EQUALVERIFY) { if (fEqual) popstack(stack); else return set_error(serror, SCRIPT_ERR_EQUALVERIFY); } } break; // // Numeric // case OP_1ADD: case OP_1SUB: case OP_NEGATE: case OP_ABS: case OP_NOT: case OP_0NOTEQUAL: { // (in -- out) if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); CScriptNum bn(stacktop(-1), fRequireMinimal); switch (opcode) { case OP_1ADD: bn += bnOne; break; case OP_1SUB: bn -= bnOne; break; case OP_NEGATE: bn = -bn; break; case OP_ABS: if (bn < bnZero) bn = -bn; break; case OP_NOT: bn = (bn == bnZero); break; case OP_0NOTEQUAL: bn = (bn != bnZero); break; default: assert(!"invalid opcode"); break; } popstack(stack); stack.push_back(bn.getvch()); } break; case OP_ADD: case OP_SUB: case OP_BOOLAND: case OP_BOOLOR: case OP_NUMEQUAL: case OP_NUMEQUALVERIFY: case OP_NUMNOTEQUAL: case OP_LESSTHAN: case OP_GREATERTHAN: case OP_LESSTHANOREQUAL: case OP_GREATERTHANOREQUAL: case OP_MIN: case OP_MAX: { // (x1 x2 -- out) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); CScriptNum bn1(stacktop(-2), fRequireMinimal); CScriptNum bn2(stacktop(-1), fRequireMinimal); CScriptNum bn(0); switch (opcode) { case OP_ADD: bn = bn1 + bn2; break; case OP_SUB: bn = bn1 - bn2; break; case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break; case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break; case OP_NUMEQUAL: bn = (bn1 == bn2); break; case OP_NUMEQUALVERIFY: bn = (bn1 == bn2); break; case OP_NUMNOTEQUAL: bn = (bn1 != bn2); break; case OP_LESSTHAN: bn = (bn1 < bn2); break; case OP_GREATERTHAN: bn = (bn1 > bn2); break; case OP_LESSTHANOREQUAL: bn = (bn1 <= bn2); break; case OP_GREATERTHANOREQUAL: bn = (bn1 >= bn2); break; case OP_MIN: bn = (bn1 < bn2 ? bn1 : bn2); break; case OP_MAX: bn = (bn1 > bn2 ? bn1 : bn2); break; default: assert(!"invalid opcode"); break; } popstack(stack); popstack(stack); stack.push_back(bn.getvch()); if (opcode == OP_NUMEQUALVERIFY) { if (CastToBool(stacktop(-1))) popstack(stack); else return set_error(serror, SCRIPT_ERR_NUMEQUALVERIFY); } } break; case OP_WITHIN: { // (x min max -- out) if (stack.size() < 3) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); CScriptNum bn1(stacktop(-3), fRequireMinimal); CScriptNum bn2(stacktop(-2), fRequireMinimal); CScriptNum bn3(stacktop(-1), fRequireMinimal); bool fValue = (bn2 <= bn1 && bn1 < bn3); popstack(stack); popstack(stack); popstack(stack); stack.push_back(fValue ? vchTrue : vchFalse); } break; // // Crypto // case OP_RIPEMD160: case OP_SHA1: case OP_SHA256: case OP_HASH160: case OP_HASH256: { // (in -- hash) if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype& vch = stacktop(-1); valtype vchHash((opcode == OP_RIPEMD160 || opcode == OP_SHA1 || opcode == OP_HASH160) ? 20 : 32); if (opcode == OP_RIPEMD160) CRIPEMD160().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_SHA1) CSHA1().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_SHA256) CSHA256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_HASH160) CHash160().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); else if (opcode == OP_HASH256) CHash256().Write(begin_ptr(vch), vch.size()).Finalize(begin_ptr(vchHash)); popstack(stack); stack.push_back(vchHash); } break; case OP_CODESEPARATOR: { // Hash starts after the code separator pbegincodehash = pc; } break; case OP_CHECKSIG: case OP_CHECKSIGVERIFY: { // (sig pubkey -- bool) if (stack.size() < 2) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); valtype& vchSig = stacktop(-2); valtype& vchPubKey = stacktop(-1); // Subset of script starting at the most recent codeseparator CScript scriptCode(pbegincodehash, pend); // Drop the signature, since there's no way for a signature to sign itself scriptCode.FindAndDelete(CScript(vchSig)); if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { //serror is set return false; } bool fSuccess = checker.CheckSig(vchSig, vchPubKey, scriptCode); popstack(stack); popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKSIGVERIFY) { if (fSuccess) popstack(stack); else return set_error(serror, SCRIPT_ERR_CHECKSIGVERIFY); } } break; case OP_CHECKMULTISIG: case OP_CHECKMULTISIGVERIFY: { // ([sig ...] num_of_signatures [pubkey ...] num_of_pubkeys -- bool) int i = 1; if ((int)stack.size() < i) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); int nKeysCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nKeysCount < 0 || nKeysCount > 20) return set_error(serror, SCRIPT_ERR_PUBKEY_COUNT); nOpCount += nKeysCount; if (nOpCount > 201) return set_error(serror, SCRIPT_ERR_OP_COUNT); int ikey = ++i; i += nKeysCount; if ((int)stack.size() < i) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); int nSigsCount = CScriptNum(stacktop(-i), fRequireMinimal).getint(); if (nSigsCount < 0 || nSigsCount > nKeysCount) return set_error(serror, SCRIPT_ERR_SIG_COUNT); int isig = ++i; i += nSigsCount; if ((int)stack.size() < i) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); // Subset of script starting at the most recent codeseparator CScript scriptCode(pbegincodehash, pend); // Drop the signatures, since there's no way for a signature to sign itself for (int k = 0; k < nSigsCount; k++) { valtype& vchSig = stacktop(-isig-k); scriptCode.FindAndDelete(CScript(vchSig)); } bool fSuccess = true; while (fSuccess && nSigsCount > 0) { valtype& vchSig = stacktop(-isig); valtype& vchPubKey = stacktop(-ikey); // Note how this makes the exact order of pubkey/signature evaluation // distinguishable by CHECKMULTISIG NOT if the STRICTENC flag is set. // See the script_(in)valid tests for details. if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, serror)) { // serror is set return false; } // Check signature bool fOk = checker.CheckSig(vchSig, vchPubKey, scriptCode); if (fOk) { isig++; nSigsCount--; } ikey++; nKeysCount--; // If there are more signatures left than keys left, // then too many signatures have failed. Exit early, // without checking any further signatures. if (nSigsCount > nKeysCount) fSuccess = false; } // Clean up stack of actual arguments while (i-- > 1) popstack(stack); // A bug causes CHECKMULTISIG to consume one extra argument // whose contents were not checked in any way. // // Unfortunately this is a potential source of mutability, // so optionally verify it is exactly equal to zero prior // to removing it from the stack. if (stack.size() < 1) return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION); if ((flags & SCRIPT_VERIFY_NULLDUMMY) && stacktop(-1).size()) return set_error(serror, SCRIPT_ERR_SIG_NULLDUMMY); popstack(stack); stack.push_back(fSuccess ? vchTrue : vchFalse); if (opcode == OP_CHECKMULTISIGVERIFY) { if (fSuccess) popstack(stack); else return set_error(serror, SCRIPT_ERR_CHECKMULTISIGVERIFY); } } break; default: return set_error(serror, SCRIPT_ERR_BAD_OPCODE); } // Size limits if (stack.size() + altstack.size() > 1000) return set_error(serror, SCRIPT_ERR_STACK_SIZE); } } catch (...) { return set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR); } if (!vfExec.empty()) return set_error(serror, SCRIPT_ERR_UNBALANCED_CONDITIONAL); return set_success(serror); }
WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransaction &transaction, const CCoinControl *coinControl) { qint64 total = 0; QList<SendCoinsRecipient> recipients = transaction.getRecipients(); std::vector<std::pair<CScript, int64_t> > vecSend; if(recipients.empty()) { return OK; } QSet<QString> setAddress; // Used to detect duplicates int nAddresses = 0; // Pre-check input data for validity foreach(const SendCoinsRecipient &rcp, recipients) { if (rcp.paymentRequest.IsInitialized()) { // PaymentRequest... int64_t subtotal = 0; const payments::PaymentDetails& details = rcp.paymentRequest.getDetails(); for (int i = 0; i < details.outputs_size(); i++) { const payments::Output& out = details.outputs(i); if (out.amount() <= 0) continue; subtotal += out.amount(); const unsigned char* scriptStr = (const unsigned char*)out.script().data(); CScript scriptPubKey(scriptStr, scriptStr+out.script().size()); vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, out.amount())); } if (subtotal <= 0) { return InvalidAmount; } total += subtotal; } else { // User-entered bitcoin address / amount: if(!validateAddress(rcp.address)) { return InvalidAddress; } if(rcp.amount <= 0) { return InvalidAmount; } setAddress.insert(rcp.address); ++nAddresses; CScript scriptPubKey; scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); vecSend.push_back(std::pair<CScript, int64_t>(scriptPubKey, rcp.amount)); total += rcp.amount; } } if(setAddress.size() != nAddresses) { return DuplicateAddress; } qint64 nBalance = getBalance(coinControl); if(total > nBalance) { return AmountExceedsBalance; } if((total + nTransactionFee) > nBalance) { transaction.setTransactionFee(nTransactionFee); return SendCoinsReturn(AmountWithFeeExceedsBalance); } { LOCK2(cs_main, wallet->cs_wallet); transaction.newPossibleKeyChange(wallet); int64_t nFeeRequired = 0; std::string strFailReason; CWalletTx *newTx = transaction.getTransaction(); CReserveKey *keyChange = transaction.getPossibleKeyChange(); bool fCreated = wallet->CreateTransaction(vecSend, *newTx, *keyChange, nFeeRequired, strFailReason, coinControl); transaction.setTransactionFee(nFeeRequired); if(!fCreated) { if((total + nFeeRequired) > nBalance) { return SendCoinsReturn(AmountWithFeeExceedsBalance); } emit message(tr("Send Coins"), QString::fromStdString(strFailReason), CClientUIInterface::MSG_ERROR); return TransactionCreationFailed; } } return SendCoinsReturn(OK); }
Value getworkaux(const Array& params, bool fHelp) { if (fHelp || params.size() < 1) throw runtime_error( "getworkaux <aux>\n" "getworkaux '' <data>\n" "getworkaux 'submit' <data>\n" "getworkaux '' <data> <chain-index> <branch>*\n" " get work with auxiliary data in coinbase, for multichain mining\n" "<aux> is the merkle root of the auxiliary chain block hashes, concatenated with the aux chain merkle tree size and a nonce\n" "<chain-index> is the aux chain index in the aux chain merkle tree\n" "<branch> is the optional merkle branch of the aux chain\n" "If <data> is not specified, returns formatted hash data to work on:\n" " \"midstate\" : precomputed hash state after hashing the first half of the data\n" " \"data\" : block data\n" " \"hash1\" : formatted hash buffer for second hash\n" " \"target\" : little endian hash target\n" "If <data> is specified and 'submit', tries to solve the block for this (parent) chain and returns true if it was successful." "If <data> is specified and empty first argument, returns the aux merkle root, with size and nonce." "If <data> and <chain-index> are specified, creates an auxiliary proof of work for the chain specified and returns:\n" " \"aux\" : merkle root of auxiliary chain block hashes\n" " \"auxpow\" : aux proof of work to submit to aux chain\n" ); if (vNodes.empty()) throw JSONRPCError(RPC_CLIENT_NOT_CONNECTED, "Skeincoin is not connected!"); if (IsInitialBlockDownload()) throw JSONRPCError(RPC_CLIENT_IN_INITIAL_DOWNLOAD, "Skeincoin is downloading blocks..."); static map<uint256, pair<CBlock*, unsigned int> > mapNewBlock; static vector<CBlockTemplate*> vNewBlockTemplate; static CReserveKey reservekey(pwalletMain); if (params.size() == 1) { static vector<unsigned char> vchAuxPrev; vector<unsigned char> vchAux = ParseHex(params[0].get_str()); // Update block static unsigned int nTransactionsUpdatedLast; static CBlockIndex* pindexPrev; static int64 nStart; static CBlockTemplate* pblocktemplate; if (pindexPrev != pindexBest || vchAux != vchAuxPrev || (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)) { if (pindexPrev != pindexBest) { // Deallocate old blocks since they're obsolete now mapNewBlock.clear(); BOOST_FOREACH(CBlockTemplate* pblocktemplate, vNewBlockTemplate) delete pblocktemplate; vNewBlockTemplate.clear(); } nTransactionsUpdatedLast = nTransactionsUpdated; pindexPrev = pindexBest; vchAuxPrev = vchAux; nStart = GetTime(); // Create new block pblocktemplate = CreateNewBlock(reservekey); if (!pblocktemplate) throw JSONRPCError(RPC_OUT_OF_MEMORY, "Out of memory"); vNewBlockTemplate.push_back(pblocktemplate); } CBlock* pblock = &pblocktemplate->block; // Update nTime pblock->nTime = max(pindexPrev->GetMedianTimePast()+1, GetAdjustedTime()); pblock->nNonce = 0; // Update nExtraNonce static unsigned int nExtraNonce = 0; static int64 nPrevTime = 0; IncrementExtraNonceWithAux(pblock, pindexPrev, nExtraNonce, nPrevTime, vchAux); // Save mapNewBlock[pblock->hashMerkleRoot] = make_pair(pblock, nExtraNonce); // Prebuild hash buffers char pmidstate[32]; char pdata[128]; char phash1[64]; FormatHashBuffers(pblock, pmidstate, pdata, phash1); uint256 hashTarget = CBigNum().SetCompact(pblock->nBits).getuint256(); Object result; result.push_back(Pair("midstate", HexStr(BEGIN(pmidstate), END(pmidstate)))); result.push_back(Pair("data", HexStr(BEGIN(pdata), END(pdata)))); result.push_back(Pair("hash1", HexStr(BEGIN(phash1), END(phash1)))); result.push_back(Pair("target", HexStr(BEGIN(hashTarget), END(hashTarget)))); return result; } else { if (params[0].get_str() != "submit" && params[0].get_str() != "") throw JSONRPCError(RPC_INVALID_PARAMETER, "<aux> must be the empty string or 'submit' if work is being submitted"); // Parse parameters vector<unsigned char> vchData = ParseHex(params[1].get_str()); if (vchData.size() != 128) throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter"); CBlock* pdata = (CBlock*)&vchData[0]; // Byte reverse for (int i = 0; i < 128/4; i++) ((unsigned int*)pdata)[i] = ByteReverse(((unsigned int*)pdata)[i]); // Get saved block if (!mapNewBlock.count(pdata->hashMerkleRoot)) return false; CBlock* pblock = mapNewBlock[pdata->hashMerkleRoot].first; unsigned int nExtraNonce = mapNewBlock[pdata->hashMerkleRoot].second; pblock->nTime = pdata->nTime; pblock->nNonce = pdata->nNonce; // Get the aux merkle root from the coinbase CScript script = pblock->vtx[0].vin[0].scriptSig; opcodetype opcode; CScript::const_iterator pc = script.begin(); script.GetOp(pc, opcode); script.GetOp(pc, opcode); script.GetOp(pc, opcode); if (opcode != OP_2) throw JSONRPCError(RPC_MISC_ERROR, "invalid aux pow script"); vector<unsigned char> vchAux; script.GetOp(pc, opcode, vchAux); RemoveMergedMiningHeader(vchAux); pblock->vtx[0].vin[0].scriptSig = MakeCoinbaseWithAux(pblock->nBits, nExtraNonce, vchAux); pblock->hashMerkleRoot = pblock->BuildMerkleTree(); if (params.size() > 2) { // Requested aux proof of work int nChainIndex = params[2].get_int(); CAuxPow pow(pblock->vtx[0]); for (int i = 3 ; (unsigned int)i < params.size() ; i++) { uint256 nHash; nHash.SetHex(params[i].get_str()); pow.vChainMerkleBranch.push_back(nHash); } pow.SetMerkleBranch(pblock); pow.nChainIndex = nChainIndex; pow.parentBlock = *pblock; CDataStream ss(SER_GETHASH|SER_BLOCKHEADERONLY, PROTOCOL_VERSION); ss << pow; Object result; result.push_back(Pair("auxpow", HexStr(ss.begin(), ss.end()))); return result; } else { if (params[0].get_str() == "submit") { return CheckWork(pblock, *pwalletMain, reservekey); } else { Object result; result.push_back(Pair("aux", HexStr(vchAux.begin(), vchAux.end()))); result.push_back(Pair("hash", pblock->GetPoWHash().GetHex())); return result; } } } }
bool CWebPageDef::WebPageUpdate( bool fNow, LPCTSTR pszDstName, CTextConsole * pSrc ) { ADDTOCALLSTACK("CWebPageDef::WebPageUpdate"); // Generate the status web pages. // Read in the Base status page "*STATUSBASE.HTM" // Filter the XML type tags. // Output the status page "*.HTM" // Server name // Server email // Number of clients, items, NPC's if ( ! fNow ) { if ( m_iUpdatePeriod <= 0 ) return false; if ( CServTime::GetCurrentTime() < m_timeNextUpdate ) return true; // should stilll be valid } ASSERT(pSrc); m_timeNextUpdate = CServTime::GetCurrentTime() + m_iUpdatePeriod; if ( pszDstName == NULL ) { pszDstName = m_sDstFilePath; } if ( m_type != WEBPAGE_TEMPLATE || *pszDstName == '\0' || m_sSrcFilePath.IsEmpty()) return false; CScript FileRead; if ( ! FileRead.Open( m_sSrcFilePath, OF_READ|OF_TEXT|OF_DEFAULTMODE )) { return false; } CScriptFileContext context( &FileRead ); // set this as the context. CFileConsole FileOut; if ( ! FileOut.m_FileOut.Open( pszDstName, OF_WRITE|OF_TEXT )) { DEBUG_ERR(( "Can't open web page output '%s'\n", static_cast<LPCTSTR>(pszDstName) )); return false; } bool fScriptMode = false; while ( FileRead.ReadTextLine( false )) { TCHAR *pszTmp = Str_GetTemp(); strcpy( pszTmp, FileRead.GetKey()); TCHAR * pszHead = strstr( pszTmp, "<script language=\"Sphere\">" ); if ( pszHead != NULL ) { // Deal with the stuff preceding the scripts. *pszHead = '\0'; pszHead += 26; ParseText( pszTmp, pSrc, 1 ); FileOut.SysMessage( pszTmp ); fScriptMode = true; } else { pszHead = pszTmp; } // Look for the end of </script> if ( fScriptMode ) { GETNONWHITESPACE(pszHead); TCHAR * pszFormat = pszHead; pszHead = strstr( pszFormat, "</script>" ); if ( pszHead != NULL ) { *pszHead = '\0'; pszHead += 9; fScriptMode = false; } if ( pszFormat[0] != '\0' ) { // Allow if/then logic ??? OnTriggerRun( CScript &s, TRIGRUN_SINGLE_EXEC, &FileOut ) CScript script( pszFormat ); if ( ! r_Verb( script, &FileOut )) { DEBUG_ERR(( "Web page source format error '%s'\n", static_cast<LPCTSTR>(pszTmp) )); continue; } } if ( fScriptMode ) continue; } // Look for stuff we can displace here. %STUFF% ParseText( pszHead, pSrc, 1 ); FileOut.SysMessage( pszHead ); } return( true ); }
bool CAuxPow::Check(uint256 hashAuxBlock, int nChainID) { if (nIndex != 0) return error("AuxPow is not a generate"); if (!fTestNet && !fCakeNet && parentBlockHeader.GetChainID() == nChainID) return error("Aux POW parent has our chain ID"); if (vChainMerkleBranch.size() > 30) return error("Aux POW chain merkle branch too long"); // Check that the chain merkle root is in the coinbase uint256 nRootHash = CBlock::CheckMerkleBranch(hashAuxBlock, vChainMerkleBranch, nChainIndex); vector<unsigned char> vchRootHash(nRootHash.begin(), nRootHash.end()); std::reverse(vchRootHash.begin(), vchRootHash.end()); // correct endian // Check that we are in the parent block merkle tree if (CBlock::CheckMerkleBranch(GetAuxHash(), vMerkleBranch, nIndex) != parentBlockHeader.hashMerkleRoot) return error("Aux POW merkle root incorrect"); const CScript script = vin[0].scriptSig; // Check that the same work is not submitted twice to our chain. // CScript::const_iterator pcHead = std::search(script.begin(), script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader)); CScript::const_iterator pc = std::search(script.begin(), script.end(), vchRootHash.begin(), vchRootHash.end()); if (pcHead == script.end()) return error("MergedMiningHeader missing from parent coinbase"); if (pc == script.end()) return error("Aux POW missing chain merkle root in parent coinbase"); if (pcHead != script.end()) { // Enforce only one chain merkle root by checking that a single instance of the merged // mining header exists just before. if (script.end() != std::search(pcHead + 1, script.end(), UBEGIN(pchMergedMiningHeader), UEND(pchMergedMiningHeader))) return error("Multiple merged mining headers in coinbase"); if (pcHead + sizeof(pchMergedMiningHeader) != pc) return error("Merged mining header is not just before chain merkle root"); } else { // For backward compatibility. // Enforce only one chain merkle root by checking that it starts early in the coinbase. // 8-12 bytes are enough to encode extraNonce and nBits. if (pc - script.begin() > 20) return error("Aux POW chain merkle root must start in the first 20 bytes of the parent coinbase"); } // Ensure we are at a deterministic point in the merkle leaves by hashing // a nonce and our chain ID and comparing to the index. pc += vchRootHash.size(); if (script.end() - pc < 8) return error("Aux POW missing chain merkle tree size and nonce in parent coinbase"); int nSize; memcpy(&nSize, &pc[0], 4); if (nSize != (1 << vChainMerkleBranch.size())) return error("Aux POW merkle branch size does not match parent coinbase"); int nNonce; memcpy(&nNonce, &pc[4], 4); // Choose a pseudo-random slot in the chain merkle tree // but have it be fixed for a size/nonce/chain combination. // // This prevents the same work from being used twice for the // same chain while reducing the chance that two chains clash // for the same slot. unsigned int rand = nNonce; rand = rand * 1103515245 + 12345; rand += nChainID; rand = rand * 1103515245 + 12345; if (nChainIndex != (rand % nSize)) return error("Aux POW wrong index"); return true; }
/** * Return public keys or hashes from scriptPubKey, for 'standard' transaction types. */ bool Solver(const CScript& scriptPubKeyIn, 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)); // Syscoin 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)); } // SYSCOIN check to see if this is a syscoin service transaction, if so get the scriptPubKey by extracting service specific script information CScript scriptPubKey; CScript scriptPubKeyOut; if (RemoveSyscoinScript(scriptPubKeyIn, scriptPubKeyOut)) scriptPubKey = scriptPubKeyOut; else scriptPubKey = scriptPubKeyIn; vSolutionsRet.clear(); // 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 (scriptPubKey.IsPayToScriptHash()) { typeRet = TX_SCRIPTHASH; std::vector<unsigned char> hashBytes(scriptPubKey.begin()+2, scriptPubKey.begin()+22); vSolutionsRet.push_back(hashBytes); return true; } // 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 const CScript& script1 = scriptPubKey; BOOST_FOREACH(const PAIRTYPE(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; }
WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipient> &recipients, const CCoinControl *coinControl) { qint64 total = 0; QSet<QString> setAddress; QString hex; if(recipients.empty()) { return OK; } // Pre-check input data for validity foreach(const SendCoinsRecipient &rcp, recipients) { if(!validateAddress(rcp.address)) { return InvalidAddress; } setAddress.insert(rcp.address); if(rcp.amount <= 0) { return InvalidAmount; } total += rcp.amount; } if(recipients.size() > setAddress.size()) { return DuplicateAddress; } int64_t nBalance = 0; std::vector<COutput> vCoins; wallet->AvailableCoins(vCoins, true, coinControl); BOOST_FOREACH(const COutput& out, vCoins) nBalance += out.tx->vout[out.i].nValue; if(total > nBalance) { return AmountExceedsBalance; } if((total + nTransactionFee) > nBalance) { return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); } std::string txid = ""; std::string messages = ""; std::string hashBoinc = ""; { LOCK2(cs_main, wallet->cs_wallet); // Sendmany std::vector<std::pair<CScript, int64_t> > vecSend; bool coinTracking = false; foreach(const SendCoinsRecipient &rcp, recipients) { CScript scriptPubKey; scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); vecSend.push_back(make_pair(scriptPubKey, rcp.amount)); if (rcp.CoinTracking) coinTracking=true; messages += "<MESSAGE>" + AdvancedCrypt(FromQStringW(rcp.Message)) + "</MESSAGE>"; } CWalletTx wtx; CReserveKey keyChange(wallet); int64_t nFeeRequired = 0; if (coinTracking) { printf("Creating tracked tx : old hashboinc %s",wtx.hashBoinc.c_str()); wtx.hashBoinc = "<TRACK>" + wtx.GetHash().ToString() + "</TRACK>"; //Run time code execution feature - 12-7-2014 std::string q = "\""; std::string code = "MsgBox(" + q + "Hello!" + q + ",MsgBoxStyle.Critical," + q + "Message Title" + q + ")\r\n"; wtx.hashBoinc += "<CODE>" + code + "</CODE>"; } if (!msAttachmentGuid.empty()) { printf("Adding attachment to tx %s",wtx.hashBoinc.c_str()); wtx.hashBoinc += "<ATTACHMENT><TXID>" + wtx.GetHash().ToString() + "</TXID><ATTACHMENTGUID>" + msAttachmentGuid + "</ATTACHMENTGUID></ATTACHMENT>"; } wtx.hashBoinc += messages; bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, coinControl); if(!fCreated) { if((total + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future { return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired); } return TransactionCreationFailed; } if (coinTracking) { printf("Tracking hashBoinc %s",wtx.hashBoinc.c_str()); } std::string samt = FormatMoney(wtx.vout[0].nValue); double dblAmt = dblFromAmount(wtx.vout[0].nValue); if(!uiInterface.ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString())) { return Aborted; } if(!wallet->CommitTransaction(wtx, keyChange)) { return TransactionCommitFailed; } hex = QString::fromStdString(wtx.GetHash().GetHex()); txid = wtx.GetHash().GetHex(); hashBoinc = wtx.hashBoinc; }
WalletModel::SendCoinsReturn WalletModel::sendCoins(const QList<SendCoinsRecipient> &recipients, const CCoinControl *coinControl) { qint64 total = 0; QSet<QString> setAddress; QString hex; if(recipients.empty()) { return OK; } if(isAnonymizeOnlyUnlocked()) { return AnonymizeOnlyUnlocked; } // Pre-check input data for validity foreach(const SendCoinsRecipient &rcp, recipients) { if(!validateAddress(rcp.address)) { return InvalidAddress; } setAddress.insert(rcp.address); if(rcp.amount <= 0) { return InvalidAmount; } total += rcp.amount; } if(recipients.size() > setAddress.size()) { return DuplicateAddress; } int64_t nBalance = 0; std::vector<COutput> vCoins; wallet->AvailableCoins(vCoins, true, coinControl); BOOST_FOREACH(const COutput& out, vCoins) nBalance += out.tx->vout[out.i].nValue; if(total > nBalance) { return AmountExceedsBalance; } if((total + nTransactionFee) > nBalance) { return SendCoinsReturn(AmountWithFeeExceedsBalance, nTransactionFee); } { LOCK2(cs_main, wallet->cs_wallet); // Sendmany std::vector<std::pair<CScript, int64_t> > vecSend; foreach(const SendCoinsRecipient &rcp, recipients) { CScript scriptPubKey; scriptPubKey.SetDestination(CBitcoinAddress(rcp.address.toStdString()).Get()); vecSend.push_back(make_pair(scriptPubKey, rcp.amount)); } CWalletTx wtx; CReserveKey keyChange(wallet); int64_t nFeeRequired = 0; std::string strFailReason; bool fCreated = wallet->CreateTransaction(vecSend, wtx, keyChange, nFeeRequired, strFailReason, coinControl); if(!fCreated) { if((total + nFeeRequired) > nBalance) // FIXME: could cause collisions in the future { return SendCoinsReturn(AmountWithFeeExceedsBalance, nFeeRequired); } return TransactionCreationFailed; } if(!uiInterface.ThreadSafeAskFee(nFeeRequired, tr("Sending...").toStdString())) { return Aborted; } if(!wallet->CommitTransaction(wtx, keyChange)) { return TransactionCommitFailed; } hex = QString::fromStdString(wtx.GetHash().GetHex()); }
UniValue validateaddress(const JSONRPCRequest& request) { if (request.fHelp || request.params.size() != 1) throw std::runtime_error( "validateaddress \"address\"\n" "\nReturn information about the given knightcoin address.\n" "\nArguments:\n" "1. \"address\" (string, required) The knightcoin address to validate\n" "\nResult:\n" "{\n" " \"isvalid\" : true|false, (boolean) If the address is valid or not. If not, this is the only property returned.\n" " \"address\" : \"address\", (string) The knightcoin address validated\n" " \"scriptPubKey\" : \"hex\", (string) The hex encoded scriptPubKey generated by the address\n" " \"ismine\" : true|false, (boolean) If the address is yours or not\n" " \"iswatchonly\" : true|false, (boolean) If the address is watchonly\n" " \"isscript\" : true|false, (boolean) If the key is a script\n" " \"script\" : \"type\" (string, optional) The output script type. Possible types: nonstandard, pubkey, pubkeyhash, scripthash, multisig, nulldata, witness_v0_keyhash, witness_v0_scripthash\n" " \"hex\" : \"hex\", (string, optional) The redeemscript for the p2sh address\n" " \"addresses\" (string, optional) Array of addresses associated with the known redeemscript\n" " [\n" " \"address\"\n" " ,...\n" " ]\n" " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output\n" " \"pubkey\" : \"publickeyhex\", (string) The hex value of the raw public key\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" " \"account\" : \"account\" (string) DEPRECATED. The account associated with the address, \"\" is the default account\n" " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" " \"hdmasterkeyid\" : \"<hash160>\" (string, optional) The Hash160 of the HD master pubkey\n" "}\n" "\nExamples:\n" + HelpExampleCli("validateaddress", "\"LER4HnAEFwYHbmGxCfP2po1nPrUeiK8KM2\"") + HelpExampleRpc("validateaddress", "\"LER4HnAEFwYHbmGxCfP2po1nPrUeiK8KM2\"") ); #ifdef ENABLE_WALLET CWallet * const pwallet = GetWalletForJSONRPCRequest(request); LOCK2(cs_main, pwallet ? &pwallet->cs_wallet : nullptr); #else LOCK(cs_main); #endif CBitcoinAddress address(request.params[0].get_str()); bool isValid = address.IsValid(); UniValue ret(UniValue::VOBJ); ret.push_back(Pair("isvalid", isValid)); if (isValid) { CTxDestination dest = address.Get(); std::string currentAddress = address.ToString(); ret.push_back(Pair("address", currentAddress)); CScript scriptPubKey = GetScriptForDestination(dest); ret.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end()))); #ifdef ENABLE_WALLET isminetype mine = pwallet ? IsMine(*pwallet, dest) : ISMINE_NO; ret.push_back(Pair("ismine", bool(mine & ISMINE_SPENDABLE))); ret.push_back(Pair("iswatchonly", bool(mine & ISMINE_WATCH_ONLY))); UniValue detail = boost::apply_visitor(DescribeAddressVisitor(pwallet), dest); ret.pushKVs(detail); if (pwallet && pwallet->mapAddressBook.count(dest)) { ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); } CKeyID keyID; if (pwallet) { const auto& meta = pwallet->mapKeyMetadata; auto it = address.GetKeyID(keyID) ? meta.find(keyID) : meta.end(); if (it == meta.end()) { it = meta.find(CScriptID(scriptPubKey)); } if (it != meta.end()) { ret.push_back(Pair("timestamp", it->second.nCreateTime)); if (!it->second.hdKeypath.empty()) { ret.push_back(Pair("hdkeypath", it->second.hdKeypath)); ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex())); } } } #endif } return ret; }
bool CBasicKeyStore::AddCScript(const CScript& redeemScript) { LOCK(cs_KeyStore); mapScripts[redeemScript.GetID()] = redeemScript; return true; }
Value createrawtransaction(const Array& params, bool fHelp) { if (fHelp || (params.size() < 2 || params.size() > 3)) throw runtime_error( "createrawtransaction [{\"txid\":txid,\"vout\":n},...] {address:amount,...} [tx-comment]\n" "Create a transaction spending given inputs\n" "(array of objects containing transaction id and output number),\n" "sending to given address(es).\n" "Returns hex-encoded raw transaction.\n" "Note that the transaction's inputs are not signed, and\n" "it is not stored in the wallet or transmitted to the network."); RPCTypeCheck(params, list_of(array_type)(obj_type)); Array inputs = params[0].get_array(); Object sendTo = params[1].get_obj(); CTransaction rawTx; if (params.size() == 3) { std::string txcomment = params[2].get_str(); if (txcomment.length() > MAX_TX_COMMENT_LEN_V2) { txcomment.resize(MAX_TX_COMMENT_LEN_V2); } rawTx.strTxComment = txcomment; } BOOST_FOREACH(Value& input, inputs) { const Object& o = input.get_obj(); const Value& txid_v = find_value(o, "txid"); if (txid_v.type() != str_type) throw JSONRPCError(-8, "Invalid parameter, missing txid key"); string txid = txid_v.get_str(); if (!IsHex(txid)) throw JSONRPCError(-8, "Invalid parameter, expected hex txid"); const Value& vout_v = find_value(o, "vout"); if (vout_v.type() != int_type) throw JSONRPCError(-8, "Invalid parameter, missing vout key"); int nOutput = vout_v.get_int(); if (nOutput < 0) throw JSONRPCError(-8, "Invalid parameter, vout must be positive"); CTxIn in(COutPoint(uint256(txid), nOutput)); rawTx.vin.push_back(in); } set<CBitcoinAddress> setAddress; BOOST_FOREACH(const Pair& s, sendTo) { CBitcoinAddress address(s.name_); if (!address.IsValid()) throw JSONRPCError(-5, string("Invalid FooCoin address:")+s.name_); if (setAddress.count(address)) throw JSONRPCError(-8, string("Invalid parameter, duplicated address: ")+s.name_); setAddress.insert(address); CScript scriptPubKey; scriptPubKey.SetDestination(address.Get()); int64 nAmount = AmountFromValue(s.value_); CTxOut out(nAmount, scriptPubKey); rawTx.vout.push_back(out); }
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
bool MultisigDialog::createRedeemScript(int m, vector<string> vKeys, CScript& redeemRet, string& errorRet) { try{ int n = vKeys.size(); //gather pub keys if (n < 1) throw runtime_error("a Multisignature address must require at least one key to redeem"); if (n < m) throw runtime_error( strprintf("not enough keys supplied " "(got %d keys, but need at least %d to redeem)", m, n)); if (n > 15) throw runtime_error("Number of addresses involved in the Multisignature address creation > 15\nReduce the number"); vector<CPubKey> pubkeys; pubkeys.resize(n); int i = 0; for(vector<string>::iterator it = vKeys.begin(); it != vKeys.end(); ++it) { string keyString = *it; #ifdef ENABLE_WALLET // Case 1: PIVX address and we have full public key: CBitcoinAddress address(keyString); if (pwalletMain && address.IsValid()) { CKeyID keyID; if (!address.GetKeyID(keyID)) { throw runtime_error( strprintf("%s does not refer to a key", keyString)); } CPubKey vchPubKey; if (!pwalletMain->GetPubKey(keyID, vchPubKey)) throw runtime_error( strprintf("no full public key for address %s", keyString)); if (!vchPubKey.IsFullyValid()){ string sKey = keyString.empty()?"(empty)":keyString; throw runtime_error(" Invalid public key: " + sKey ); } pubkeys[i++] = vchPubKey; } //case 2: hex pub key else #endif if (IsHex(keyString)) { CPubKey vchPubKey(ParseHex(keyString)); if (!vchPubKey.IsFullyValid()){ throw runtime_error(" Invalid public key: " + keyString); } pubkeys[i++] = vchPubKey; } else { throw runtime_error(" Invalid public key: " + keyString); } } //populate redeem script //OP_N for required signatures redeemRet << redeemRet.EncodeOP_N(m); //public keys for(CPubKey& key : pubkeys){ vector<unsigned char> vKey= ToByteVector(key); redeemRet << vKey; } //OP_N for total pubkeys redeemRet << redeemRet.EncodeOP_N(pubkeys.size()); redeemRet << OP_CHECKMULTISIG; return true; }catch(const runtime_error& e){ errorRet = string(e.what()); return false; } }