<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE nta PUBLIC '-//Uppaal Team//DTD Flat System 1.1//EN' 'http://www.it.uu.se/research/group/darts/uppaal/flat-1_2.dtd'>
<nta>
	<declaration>// Place global declarations here.
//this model checks probability by contructing secret chain
broadcast chan Transaction;
broadcast chan request;
broadcast chan send; //Question: shall it be broadcast??
const int N = 4;//max number of pools
const int PEERS = 4; // maximum number of peers
const int MAX_WALLET = PEERS+1;
broadcast chan blockSolution;
broadcast chan secretSolution;
const int HASHSIZE = 30000; //hashes are stored as integers
const int MAX_TRANSACTION = 30000;//maximum number of transactions
const int MAX_BLOCK = 30000; //maximum number of blocks
const int MAX_ORPHAN_BLOCK = 1; //maximum number of blocks
bool flag =false;
//const int MAX_INPUT_TRANSACTION = 3; //maximum number of input transactions
//const int MAX_OUTPUT_TRANSACTION = 3; //maximum number of output transactions
//const int MAX_BTC_AMOUNT = 12; //maximum amount (BTC)
const int MAX_POOL_SIZE = PEERS+1; //maximum size of the Pool
const int UNCONFIRMED = 0;
const int CONFIRMED = 1;
const int INVALID = 2;
typedef int[1,N] id_t;//Pool ID
typedef int[-1,HASHSIZE] BLOCKHASH; //first block will refer to -1
typedef int[-1,MAX_TRANSACTION] TXNUMBER;//first transaction will refer to -1
//typedef int[0,MAX_INPUT_TRANSACTION] COUNT_TX_IN;//number of input transactions
//typedef int[0,MAX_OUTPUT_TRANSACTION] COUNT_TX_OUT;//number of output transactions
//typedef int[0,MAX_BTC_AMOUNT] AMOUNT;//Amount will be used in output transaction
typedef int[0,PEERS+N] PEER;// there will be senders who do not take part in mining. These will just send transactions.
//typedef int[0,INVALID] STATUS; //Transaction status : UNCONFIRMED or CONFIRMED

int [0, MAX_POOL_SIZE] tranIndex = 0;
int [0, MAX_POOL_SIZE] tranIndex2 = 0;
//output transaction structure
typedef struct{
PEER Address;
//AMOUNT value;
}TXOUT;

int confirmation = 0;
int confirmation_counter = 0;
//input transaction structure
typedef struct{
TXNUMBER id;

}TXIN;

//Assumption: There is  one input and two output transaction
typedef struct {
TXNUMBER Id;
//COUNT_TX_OUT ouputCount;
TXIN TxInput;
TXOUT TxOutput;
//COUNT_TX_IN inputCount;
//COUNT_TX_OUT ouputCount;
//STATUS status;	
}Tx; //transaction


//Assumption only one transaction will be included in one block
typedef struct {
BLOCKHASH num;
BLOCKHASH prevBlocknum;	
Tx tx;	
}Block; //block details


//Blockchain structure with maximum of 20 blocks
typedef struct{
Block chain[MAX_BLOCK];

}BlockChain;

//wallet will be used by peers to maintain unspent output from every transaction
typedef struct{
TXNUMBER Id;
//AMOUNT value;

}Wallet;
//Every transaction will have a unique number. Therefore stored here as global.
TXNUMBER Tx_num = PEERS+1;

//Every block will have a unique number interms of hash.
BLOCKHASH Block_num = 2;

Tx TxPool[MAX_POOL_SIZE]; //transaction pool. Peers will create transaction and place in this pool. Miners will use transaction for mining.
Tx MPeerPool; //this is for MPeer and MPool

//meta Tx TxGlobal;
meta Block Chain;
meta BLOCKHASH Blocknum;
//meta Block orphanBlock;




</declaration>
	<template>
		<name x="5" y="5">Pool</name>
		<parameter>const id_t id,  const int &amp;rateX</parameter>
		<declaration>// Place local declarations here.
clock x;
bool orphan = false;
Tx localTx;

