Skip to content

Commit

Permalink
Merge pull request #63 from dexX7/oc-0.10-pr-13-encoding-overhaul
Browse files Browse the repository at this point in the history
Encoding and transaction creation overhaul and tests
  • Loading branch information
zathras-crypto committed Apr 17, 2015
2 parents ecb57e1 + fd6cd48 commit c1de71c
Show file tree
Hide file tree
Showing 8 changed files with 543 additions and 68 deletions.
2 changes: 2 additions & 0 deletions src/Makefile.test.include
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ endif

# Omni Core extensions
OMNICORE_TESTS = \
test/mastercore_create_payload_tests.cpp \
test/mastercore_encoding_c_tests.cpp \
test/mastercore_obfuscation_tests.cpp \
test/mastercore_rounduint64_tests.cpp \
test/mastercore_script_dust_tests.cpp \
Expand Down
33 changes: 20 additions & 13 deletions src/mastercore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ using namespace mastercore;
// comment out MY_HACK & others here - used for Unit Testing only !
// #define MY_HACK

string exodus_address = "1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P";
static string exodus_address = "1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P";
static const string exodus_testnet = "mpexoDuSkGGqvqrkrjiFng38QPkJQVFyqv";
static const string getmoney_testnet = "moneyqMan7uh8FqdCA2BV5yZ8qVrc9ikLP";

Expand All @@ -109,7 +109,12 @@ uint64_t global_balance_reserved_maineco[100000];
uint64_t global_balance_money_testeco[100000];
uint64_t global_balance_reserved_testeco[100000];

bool autoCommit = true; // whether to automatically commit created transactions, override with --autocommit=false
/**
* Used to indicate, whether to automatically commit created transactions.
*
* Can be set with configuration "-autocommit" or RPC "setautocommit_OMNI".
*/
bool autoCommit = true;

string global_alert_message;

Expand Down Expand Up @@ -3770,18 +3775,20 @@ int mastercore_handler_disc_end(int nBlockNow, CBlockIndex const * pBlockIndex)
return 0;
}

const std::string ExodusAddress()
/**
* Returns the Exodus address.
*
* Main network:
* 1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P
*
* Test network:
* mpexoDuSkGGqvqrkrjiFng38QPkJQVFyqv
*
* @return The Exodus address
*/
const CBitcoinAddress ExodusAddress()
{
return string(exodus_address);
}

const std::string NotificationAddress()
{
static const string addr = "1MpNote1jsHkbQLwEmgoMr29EoUC1nyxxV";

if (isNonMainNet()) {}; // TODO pick a notification address for TestNet

return addr;
return CBitcoinAddress(exodus_address);
}

// the 31-byte packet & the packet #
Expand Down
11 changes: 7 additions & 4 deletions src/mastercore.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#ifndef _MASTERCOIN
#define _MASTERCOIN 1

class CBitcoinAddress;
class CBlockIndex;
class CTransaction;

Expand Down Expand Up @@ -211,12 +212,16 @@ std::string FormatMP(unsigned int, int64_t n, bool fSign = false);
uint256 send_MP(const string &FromAddress, const string &ToAddress, const string &RedeemAddress, unsigned int PropertyID, uint64_t Amount);
int64_t feeCheck(const string &address);

const std::string ExodusAddress();
/** Returns the Exodus address. */
const CBitcoinAddress ExodusAddress();

/** Used to indicate, whether to automatically commit created transactions. */
extern bool autoCommit;

extern int msc_debug_ui;

extern CCriticalSection cs_tally;
extern bool autoCommit;

extern const int msc_debug_dex;

enum TallyType { BALANCE = 0, SELLOFFER_RESERVE = 1, ACCEPT_RESERVE = 2, PENDING = 3, METADEX_RESERVE = 4, TALLY_TYPE_COUNT };
Expand Down Expand Up @@ -519,8 +524,6 @@ extern uint64_t global_balance_reserved_maineco[100000];
extern uint64_t global_balance_money_testeco[100000];
extern uint64_t global_balance_reserved_testeco[100000];

extern std::string exodus_address;

int mastercore_init(void);

int64_t getMPbalance(const string &Address, unsigned int property, TallyType ttype);
Expand Down
5 changes: 3 additions & 2 deletions src/mastercore_sp.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class CBlockIndex;

#include "base58.h"
#include "uint256.h"
#include "utiltime.h"

Expand Down Expand Up @@ -302,15 +303,15 @@ class CMPSPInfo
openDB();

// special cases for constant SPs MSC and TMSC
implied_msc.issuer = ExodusAddress();
implied_msc.issuer = ExodusAddress().ToString();
implied_msc.prop_type = MSC_PROPERTY_TYPE_DIVISIBLE;
implied_msc.num_tokens = 700000;
implied_msc.category = "N/A";
implied_msc.subcategory = "N/A";
implied_msc.name = "MasterCoin";
implied_msc.url = "www.mastercoin.org";
implied_msc.data = "***data***";
implied_tmsc.issuer = ExodusAddress();
implied_tmsc.issuer = ExodusAddress().ToString();
implied_tmsc.prop_type = MSC_PROPERTY_TYPE_DIVISIBLE;
implied_tmsc.num_tokens = 700000;
implied_tmsc.category = "N/A";
Expand Down
119 changes: 74 additions & 45 deletions src/omnicore_encoding.cpp
Original file line number Diff line number Diff line change
@@ -1,77 +1,106 @@
// This file serves to seperate encoding of data outputs from the main mastercore.cpp/h files.
#include "omnicore_encoding.h"

