mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-02-05 03:14:16 +00:00
implement CScript => string extraction, check username constraits, improve username hash
This commit is contained in:
parent
623b80c061
commit
d9fdca340c
@ -176,10 +176,10 @@ Value stop(const Array& params, bool fHelp)
|
||||
if (fHelp || params.size() > 1)
|
||||
throw runtime_error(
|
||||
"stop\n"
|
||||
"Stop Bitcoin server.");
|
||||
"Stop Twister server.");
|
||||
// Shutdown will take long enough that the response should get back
|
||||
StartShutdown();
|
||||
return "Bitcoin server stopping";
|
||||
return "Twister server stopping";
|
||||
}
|
||||
|
||||
|
||||
|
@ -80,7 +80,12 @@ uint256 CTransaction::GetHash() const
|
||||
|
||||
uint256 CTransaction::GetUsernameHash() const
|
||||
{
|
||||
return SerializeHash(userName);
|
||||
if(userName.IsSmallString()) {
|
||||
return SerializeHash(userName.ExtractSmallString());
|
||||
}
|
||||
// [MF] TODO: remove this assert later, it will fail for spammessage.
|
||||
assert(!"username not small string");
|
||||
return uint256();
|
||||
}
|
||||
|
||||
|
||||
|
45
src/main.cpp
45
src/main.cpp
@ -408,7 +408,9 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
||||
CBlock blockTmp;
|
||||
|
||||
if (pblock == NULL) {
|
||||
CCoins coins;
|
||||
/* [MF] FIXME: Use GetTransaction to obtain block? */
|
||||
/*
|
||||
CCoins coins;
|
||||
if (pcoinsTip->GetCoins(GetUsernameHash(), coins)) {
|
||||
CBlockIndex *pindex = FindBlockByHeight(coins.nHeight);
|
||||
if (pindex) {
|
||||
@ -417,6 +419,8 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
||||
pblock = &blockTmp;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (pblock) {
|
||||
@ -452,7 +456,26 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
||||
|
||||
|
||||
|
||||
|
||||
bool CheckUsername(const std::string &userName, CValidationState &state)
|
||||
{
|
||||
if (!userName.size() || userName.size() > 16 )
|
||||
return state.DoS(10, error("CheckUsername() : username size out of limits"));
|
||||
BOOST_FOREACH(char c, userName) {
|
||||
if( isalpha(c) ) {
|
||||
if( !islower(c) )
|
||||
return state.DoS(10, error("CheckUsername() : username must be lowercase"));
|
||||
} else if( isdigit(c) ) {
|
||||
// digit ok
|
||||
} else if( isspace(c) ) {
|
||||
return state.DoS(10, error("CheckUsername() : username spaces not allowed"));
|
||||
} else if( c == '_' ) {
|
||||
// underscore ok
|
||||
} else {
|
||||
return state.DoS(10, error("CheckUsername() : invalid username character"));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// [MF] check tx consistency and pow, not duplicated id.
|
||||
@ -467,10 +490,12 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state)
|
||||
} else {
|
||||
if (tx.userName.empty())
|
||||
return state.DoS(10, error("CheckTransaction() : username empty"));
|
||||
if (tx.userName.size() > MAX_USERNAME_SIZE)
|
||||
return state.DoS(100, error("CheckTransaction() : username too big"));
|
||||
if (tx.pubKey.empty())
|
||||
return state.DoS(10, error("CheckTransaction() : pubKey empty"));
|
||||
if (!tx.userName.IsSmallString())
|
||||
return state.DoS(10, error("CheckTransaction() : username not smallstring"));
|
||||
if (!CheckUsername( tx.userName.ExtractSmallString(), state ))
|
||||
return state.DoS(10, error("CheckTransaction() : username check failed"));
|
||||
}
|
||||
// Size limits
|
||||
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
|
||||
@ -574,7 +599,7 @@ bool CTxMemPool::addUnchecked(const uint256& userhash, CTransaction &tx)
|
||||
bool CTxMemPool::remove(const CTransaction &tx, bool fRecursive)
|
||||
{
|
||||
// Remove transaction from memory pool
|
||||
{
|
||||
if( !tx.IsSpamMessage() ){
|
||||
LOCK(cs);
|
||||
uint256 hash = tx.GetUsernameHash();
|
||||
if (mapTx.count(hash))
|
||||
@ -1095,7 +1120,7 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
||||
}
|
||||
|
||||
// Do not allow blocks that contain transactions which 'overwrite' older transactions,
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++) {
|
||||
for (unsigned int i = 1; i < block.vtx.size(); i++) {
|
||||
if( pblocktree->HaveTxIndex(block.vtx[i].GetUsernameHash()) )
|
||||
return state.DoS(100, error("ConnectBlock() : tried to overwrite transaction"));
|
||||
|
||||
@ -1110,16 +1135,16 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
||||
int64 nStart = GetTimeMicros();
|
||||
CDiskTxPos pos(pindex->GetBlockPos(), GetSizeOfCompactSize(block.vtx.size()));
|
||||
std::vector<std::pair<uint256, CDiskTxPos> > vPos;
|
||||
vPos.reserve(block.vtx.size());
|
||||
vPos.reserve(block.vtx.size()-1);
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
||||
{
|
||||
const CTransaction &tx = block.vtx[i];
|
||||
|
||||
CTxUndo txundo;
|
||||
if (!tx.IsSpamMessage())
|
||||
if (!tx.IsSpamMessage()) {
|
||||
blockundo.vtxundo.push_back(txundo);
|
||||
|
||||
vPos.push_back(std::make_pair(tx.GetUsernameHash(), pos));
|
||||
vPos.push_back(std::make_pair(tx.GetUsernameHash(), pos));
|
||||
}
|
||||
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
|
||||
}
|
||||
int64 nTime = GetTimeMicros() - nStart;
|
||||
|
@ -270,6 +270,8 @@ inline bool AllowFree(double dPriority)
|
||||
return dPriority > COIN * 144 / 250;
|
||||
}
|
||||
|
||||
bool CheckUsername(const std::string &userName, CValidationState &state);
|
||||
|
||||
// Context-independent validity checks
|
||||
bool CheckTransaction(const CTransaction& tx, CValidationState& state);
|
||||
|
||||
|
@ -55,9 +55,22 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||
result.push_back(Pair("version", block.nVersion));
|
||||
result.push_back(Pair("merkleroot", block.hashMerkleRoot.GetHex()));
|
||||
Array txs;
|
||||
BOOST_FOREACH(const CTransaction&tx, block.vtx)
|
||||
Array txuserhashes;
|
||||
Array usernames;
|
||||
std::string spamMessage;
|
||||
BOOST_FOREACH(const CTransaction&tx, block.vtx) {
|
||||
txs.push_back(tx.GetHash().GetHex());
|
||||
if( tx.IsSpamMessage() ) {
|
||||
spamMessage = tx.message.ExtractPushDataString(0);
|
||||
} else {
|
||||
txuserhashes.push_back(tx.GetUsernameHash().GetHex());
|
||||
usernames.push_back(tx.userName.ExtractSmallString());
|
||||
}
|
||||
}
|
||||
result.push_back(Pair("tx", txs));
|
||||
result.push_back(Pair("spamMessage", spamMessage));
|
||||
result.push_back(Pair("userhashes", txuserhashes));
|
||||
result.push_back(Pair("usernames", usernames));
|
||||
result.push_back(Pair("time", (boost::int64_t)block.GetBlockTime()));
|
||||
result.push_back(Pair("nonce", (boost::uint64_t)block.nNonce));
|
||||
result.push_back(Pair("bits", HexBits(block.nBits)));
|
||||
|
@ -1304,7 +1304,7 @@ Value encryptwallet(const Array& params, bool fHelp)
|
||||
// slack space in .dat files; that is bad if the old data is
|
||||
// unencrypted private keys. So:
|
||||
StartShutdown();
|
||||
return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
|
||||
return "wallet encrypted; Twister server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.";
|
||||
}
|
||||
|
||||
class DescribeAddressVisitor : public boost::static_visitor<Object>
|
||||
|
@ -1777,6 +1777,16 @@ bool CScript::IsPayToScriptHash() const
|
||||
this->at(22) == OP_EQUAL);
|
||||
}
|
||||
|
||||
bool CScript::IsSmallString() const
|
||||
{
|
||||
if( !size() || this->at(0) >= OP_PUSHDATA1 )
|
||||
return false;
|
||||
unsigned int opSize = this->at(0);
|
||||
if( this->size() != opSize + 1 )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
class CScriptVisitor : public boost::static_visitor<bool>
|
||||
{
|
||||
private:
|
||||
|
39
src/script.h
39
src/script.h
@ -533,6 +533,8 @@ public:
|
||||
|
||||
bool IsPayToScriptHash() const;
|
||||
|
||||
bool IsSmallString() const;
|
||||
|
||||
// Called by IsStandardTx
|
||||
bool IsPushOnly() const
|
||||
{
|
||||
@ -548,6 +550,43 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExtractPushData( std::vector< std::vector<unsigned char> > &vData) const
|
||||
{
|
||||
vData.clear();
|
||||
const_iterator pc = begin();
|
||||
while (pc < end())
|
||||
{
|
||||
opcodetype opcode;
|
||||
std::vector<unsigned char> vch;
|
||||
if (!GetOp(pc, opcode, vch))
|
||||
return false;
|
||||
if (opcode > OP_16)
|
||||
return false;
|
||||
vData.push_back(vch);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// only for username
|
||||
std::string ExtractSmallString() const
|
||||
{
|
||||
if( !IsSmallString() )
|
||||
return std::string();
|
||||
|
||||
unsigned int opSize = this->at(0);
|
||||
return std::string((const char*)&(this[1]), opSize);
|
||||
}
|
||||
|
||||
std::string ExtractPushDataString(int n) const
|
||||
{
|
||||
std::vector< std::vector<unsigned char> > vData;
|
||||
if( ExtractPushData(vData) && vData.size() >= n+1 ) {
|
||||
std::string str((const char*)vData[n].data(), vData[n].size());
|
||||
return str;
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
void SetDestination(const CTxDestination& address);
|
||||
void SetMultisig(int nRequired, const std::vector<CPubKey>& keys);
|
||||
|
Loading…
x
Reference in New Issue
Block a user