int chain1[4], chain2[4];

int lengthLongestChain = 1;
int normalChainLength = 0;

int blockDifference = 0;
void initial()
{
    int i;
    chain1[0] = 1;
    chain1[1] = 0;
    chain1[3] = 1;
    chain2[0] = 1;
    chain2[1] = 0;
    chain2[3] = 1;
    for(i = 0; i &lt; MAX_POOL_SIZE; i++)
    {
        if(TxPool[i].Id == 0)
            TxPool[i].Id = -1;
    }
}

bool checkTxPool()
{
    bool flag = false;
    int i;
    if((TxPool[tranIndex2].Id != -1  )/* &amp;&amp; TxPool[i].status == UNCONFIRMED*/)
    {
        flag = true;
    }
    return flag;
}

void getTransaction()
{
    localTx.Id = TxPool[tranIndex2].Id;
    localTx.TxInput.id = TxPool[tranIndex2].TxInput.id;
    localTx.TxOutput.Address = TxPool[tranIndex2].TxOutput.Address;

}

void resetLocalTx()
{
    localTx.Id = -1;
    localTx.TxInput.id = -1;
    localTx.TxOutput.Address = 0;
}


//
void removeTxPool()
{
    TxPool[tranIndex2].Id = -1;
    TxPool[tranIndex2].TxInput.id = -1;
    TxPool[tranIndex2].TxOutput.Address = 0;

}

void updateBlockChain()
{
    //update on global variable
    Chain.num = Block_num;
    Chain.tx.Id = localTx.Id;
    Chain.tx.TxInput.id = localTx.TxInput.id;
    Chain.tx.TxOutput.Address = localTx.TxOutput.Address;
    Chain.prevBlocknum = chain1[0];
    chain1[0] = Chain.num;
    chain1[1] = Chain.prevBlocknum;
    chain1[2] = id;
    if (MPeerPool.Id != 0 )
        flag = true;

    //update global variable block hash
    Block_num = (Block_num + 1)% HASHSIZE;
    //remove transaction from pool
    removeTxPool();
    //reset localTx
    resetLocalTx();
    tranIndex2 = (tranIndex2 + 1)%MAX_POOL_SIZE;
}

void addBlock()
{

    chain1[0] = Chain.num;
    chain1[1] = Chain.prevBlocknum;
}
</declaration>
		<location id="id0" x="-2261" y="-2210">
			<name x="-2271" y="-2244">Initial</name>
			<committed/>
		</location>
		<location id="id1" x="-2125" y="-2210">
			<name x="-2099" y="-2235">Mine</name>
			<label kind="exponentialrate" x="-2099" y="-2201">1:rateX</label>
		</location>
		<init ref="id0"/>
		<transition>
			<source ref="id0"/>
			<target ref="id1"/>
			<label kind="assignment" x="-2218" y="-2201">initial()</label>
		</transition>
		<transition>
			<source ref="id1"/>
			<target ref="id1"/>
			<label kind="synchronisation" x="-2167" y="-2056">blockSolution?</label>
			<label kind="assignment" x="-2167" y="-2031">x=0,
addBlock()</label>
			<nail x="-2184" y="-2057"/>
			<nail x="-2048" y="-2057"/>
		</transition>
		<transition>
			<source ref="id1"/>
			<target ref="id1"/>
			<label kind="guard" x="-2168" y="-2465">checkTxPool()&amp;&amp; flag == false</label>
			<label kind="synchronisation" x="-2176" y="-2448">blockSolution!</label>
			<label kind="assignment" x="-2176" y="-2431">getTransaction(),
updateBlockChain(),
x = 0</label>
			<nail x="-2065" y="-2371"/>
			<nail x="-2184" y="-2371"/>
		</transition>
	</template>
	<template>
		<name>Peer</name>
		<parameter>const PEER id, const int &amp;confirmation_no</parameter>
		<declaration>clock x1;