#include "mastercore.h"
#include "mastercore_script.h"
#include "omnicore_encoding.h"
#include "omnicore_utils.h"

#include "base58.h"
#include "primitives/transaction.h"
#include "pubkey.h"
#include "random.h"
#include "script/script.h"
#include "script/standard.h"
#include "utilstrencodings.h"
#include "random.h"
#include "wallet.h"
#include "openssl/sha.h"

#include <boost/algorithm/string.hpp>

#include <stdint.h>
#include <string>
#include <utility>
#include <vector>

bool OmniCore_Encode_ClassB(const std::string& senderAddress, const CPubKey& redeemingPubKey, const std::vector<unsigned char>& vecPayload, std::vector<std::pair <CScript,int64_t> >& vecOutputs)
/**
* Embedds a payload in obfuscated multisig outputs, and adds an Exodus marker output.
*
* @see The class B transaction encoding specification:
* https://github.com/mastercoin-MSC/spec#class-b-transactions-also-known-as-the-multisig-method
*/
bool OmniCore_Encode_ClassB(const std::string& senderAddress, const CPubKey& redeemingPubKey,
const std::vector<unsigned char>& vchPayload, std::vector<std::pair<CScript, int64_t> >& vecOutputs)
{
int nRemainingBytes = vecPayload.size();
int nRemainingBytes = vchPayload.size();
int nNextByte = 0;
unsigned char seqNum = 1;
unsigned char chSeqNum = 1;
std::string strObfuscatedHashes[1+MAX_SHA256_OBFUSCATION_TIMES];
PrepareObfuscatedHashes(senderAddress, strObfuscatedHashes);
while (nRemainingBytes > 0) {
int nKeys = 1; // assume one key of data since we have data remaining
if (nRemainingBytes > (PACKET_SIZE - 1)) { nKeys += 1; } // we have enough data for 2 keys in this output
std::vector<CPubKey> keys;
keys.push_back(redeemingPubKey); // always include the redeeming pubkey
int nKeys = 1; // Assume one key of data, because we have data remaining
if (nRemainingBytes > (PACKET_SIZE - 1)) { nKeys += 1; } // ... or enough data to embed in 2 keys
std::vector<CPubKey> vKeys;
vKeys.push_back(redeemingPubKey); // Always include the redeeming pubkey
for (int i = 0; i < nKeys; i++) {
std::vector<unsigned char> fakeKey;
fakeKey.push_back(seqNum); // add sequence number
int numBytes = nRemainingBytes < (PACKET_SIZE - 1) ? nRemainingBytes: (PACKET_SIZE - 1); // add up to 30 bytes of data
fakeKey.insert(fakeKey.end(), vecPayload.begin() + nNextByte, vecPayload.begin() + nNextByte + numBytes);
nNextByte += numBytes;
nRemainingBytes -= numBytes;
while (fakeKey.size() < PACKET_SIZE) { fakeKey.push_back(0); } // pad to 31 total bytes with zeros
std::vector<unsigned char>hash = ParseHex(strObfuscatedHashes[seqNum]);
for (int j = 0; j < PACKET_SIZE; j++) { // xor in the obfuscation
fakeKey[j] = fakeKey[j] ^ hash[j];
// Add up to 30 bytes of data
int nCurrentBytes = nRemainingBytes < (PACKET_SIZE - 1) ? nRemainingBytes: (PACKET_SIZE - 1);
std::vector<unsigned char> vchFakeKey;
vchFakeKey.insert(vchFakeKey.end(), chSeqNum); // Add sequence number
vchFakeKey.insert(vchFakeKey.end(), vchPayload.begin() + nNextByte,
vchPayload.begin() + nNextByte + nCurrentBytes);
vchFakeKey.resize(PACKET_SIZE); // Pad to 31 total bytes with zeros
nNextByte += nCurrentBytes;
nRemainingBytes -= nCurrentBytes;
std::vector<unsigned char> vchHash = ParseHex(strObfuscatedHashes[chSeqNum]);
for (int j = 0; j < PACKET_SIZE; j++) { // Xor in the obfuscation
vchFakeKey[j] = vchFakeKey[j] ^ vchHash[j];
}
fakeKey.insert(fakeKey.begin(), 2); // prepend the 2
vchFakeKey.insert(vchFakeKey.begin(), 0x02); // Prepend a public key prefix
vchFakeKey.resize(33);
CPubKey pubKey;
fakeKey.resize(33);
unsigned char random_byte = (unsigned char)(GetRand(256)); // fix up the ecdsa code point
for (int j = 0; i < 256 ; j++) {
fakeKey[32] = random_byte;
pubKey = CPubKey(fakeKey);
unsigned char chRandom = static_cast<unsigned char>(GetRand(256));
for (int j = 0; i < 256 ; j++) { // Fix ECDSA coodinate
vchFakeKey[32] = chRandom;
pubKey = CPubKey(vchFakeKey);
if (pubKey.IsFullyValid()) break;
++random_byte; // cycle 256 times, if we must to find a valid ECDSA point
++chRandom; // ... but cycle no more than 256 times to find a valid point
}
keys.push_back(pubKey);
seqNum++;
vKeys.push_back(pubKey);
chSeqNum++;
}
CScript multisig_output = GetScriptForMultisig(1, keys);
vecOutputs.push_back(make_pair(multisig_output, GetDustThreshold(multisig_output)));

// Push back a bare multisig output with obfuscated data
CScript scriptMultisigOut = GetScriptForMultisig(1, vKeys);
vecOutputs.push_back(std::make_pair(scriptMultisigOut, GetDustThreshold(scriptMultisigOut)));
}
CScript scriptPubKey = GetScriptForDestination(CBitcoinAddress(exodus_address).Get());
vecOutputs.push_back(make_pair(scriptPubKey, GetDustThreshold(scriptPubKey))); // add the Exodus marker

// Add the Exodus marker output
CScript scriptExodusOutput = GetScriptForDestination(ExodusAddress().Get());
vecOutputs.push_back(std::make_pair(scriptExodusOutput, GetDustThreshold(scriptExodusOutput)));
return true;
}

bool OmniCore_Encode_ClassC(const std::vector<unsigned char>& vecPayload, std::vector<std::pair <CScript,int64_t> >& vecOutputs)
/**
* @return The marker for class C transactions.
*/
static inline std::vector<unsigned char> GetOmMarker()
{
const unsigned char pch[] = {0x6f, 0x6d}; // Hex-encoded: "om"

return std::vector<unsigned char>(pch, pch + sizeof (pch) / sizeof (pch[0]));
}

/**
* Embedds a payload in an OP_RETURN output, prefixed with a transaction marker.
*
* The request is rejected, if the size of the payload with marker is larger than
* the allowed data carrier size ("-datacarriersize=n").
*/
bool OmniCore_Encode_ClassC(const std::vector<unsigned char>& vchPayload,
std::vector<std::pair <CScript, int64_t> >& vecOutputs)
{
const unsigned char bytes[] = {0x6f,0x6d}; // define Omni marker bytes
if (vecPayload.size() > nMaxDatacarrierBytes-sizeof(bytes)/sizeof(bytes[0])) { return false; } // we shouldn't see this since classAgnostic_send handles size vs class, but include check here for safety
std::vector<unsigned char> omniBytesPlusData(bytes, bytes+sizeof(bytes)/sizeof(bytes[0]));
omniBytesPlusData.insert(omniBytesPlusData.end(), vecPayload.begin(), vecPayload.end());
std::vector<unsigned char> vchData;
std::vector<unsigned char> vchOmBytes = GetOmMarker();
vchData.insert(vchData.end(), vchOmBytes.begin(), vchOmBytes.end());
vchData.insert(vchData.end(), vchPayload.begin(), vchPayload.end());
if (vchData.size() > nMaxDatacarrierBytes) { return false; }

CScript script;
script << OP_RETURN << omniBytesPlusData;
vecOutputs.push_back(make_pair(script, 0));
script << OP_RETURN << vchData;
vecOutputs.push_back(std::make_pair(script, 0));
return true;
}
13 changes: 9 additions & 4 deletions src/omnicore_encoding.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,17 @@
class CPubKey;
class CTxOut;

#include "script/script.h"

#include <stdint.h>
#include <string>
#include <utility>
#include <vector>
#include "script/script.h"
#include "script/standard.h"

bool OmniCore_Encode_ClassB(const std::string& senderAddress, const CPubKey& redeemingPubKey, const std::vector<unsigned char>& vecPayload, std::vector<std::pair <CScript,int64_t> >& vecOutputs);
bool OmniCore_Encode_ClassC(const std::vector<unsigned char>& vecPayload, std::vector<std::pair <CScript,int64_t> >& vecOutputs);
/** Embedds a payload in obfuscated multisig outputs, and adds an Exodus marker output. */
bool OmniCore_Encode_ClassB(const std::string& senderAddress, const CPubKey& redeemingPubKey, const std::vector<unsigned char>& vchPayload, std::vector<std::pair<CScript, int64_t> >& vecOutputs);

/** Embedds a payload in an OP_RETURN output, prefixed with a transaction marker. */
bool OmniCore_Encode_ClassC(const std::vector<unsigned char>& vecPayload, std::vector<std::pair<CScript, int64_t> >& vecOutputs);

#endif // OMNICORE_ENCODING_H
Loading

0 comments on commit c1de71c

Please sign in to comment.