Wallet wallet[MAX_WALLET];
int [0,MAX_WALLET]walletIndex = 1;
int [0,MAX_WALLET]walletIndex2 = 0;
void initial()
{
    int i;
    wallet[0].Id = id;
    for(i = 1; i &lt; MAX_WALLET; i++)
        wallet[i].Id = -1;
    for(i = 0; i &lt; MAX_POOL_SIZE; i++)
    {
        if(TxPool[i].Id == 0)
            TxPool[i].Id = -1;
    }
}

//create transaction
void create_Transaction(PEER Add)
{
    int i, index = -1, j;

    TxPool[tranIndex].Id = Tx_num;
    TxPool[tranIndex].TxInput.id = wallet[walletIndex2].Id;
    TxPool[tranIndex].TxOutput.Address = Add;
    wallet[walletIndex2].Id = -1;
    walletIndex2 = (walletIndex2 + 1)%MAX_WALLET;
    Tx_num = (Tx_num + 1)% MAX_TRANSACTION;
    tranIndex = (tranIndex + 1) %MAX_POOL_SIZE;
}

//check whether peer has bitcoins to do any transaction
bool checkWallet()
{
    bool flag = false;

    if(wallet[walletIndex2].Id !=-1)
    {
        flag = true;
    }
    return flag;
}


void updateWallet()
{
    if ( Chain.tx.TxOutput.Address == id)
    {
        wallet[walletIndex].Id = Chain.tx.Id;
        walletIndex = (walletIndex + 1) % MAX_WALLET;
    }
}
</declaration>
		<location id="id2" x="-816" y="-102">
			<name x="-826" y="-136">Initial</name>
			<committed/>
		</location>
		<location id="id3" x="-680" y="-102">
			<name x="-714" y="-93">Wait</name>
			<label kind="exponentialrate" x="-690" y="-68">1:1</label>
		</location>
		<init ref="id2"/>
		<transition>
			<source ref="id3"/>
			<target ref="id3"/>
			<label kind="synchronisation" x="-704" y="-391">secretSolution?</label>
			<label kind="assignment" x="-704" y="-374">updateWallet()</label>
			<nail x="-722" y="-374"/>
			<nail x="-612" y="-374"/>
		</transition>
		<transition>
			<source ref="id3"/>
			<target ref="id3"/>
			<label kind="synchronisation" x="-510" y="-382">blockSolution?</label>
			<label kind="assignment" x="-510" y="-365">updateWallet(),
x1=0</label>
			<nail x="-569" y="-357"/>
			<nail x="-467" y="-297"/>
		</transition>
		<transition>
			<source ref="id2"/>
			<target ref="id3"/>
			<label kind="assignment" x="-765" y="-93">initial()</label>
		</transition>
		<transition>
			<source ref="id3"/>
			<target ref="id3"/>
			<label kind="select" x="-399" y="-280">add:int[1,PEERS-1]</label>
			<label kind="guard" x="-399" y="-263">checkWallet() &amp;&amp; flag == false</label>
			<label kind="assignment" x="-399" y="-246">create_Transaction(add),
x1 = 0</label>
			<nail x="-399" y="-170"/>
			<nail x="-450" y="-280"/>
		</transition>
	</template>
	<template>
		<name>MPeer</name>
		<parameter>const PEER id</parameter>
		<declaration>clock x1;

Wallet wallet[1];

int counter = 0;
void initial()
{
    int i;
    wallet[0].Id = id;
}

//create transaction
void create_Transaction(PEER Add)
{
    int i, index = -1, j;
    TxPool[tranIndex].Id = Tx_num;
    TxPool[tranIndex].TxInput.id = wallet[0].Id;
    TxPool[tranIndex].TxOutput.Address = Add;
    Tx_num = (Tx_num + 1)% MAX_TRANSACTION;
    tranIndex = (tranIndex + 1) %MAX_POOL_SIZE;
}


void createDuplicateTransaction()
{
    MPeerPool.Id = Tx_num;
    MPeerPool.TxInput.id = wallet[0].Id;
    MPeerPool.TxOutput.Address = id;
    Tx_num = (Tx_num + 1)% MAX_TRANSACTION;
}

</declaration>
		<location id="id4" x="-816" y="-102">
			<name x="-826" y="-136">Initial</name>
			<committed/>
		</location>
		<location id="id5" x="-680" y="-102">
			<name x="-714" y="-93">Wait</name>
		</location>
		<init ref="id4"/>
		<transition>
			<source ref="id4"/>
			<target ref="id5"/>
			<label kind="select" x="-798" y="-153">add:int[1,PEERS]</label>
			<label kind="assignment" x="-765" y="-93">initial(),
create_Transaction(add),
createDuplicateTransaction(),
x1 = 0,
counter++</label>
		</transition>
	</template>
	<template>
		<name>MPool</name>
		<parameter>const id_t ID,   const int &amp;rateX, const int &amp;confirmation_no</parameter>
		<declaration>// Place local declarations here.
clock x;

Tx localTx;

BLOCKHASH  racePrevBlock,MPrevBlock;
int chain1[5];
int chain2[5];
int raceLength = 0;
int racePrevBlockIndex = 0;
int racePrevBlockLength = -1;
int normalChainLength = 0;
int count = 0, counter =0;
bool raceFlag = false, raceflag = false, requestOrphan = false, raceSuccess = false;
int blockDifference = 0;
int blockDifference1 = 0;
bool checkRace()
{
    if(raceflag == true &amp;&amp; raceLength &gt; normalChainLength)
        return true;
    return false;

}
void initial()
{
    int i;
    confirmation = confirmation_no;
    chain1[0] = 1;
    chain1[1] = 0;
    chain1[3] = 1;
    chain2[0] = 1;
    chain2[1] = 0;
    chain2[3] = 1;
    for(i = 0; i &lt; MAX_POOL_SIZE; i++)
    {
        if(TxPool[i].Id == 0)
            TxPool[i].Id = -1;
    }
}

void resetMPeerPool()
{
    MPeerPool.Id = 0;
    MPeerPool.TxOutput.Address = 0;

}
bool checkTxPool()
{
    bool flag = false;
    int i;
    if((TxPool[tranIndex2].Id != -1 ))
    {
        flag = true;
    }

    return flag;
}

void getTransaction()
{
    localTx.Id = TxPool[tranIndex2].Id;
    localTx.TxInput.id = TxPool[tranIndex2].TxInput.id;
    localTx.TxOutput.Address = TxPool[tranIndex2].TxOutput.Address;
}

void resetLocalTx()
{
    localTx.Id = -1;
    localTx.TxInput.id = -1;
    localTx.TxOutput.Address = 0;
}


//
void removeTxPool()
{
    TxPool[tranIndex2].Id = -1;
    TxPool[tranIndex2].TxInput.id = -1;
    TxPool[tranIndex2].TxOutput.Address = 0;
}

void updateBlockChain()
{
    if(raceFlag == false)
    {

    }
    else
    {
        chain2[1] = chain2[0];
        Chain.num = Block_num;
        Chain.prevBlocknum = chain2[1];
        Chain.tx.Id = localTx.Id;
        Chain.tx.TxInput.id = localTx.TxInput.id;
        Chain.tx.TxOutput.Address = localTx.TxOutput.Address;
        chain2[0] = Chain.num;
        chain2[2] = ID;
        chain2[4] = localTx.TxInput.id;
        blockDifference++;
        if (blockDifference &gt;= blockDifference1 &amp;&amp; blockDifference1 &gt; confirmation_no)
        {
            raceSuccess = true;
        }
        raceflag = true;
    }
    Block_num = (Block_num + 1)%HASHSIZE;
    //remove transaction from pool

    if(MPeerPool.Id == 0)
    {
        removeTxPool();
        tranIndex2 = (tranIndex2 + 1)% MAX_POOL_SIZE;
    }
    else
        resetMPeerPool();
    //reset localTx
    resetLocalTx();
}

void addBlock()
{
    chain1[0] = Chain.num;
    chain1[1] = Chain.prevBlocknum;
    blockDifference1++;
    chain1[4] = Chain.tx.TxInput.id;
}

</declaration>
		<location id="id6" x="-1972" y="-2210">
			<name x="-1980" y="-2261">Mine</name>
			<label kind="exponentialrate" x="-1963" y="-2193">1:rateX</label>
		</location>
		<location id="id7" x="-2176" y="-2210">
			<name x="-2202" y="-2244">Initial</name>
			<committed/>
		</location>
		<init ref="id7"/>
		<transition color="#0000ff">
			<source ref="id6"/>
			<target ref="id6"/>
			<label kind="guard" x="-2278" y="-1989">MPeerPool.Id != 0  &amp;&amp;  flag == true</label>
			<label kind="assignment" x="-2193" y="-2091">raceFlag = true,
updateBlockChain(),
flag = false,
confirmation_counter = 0</label>
			<nail x="-2057" y="-2057"/>
			<nail x="-1946" y="-2040"/>
		</transition>
		<transition>
			<source ref="id7"/>
			<target ref="id6"/>
			<label kind="assignment" x="-2116" y="-2235">initial()</label>
		</transition>
		<transition>
			<source ref="id6"/>
			<target ref="id6"/>
			<label kind="synchronisation" x="-1751" y="-2210">blockSolution?</label>
			<label kind="assignment" x="-1751" y="-2193">addBlock(),
x=0</label>
			<nail x="-1759" y="-2244"/>
			<nail x="-1776" y="-2142"/>
		</transition>
		<transition>
			<source ref="id6"/>
			<target ref="id6"/>
			<label kind="guard" x="-1785" y="-2388">checkTxPool() &amp;&amp; MPeerPool.Id ==0</label>
			<label kind="synchronisation" x="-1793" y="-2363">secretSolution!</label>
			<label kind="assignment" x="-1734" y="-2346">x = 0,
getTransaction(),
updateBlockChain()</label>
			<nail x="-1768" y="-2269"/>
			<nail x="-1819" y="-2363"/>
		</transition>
	</template>
	<system>// Place template instantiations here.

// List one or more processes to be composed into a system.
/*
Pool1 = Pool(1, 5433);
Pool2 = Pool(2, 3018);
Pool3 = Pool(3, 2469);
Pool4 = MPool(4, 1041,6);

Pool1 = Pool(1, 3622);//15%
Pool2 = Pool(2, 3018);//18%
Pool3 = Pool(3, 2469);//22%
Pool4 = MPool(4, 1207,6);//45%

Pool1 = Pool(1, 2716);//20%
Pool2 = Pool(2, 1940);//28%
Pool3 = Pool(3, 2469);//22%
Pool4 = MPool(4, 1811,6);//30%

Pool1 = Pool(1, 1811);//30%
Pool2 = Pool(2, 1940);//28%
Pool3 = Pool(3, 2469);//22%
Pool4 = MPool(4, 2716,6);//20%

Pool1 = Pool(1, 1207);//45%
Pool2 = Pool(2, 3018);//18%
Pool3 = Pool(3, 2469);//22%
Pool4 = MPool(4, 3622,6);//15%

Pool1 = Pool(1, 1086);//50%
Pool2 = Pool(2, 1811);//30%
Pool3 = Pool(3, 3622);//15%
Pool4 = MPool(4, 10867,3);//5%

*/

Pool1 = Pool(1, 1811);//30%
Pool2 = Pool(2, 1940);//28%
Pool3 = Pool(3, 2469);//22%
Pool4 = MPool(4, 2716,1);//20%

Peer1 = Peer(1, 0);
Peer2 = Peer(2, 0);
Peer3 = Peer(3, 0);
MPeer1 = MPeer(4);
MPeer2 = MPeer(4);
MPeer3 = MPeer(5);
//Peer5 = Peer(4, 0);
//Peer6 = Peer(5, 0);
//Peer7 = Peer(6, 0);
system   Pool4, Pool1, Pool2,Pool3,  Peer1, Peer2,Peer3, MPeer1;//Peer5, Peer6, Peer7, MPool1;
    

</system>
	<queries>
		<query>
			<formula>Pr[#&lt;=60000](&lt;&gt;   Pool4.raceSuccess == true)
			</formula>
			<comment>
			</comment>
		</query>
	</queries>
</nta>
