update to newer version
This commit is contained in:
parent
d6a32870bc
commit
29138de53e
37 changed files with 15795 additions and 12789 deletions
BIN
wallet/.DS_Store
vendored
BIN
wallet/.DS_Store
vendored
Binary file not shown.
|
@ -1,67 +0,0 @@
|
|||
const ChainUtil = require('../chain-util');
|
||||
const { MINING_REWARD } = require('../config');
|
||||
|
||||
class CoinTransaction {
|
||||
constructor() {
|
||||
this.id = ChainUtil.id();
|
||||
this.input = null;
|
||||
this.outputs = [];
|
||||
}
|
||||
|
||||
update(senderWallet, recipient, amount) {
|
||||
const senderOutput = this.outputs.find(output => output.address === senderWallet.publicKey);
|
||||
if (amount > senderOutput.amount) {
|
||||
console.log(`Amount: ${amount} exceeds balance.`);
|
||||
return;
|
||||
}
|
||||
|
||||
senderOutput.amount = senderOutput.amount - amount;
|
||||
this.outputs.push({ amount, address: recipient });
|
||||
CoinTransaction.signCoinTransaction(this, senderWallet);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static CoinTransactionWithOutputs(senderWallet, outputs) {
|
||||
const cointransaction = new this();
|
||||
cointransaction.outputs.push(...outputs);
|
||||
CoinTransaction.signCoinTransaction(cointransaction, senderWallet);
|
||||
return cointransaction;
|
||||
}
|
||||
|
||||
static newCoinTransaction(senderWallet, recipient, amount) {
|
||||
if (amount > senderWallet.balance) {
|
||||
console.log(`Amount: ${amount} exceeds balance.`);
|
||||
return;
|
||||
}
|
||||
|
||||
return CoinTransaction.CoinTransactionWithOutputs(senderWallet, [
|
||||
{ amount: senderWallet.balance - amount, address: senderWallet.publicKey},
|
||||
{ amount, address: recipient }]);
|
||||
}
|
||||
|
||||
static rewardCoinTransaction(minerWallet, blockchainWallet) {
|
||||
return CoinTransaction.CoinTransactionWithOutputs(blockchainWallet, [{
|
||||
amount: MINING_REWARD, address: minerWallet.publicKey
|
||||
}]);
|
||||
}
|
||||
|
||||
static signCoinTransaction(cointransaction, senderWallet) {
|
||||
cointransaction.input = {
|
||||
timestamp: Date.now(),
|
||||
amount: senderWallet.balance,
|
||||
address: senderWallet.publicKey,
|
||||
signature: senderWallet.sign(ChainUtil.hash(cointransaction.outputs))
|
||||
}
|
||||
}
|
||||
|
||||
static verifyCoinTransaction(cointransaction) {
|
||||
return ChainUtil.verifySignature(
|
||||
cointransaction.input.address,
|
||||
cointransaction.input.signature,
|
||||
ChainUtil.hash(cointransaction.outputs)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CoinTransaction;
|
|
@ -1,100 +0,0 @@
|
|||
const ChainUtil = require('../chain-util');
|
||||
|
||||
class MetaDataTransaction {
|
||||
constructor() {
|
||||
this.id = null; // if there is a problem in the metadata transaction, change null with ChainUtil.id();
|
||||
this.Signiture = null;
|
||||
this.Name = null;
|
||||
this.Geo = [];
|
||||
this.IP_URL = null;
|
||||
this.Topic_Token = null;
|
||||
this.Permission = null;
|
||||
this.RequestDetail = null;
|
||||
this.OrgOwner = null;
|
||||
this.DepOwner = null;
|
||||
this.PrsnOwner = null;
|
||||
this.MetaHash = null;
|
||||
this.PaymentPerKbyte = null;
|
||||
this.PaymentPerMinute = null;
|
||||
this.Protocol = null;
|
||||
this.MessageAttributes= {};
|
||||
this.Interval = null;
|
||||
this.FurtherDetails = null;
|
||||
this.SSNmetadata = null;
|
||||
|
||||
// this.Geo = null;
|
||||
// this.Std = null;
|
||||
// this.name= null;
|
||||
// this.MetaHash= null;
|
||||
// this.file=null;
|
||||
}
|
||||
|
||||
// update(senderWallet, Geo, URI, Name,Permission, OrgOwner, SSNmetadata) {
|
||||
|
||||
// this.Geo = Geo;
|
||||
// this.URI = URI;
|
||||
// this.Name = Name;
|
||||
// this.Permission = Permission;
|
||||
// this.OrgOwner = OrgOwner;
|
||||
// this.PrsnOwner = senderWallet.publicKey;
|
||||
// this.MetaHash = ChainUtil.hash(SSNmetadata);
|
||||
// this.SSNmetadata = SSNmetadata;
|
||||
|
||||
// MetaDatatransaction.signMetaDataTransaction(this, senderWallet);
|
||||
|
||||
// return this;
|
||||
// }
|
||||
|
||||
static MetaDataTransactionWithIoT(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Intrval, FurtherDetails, SSNmetadata) {
|
||||
const metaDataTransaction = new this();
|
||||
metaDataTransaction.id = ChainUtil.id();
|
||||
metaDataTransaction.Name = Name;
|
||||
metaDataTransaction.Geo = Geo;
|
||||
metaDataTransaction.IP_URL = IP_URL;
|
||||
metaDataTransaction.Topic_Token = Topic_Token;
|
||||
metaDataTransaction.Permission = Permission;
|
||||
metaDataTransaction.RequestDetail = RequestDetail
|
||||
metaDataTransaction.OrgOwner = OrgOwner;
|
||||
metaDataTransaction.DepOwner = DepOwner;
|
||||
metaDataTransaction.PrsnOwner = PrsnOwner;
|
||||
metaDataTransaction.PaymentPerKbyte = PaymentPerKbyte ;
|
||||
metaDataTransaction.PaymentPerMinute = PaymentPerMinute;
|
||||
metaDataTransaction.Protocol = Protocol;
|
||||
metaDataTransaction.MessageAttributes = MessageAttributes;
|
||||
metaDataTransaction.MessageAttributes['DeviceID'] = metaDataTransaction.id;
|
||||
metaDataTransaction.MessageAttributes['DeviceName'] = Name;
|
||||
metaDataTransaction.MessageAttributes['Sensors'] =[{"SensorName":"","Value":"" , "Unit":""}];
|
||||
metaDataTransaction.MessageAttributes['TimeStamp'] = "";
|
||||
metaDataTransaction.Interval = Intrval;
|
||||
metaDataTransaction.FurtherDetails = FurtherDetails;
|
||||
metaDataTransaction.SSNmetadata = SSNmetadata;
|
||||
metaDataTransaction.MetaHash = ChainUtil.hash(SSNmetadata);
|
||||
MetaDataTransaction.signMetaDataTransaction(metaDataTransaction, senderWallet);
|
||||
return metaDataTransaction;
|
||||
}
|
||||
|
||||
|
||||
static newMetaDataTransaction(senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval, FurtherDetails, SSNmetadata){
|
||||
return MetaDataTransaction.MetaDataTransactionWithIoT(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval, FurtherDetails, SSNmetadata
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
static signMetaDataTransaction (metaDataTransaction, senderWallet) {
|
||||
metaDataTransaction.Signiture = {
|
||||
timestamp: Date.now(),
|
||||
address: senderWallet.publicKey,
|
||||
signature: senderWallet.sign(ChainUtil.hash(metaDataTransaction.SSNmetadata))
|
||||
}
|
||||
}
|
||||
|
||||
static verifyMetaDataTransaction(metaDataTransaction) {
|
||||
return ChainUtil.verifySignature(
|
||||
metaDataTransaction.Signiture.address,
|
||||
metaDataTransaction.Signiture.signature,
|
||||
ChainUtil.hash(metaDataTransaction.SSNmetadata)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
module.exports = MetaDataTransaction;
|
|
@ -1,8 +1,7 @@
|
|||
const ChainUtil = require('../chain-util');
|
||||
const CoinTransaction = require('./CoinTransaction');
|
||||
const Transaction = require('./transaction');
|
||||
const { INITIAL_BALANCE } = require('../config');
|
||||
const MetaDataTransaction = require('./MetaDataTransaction');
|
||||
const transactionPool = require('./transaction-pool');
|
||||
const Metadata = require('./metadata');
|
||||
|
||||
class Wallet {
|
||||
constructor() {
|
||||
|
@ -21,49 +20,57 @@ class Wallet {
|
|||
return this.keyPair.sign(dataHash);
|
||||
}
|
||||
|
||||
createCoinTransaction(recipient, amount, blockchain, transactionPool) {
|
||||
// this.balance = this.calculateBalance(blockchain);
|
||||
createTransaction(recipient, amount, blockchain, transactionPool) {
|
||||
this.balance = this.calculateBalance(blockchain);
|
||||
|
||||
if (amount > this.balance) {
|
||||
console.log(`Amount: ${amount} exceceds current balance: ${this.balance}`);
|
||||
return;
|
||||
}
|
||||
if (amount > this.balance) {
|
||||
console.log(`Amount: ${amount} exceceds current balance: ${this.balance}`);
|
||||
return;
|
||||
}
|
||||
|
||||
let cointransaction = transactionPool.existingPaymentTransaction(this.publicKey);
|
||||
let transaction = transactionPool.existingTransaction(this.publicKey);
|
||||
|
||||
if (transaction) {
|
||||
transaction.update(this, recipient, amount);
|
||||
} else {
|
||||
transaction = Transaction.newTransaction(this, recipient, amount);
|
||||
transactionPool.updateOrAddTransaction(transaction);
|
||||
}
|
||||
|
||||
if (cointransaction) {
|
||||
cointransaction.update(this, recipient, amount);
|
||||
} else { //this should be the original one
|
||||
//just for test i make the transaction not to update if the sender is the same
|
||||
cointransaction = CoinTransaction.newCoinTransaction(this, recipient, amount);
|
||||
transactionPool.updateOrAddPaymentTransaction(cointransaction);
|
||||
}
|
||||
|
||||
return cointransaction;
|
||||
return transaction;
|
||||
}
|
||||
createMetaDataTransaction(Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval, FurtherDetails, SSNmetadata, transactionPool){
|
||||
/* let metaData = metaDataPool.existingMetaData(this.publicKey);
|
||||
|
||||
if (metaData) {
|
||||
metaData.update(this, Geo, Std, Name,MetaHash,file);
|
||||
} else {*/
|
||||
|
||||
const metaDataTransaction= MetaDataTransaction.newMetaDataTransaction(this, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes,Interval, FurtherDetails, SSNmetadata);
|
||||
transactionPool.updateOrAddMetaDataTransaction(metaDataTransaction);
|
||||
//}
|
||||
return metaDataTransaction;
|
||||
}
|
||||
|
||||
createMetadata(Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,
|
||||
PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Interval,
|
||||
FurtherDetails, SSNmetadata, transactionPool){
|
||||
//let metadata = transactionPool.existingMetadata(this.publicKey);
|
||||
|
||||
// if (metaData) {
|
||||
// metadata.update(this, Geo, Std, Name,MetaHash,file);
|
||||
// } else {*/
|
||||
|
||||
let metadata= Metadata.newMetadata(this, Name,Geo ,IP_URL , Topic_Token, Permission,
|
||||
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute,
|
||||
Protocol, MessageAttributes,Interval, FurtherDetails, SSNmetadata);
|
||||
transactionPool.AddMetadata(metadata);
|
||||
|
||||
//}
|
||||
return metadata;
|
||||
}
|
||||
|
||||
|
||||
calculateBalance(blockchain) {
|
||||
let balance = this.balance;
|
||||
let cointransactions = [];
|
||||
blockchain.chain.forEach(block => block.data.forEach(cointransaction => {
|
||||
cointransactions.push(cointransaction);
|
||||
let transactions = [];
|
||||
blockchain.chain.forEach(block => block.data.forEach(transaction => {
|
||||
transactions.push(transaction);
|
||||
}));
|
||||
|
||||
const walletInputTs = cointransactions
|
||||
.filter(cointransaction => cointransaction.input.address === this.publicKey);
|
||||
console.log("transactions of balance")
|
||||
console.log(transactions);
|
||||
const PaymentTransactions = transactions[0];
|
||||
console.log("Payment transactions ")
|
||||
console.log(PaymentTransactions);
|
||||
const walletInputTs = PaymentTransactions.filter(transaction => transaction.input.address === this.publicKey);
|
||||
|
||||
let startTime = 0;
|
||||
|
||||
|
@ -76,9 +83,9 @@ class Wallet {
|
|||
startTime = recentInputT.input.timestamp;
|
||||
}
|
||||
|
||||
cointransactions.forEach(cointransaction => {
|
||||
if (cointransaction.input.timestamp > startTime) {
|
||||
cointransaction.outputs.find(output => {
|
||||
PaymentTransactions.forEach(transaction => {
|
||||
if (transaction.input.timestamp > startTime) {
|
||||
transaction.outputs.find(output => {
|
||||
if (output.address === this.publicKey) {
|
||||
balance += output.amount;
|
||||
}
|
||||
|
@ -96,4 +103,5 @@ class Wallet {
|
|||
}
|
||||
}
|
||||
|
||||
module.exports = Wallet;
|
||||
module.exports = Wallet;
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ describe('Wallet', () => {
|
|||
let wallet, tp, bc;
|
||||
|
||||
beforeEach(() => {
|
||||
wallet = new Wallet();
|
||||
wallet = new Wallet();
|
||||
tp = new TransactionPool();
|
||||
bc = new Blockchain();
|
||||
});
|
||||
|
@ -18,16 +18,12 @@ describe('Wallet', () => {
|
|||
beforeEach(() => {
|
||||
sendAmount = 50;
|
||||
recipient = 'r4nd0m-4ddr355';
|
||||
Geo = 20;
|
||||
Std = 9014;
|
||||
Name = 'temp';
|
||||
MetaHash = '123abcd';
|
||||
transaction = wallet.createCoinTransaction(recipient, sendAmount,Geo, Std, Name,MetaHash, bc, tp);
|
||||
transaction = wallet.createTransaction(recipient, sendAmount, bc, tp);
|
||||
});
|
||||
|
||||
describe('and doing the same transaction', () => {
|
||||
beforeEach(() => {
|
||||
wallet.createCoinTransaction(recipient, sendAmount,Geo, Std, Name,MetaHash, bc, tp);
|
||||
wallet.createTransaction(recipient, sendAmount, bc, tp);
|
||||
});
|
||||
|
||||
it('doubles the `sendAmount` subtracted from the wallet balance', () => {
|
||||
|
@ -50,9 +46,9 @@ describe('Wallet', () => {
|
|||
addBalance = 100;
|
||||
repeatAdd = 3;
|
||||
for (let i=0; i<repeatAdd; i++) {
|
||||
senderWallet.createCoinTransaction(wallet.publicKey, addBalance,Geo, Std, Name,MetaHash, bc, tp);
|
||||
senderWallet.createTransaction(wallet.publicKey, addBalance, bc, tp);
|
||||
}
|
||||
bc.addBlock(tp.paymenttransactions);
|
||||
bc.addBlock(tp.transactions);
|
||||
});
|
||||
|
||||
it('calculates the balance for blockchain transactions matching the recipient', () => {
|
||||
|
@ -70,15 +66,15 @@ describe('Wallet', () => {
|
|||
tp.clear();
|
||||
subtractBalance = 60;
|
||||
recipientBalance = wallet.calculateBalance(bc);
|
||||
wallet.createCoinTransaction(senderWallet.publicKey, subtractBalance,20,9014,'temp','123abc', bc, tp);
|
||||
bc.addBlock(tp.paymenttransactions);
|
||||
wallet.createTransaction(senderWallet.publicKey, subtractBalance, bc, tp);
|
||||
bc.addBlock(tp.transactions);
|
||||
});
|
||||
|
||||
describe('and the sender sends another transaction to the recipient', () => {
|
||||
beforeEach(() => {
|
||||
tp.clear();
|
||||
senderWallet.createCoinTransaction(wallet.publicKey, addBalance, 20,9014,'temp','123abc',bc, tp);
|
||||
bc.addBlock(tp.paymenttransactions);
|
||||
senderWallet.createTransaction(wallet.publicKey, addBalance, bc, tp);
|
||||
bc.addBlock(tp.transactions);
|
||||
});
|
||||
|
||||
it('calculate the recipient balance only using transactions since its most recent one', () => {
|
||||
|
|
88
wallet/metadata.js
Normal file
88
wallet/metadata.js
Normal file
|
@ -0,0 +1,88 @@
|
|||
const ChainUtil = require('../chain-util');
|
||||
|
||||
class Metadata {
|
||||
constructor() {
|
||||
this.id = null;
|
||||
this.Signiture = null;
|
||||
this.Name = null;
|
||||
this.Geo = null;
|
||||
// this.GeospatialLocation = [];
|
||||
// this.Owenership = null;
|
||||
// this.Cost = null;
|
||||
// this.Identifications = null;
|
||||
// this.Integration = null;
|
||||
|
||||
this.IP_URL = null;
|
||||
this.Topic_Token = null;
|
||||
this.Permission = null;
|
||||
this.RequestDetail = null;
|
||||
this.OrgOwner = null;
|
||||
this.DepOwner = null;
|
||||
this.PrsnOwner = null;
|
||||
this.MetaHash = null;
|
||||
this.PaymentPerKbyte = null;
|
||||
this.PaymentPerMinute = null;
|
||||
this.Protocol = null;
|
||||
this.MessageAttributes= {};
|
||||
this.Interval = null;
|
||||
this.FurtherDetails = null;
|
||||
this.SSNmetadata = null;
|
||||
}
|
||||
|
||||
static MetadataOfIoTDevice(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes, Intrval, FurtherDetails, SSNmetadata) {
|
||||
const metadata = new this();
|
||||
metadata.id = ChainUtil.id();
|
||||
metadata.Name = Name;
|
||||
metadata.Geo = Geo;
|
||||
metadata.IP_URL = IP_URL;
|
||||
metadata.Topic_Token = Topic_Token;
|
||||
metadata.Permission = Permission;
|
||||
metadata.RequestDetail = RequestDetail
|
||||
metadata.OrgOwner = OrgOwner;
|
||||
metadata.DepOwner = DepOwner;
|
||||
metadata.PrsnOwner = PrsnOwner;
|
||||
metadata.PaymentPerKbyte = PaymentPerKbyte ;
|
||||
metadata.PaymentPerMinute = PaymentPerMinute;
|
||||
metadata.Protocol = Protocol;
|
||||
metadata.MessageAttributes = MessageAttributes;
|
||||
// metadata.MessageAttributes['DeviceID'] = metadata.id;
|
||||
// metadata.MessageAttributes['DeviceName'] = Name;
|
||||
// metadata.MessageAttributes['Sensors'] =[{"SensorName":"","Value":"" , "Unit":""}];
|
||||
// metadata.MessageAttributes['TimeStamp'] = "";
|
||||
metadata.Interval = Intrval;
|
||||
metadata.FurtherDetails = FurtherDetails;
|
||||
metadata.SSNmetadata = SSNmetadata;
|
||||
metadata.MetaHash = ChainUtil.hash(SSNmetadata);
|
||||
Metadata.signMetadata(metadata, senderWallet);
|
||||
return metadata;
|
||||
}
|
||||
|
||||
static newMetadata(senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission, RequestDetail,
|
||||
OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol, MessageAttributes,
|
||||
Interval, FurtherDetails, SSNmetadata){
|
||||
return Metadata.MetadataOfIoTDevice(senderWallet, Name,Geo ,IP_URL , Topic_Token, Permission,
|
||||
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte, PaymentPerMinute, Protocol,
|
||||
MessageAttributes, Interval, FurtherDetails, SSNmetadata
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
static signMetadata (metadata, senderWallet) {
|
||||
metadata.Signiture = {
|
||||
timestamp: Date.now(),
|
||||
address: senderWallet.publicKey,
|
||||
signature: senderWallet.sign(ChainUtil.hash(metadata.SSNmetadata))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static verifyMetadata(metadata) {
|
||||
return ChainUtil.verifySignature(
|
||||
metadata.Signiture.address,
|
||||
metadata.Signiture.signature,
|
||||
ChainUtil.hash(metadata.SSNmetadata)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Metadata;
|
109
wallet/metadata.test.js
Normal file
109
wallet/metadata.test.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
const Transaction = require('./transaction');
|
||||
const Metadata = require('./metadata');
|
||||
const Wallet = require('./index');
|
||||
const { MINING_REWARD } = require('../config');
|
||||
|
||||
describe('Transaction & Metadata', () => {
|
||||
let transaction, metadata, wallet, recipient, amount,
|
||||
senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission,
|
||||
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte,
|
||||
PaymentPerMinute, Protocol, MessageAttributes, Interval,
|
||||
FurtherDetails, SSNmetadata;
|
||||
|
||||
beforeEach(() => {
|
||||
wallet = new Wallet();
|
||||
amount = 50;
|
||||
recipient = 'r3c1p13nt';
|
||||
senderWallet = new Wallet();
|
||||
Name = 'IoT_Lab_Temp_Sensor'
|
||||
Geo = [1.045,0.0135]
|
||||
IP_URL = 'www.IoT-locationbar.com/sensors/temp'
|
||||
Topic_Token = 'ACCESS_TOKEN'
|
||||
Permission = 'Public'
|
||||
RequestDetail = 'Null'
|
||||
OrgOwner = 'Swinburne_University'
|
||||
DepOwner = 'Computer_Science'
|
||||
PrsnOwner = 'Anas_Dawod'
|
||||
PaymentPerKbyte = 10
|
||||
PaymentPerMinute = 5
|
||||
Protocol = 'MQTT'
|
||||
MessageAttributes = 'null'
|
||||
Interval = 10
|
||||
FurtherDetails = 'null'
|
||||
SSNmetadata = 'null'
|
||||
transaction = Transaction.newTransaction(wallet, recipient, amount);
|
||||
metadata = Metadata.newMetadata(senderWallet,Name,Geo ,IP_URL , Topic_Token, Permission,
|
||||
RequestDetail, OrgOwner, DepOwner,PrsnOwner, PaymentPerKbyte,
|
||||
PaymentPerMinute, Protocol, MessageAttributes, Interval,
|
||||
FurtherDetails, SSNmetadata)
|
||||
});
|
||||
|
||||
it('outputs the `amount` subtracted from the wallet balance', () => {
|
||||
expect(transaction.outputs.find(output => output.address === wallet.publicKey).amount)
|
||||
.toEqual(wallet.balance - amount);
|
||||
});
|
||||
|
||||
it('outputs the `amount` added to the recipient', () => {
|
||||
expect(transaction.outputs.find(output => output.address === recipient).amount)
|
||||
.toEqual(amount);
|
||||
});
|
||||
|
||||
it('inputs the balance of the wallet', () => {
|
||||
expect(transaction.input.amount).toEqual(wallet.balance);
|
||||
});
|
||||
|
||||
it('validates a valid transaction', () => {
|
||||
expect(Transaction.verifyTransaction(transaction)).toBe(true);
|
||||
});
|
||||
|
||||
it('validates a valid metadata', () => {
|
||||
expect(Metadata.verifyMetadata(metadata)).toBe(true);
|
||||
});
|
||||
|
||||
it('invalidates a corrupt transaction', () => {
|
||||
transaction.outputs[0].amount = 50000;
|
||||
expect(Transaction.verifyTransaction(transaction)).toBe(false);
|
||||
});
|
||||
|
||||
describe('transacting with an amount that exceeds the balance', () => {
|
||||
beforeEach(() => {
|
||||
amount = 50000;
|
||||
transaction = Transaction.newTransaction(wallet, recipient, amount);
|
||||
});
|
||||
|
||||
it('does not create the transaction', () => {
|
||||
expect(transaction).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
|
||||
describe('and updating a transaction', () => {
|
||||
let nextAmount, nextRecipient;
|
||||
|
||||
beforeEach(() => {
|
||||
nextAmount = 20;
|
||||
nextRecipient = 'n3xt-4ddr355';
|
||||
transaction = transaction.update(wallet, nextRecipient, nextAmount);
|
||||
});
|
||||
|
||||
it(`subtracts the next amount from the sender's output`, () => {
|
||||
expect(transaction.outputs.find(output => output.address === wallet.publicKey).amount)
|
||||
.toEqual(wallet.balance - amount - nextAmount);
|
||||
});
|
||||
|
||||
it('outputs an amount for the next recipient', () => {
|
||||
expect(transaction.outputs.find(output => output.address === nextRecipient).amount)
|
||||
.toEqual(nextAmount);
|
||||
});
|
||||
});
|
||||
|
||||
describe('creating a reward transaction', () => {
|
||||
beforeEach(() => {
|
||||
transaction = Transaction.rewardTransaction(wallet, Wallet.blockchainWallet());
|
||||
});
|
||||
|
||||
it(`reward the miner's wallet`, () => {
|
||||
expect(transaction.outputs.find(output => output.address === wallet.publicKey).amount)
|
||||
.toEqual(MINING_REWARD);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,118 +1,73 @@
|
|||
const PaymntTransaction = require('./CoinTransaction');
|
||||
const MetaDataTransaction = require('./MetaDataTransaction');
|
||||
//const CompTransaction = require('./CompTransaction');
|
||||
//const IntegrationTransaction = require('./IntegrationTransaction');
|
||||
const { MaxNumOfPaymentTransactions, MaxNumOfMetadataTransactions,
|
||||
MaxNumOfCompTransactions, MaxNumOfIntegrationTransactions}
|
||||
= require('../config');
|
||||
const Transaction = require('../wallet/transaction');
|
||||
const Metadata = require('../wallet/metadata')
|
||||
class TransactionPool {
|
||||
constructor() {
|
||||
this.paymenttransactions = [];
|
||||
this.metaDataTransactions =[];
|
||||
this.comptransactions = [];
|
||||
this.integrationTransactions =[];
|
||||
this.transactions = [];
|
||||
this.metadataS =[];
|
||||
}
|
||||
updateOrAddPaymentTransaction(paymenttransaction) {
|
||||
let paymenttransactionWithId = this.paymenttransactions.find(t =>
|
||||
t.id === paymenttransaction.id);
|
||||
if (paymenttransactionWithId) {
|
||||
this.paymenttransactions[this.paymenttransactions.indexOf
|
||||
(paymenttransactionWithId)] = paymenttransaction;
|
||||
} else {
|
||||
this.paymenttransactions.push(paymenttransaction);
|
||||
}
|
||||
}
|
||||
updateOrAddMetaDataTransaction(metaDataTransaction) {
|
||||
let metaDataTransactionWithId = this.metaDataTransactions.find(t =>
|
||||
t.id === metaDataTransaction.id);
|
||||
if (metaDataTransactionWithId) {
|
||||
this.metaDataTransactions[this.metaDataTransactions.indexOf
|
||||
(metaDataTransactionWithId)] = metaDataTransaction;
|
||||
|
||||
updateOrAddTransaction(transaction) {
|
||||
let transactionWithId = this.transactions.find(t => t.id === transaction.id);
|
||||
|
||||
if (transactionWithId) {
|
||||
this.transactions[this.transactions.indexOf(transactionWithId)] = transaction;
|
||||
} else {
|
||||
this.metaDataTransactions.push(metaDataTransaction);
|
||||
this.transactions.push(transaction);
|
||||
}
|
||||
}
|
||||
updateOrAddCompTransaction(comptransaction) {
|
||||
let comptransactionWithId = this.comptransactions.find(t =>
|
||||
t.id === comptransaction.id);
|
||||
if (comptransactionWithId) {
|
||||
this.comptransactions[this.comptransactions.indexOf
|
||||
(comptransactionWithId)] = comptransaction;
|
||||
} else {
|
||||
this.comptransactions.push(comptransaction);
|
||||
} }
|
||||
updateOrAddIntegrationTransaction(integrationTransaction) {
|
||||
let integrationTransactionWithId = this.integrationTransaction.find(
|
||||
t => t.id === integrationTransaction.id);
|
||||
if (integrationTransactionWithId) {
|
||||
this.integrationTransactions[this.integrationTransactions.indexOf
|
||||
(integrationTransactionWithId)] = integrationTransaction;
|
||||
} else {
|
||||
this.integrationTransactions.push(integrationTransaction);
|
||||
}
|
||||
|
||||
AddMetadata(metadata) {
|
||||
// let metadataWithId = this.metadataS.find(t => t.id === metadata.id);
|
||||
|
||||
// if (metadataWithId) {
|
||||
// this.metaDataS[this.metadataS.indexOf(metadataWithId)] = metadata;
|
||||
// } else {
|
||||
this.metadataS.push(metadata);
|
||||
// }
|
||||
}
|
||||
existingPaymentTransaction(address) {
|
||||
return this.paymenttransactions.find(t =>
|
||||
t.input.address === address); }
|
||||
existingMetaDataTransaction(address) {
|
||||
return this.metaDataTransactions.find(t =>
|
||||
t.Signiture.address === address);}
|
||||
existingCompTransaction(address) {
|
||||
return this.comptransactions.find(t =>
|
||||
t.input.address === address); }
|
||||
existingIntegrationTransaction(address) {
|
||||
return this.integrationTransactions.find(t =>
|
||||
t.Signiture.address === address);}
|
||||
validPaymentTransactions() {
|
||||
return this.paymenttransactions.filter(paymenttransaction => {
|
||||
const outputTotal = paymenttransaction.outputs.reduce(
|
||||
(total, output) => {
|
||||
|
||||
existingTransaction(address) {
|
||||
return this.transactions.find(t => t.input.address === address);
|
||||
}
|
||||
|
||||
existingMetadata(address) {
|
||||
return this.metadataS.find(t => t.Signiture.address === address);
|
||||
}
|
||||
|
||||
validTransactions() {
|
||||
return this.transactions.filter(transaction => {
|
||||
const outputTotal = transaction.outputs.reduce((total, output) => {
|
||||
return total + output.amount;
|
||||
}, 0);
|
||||
if (paymenttransaction.input.amount !== outputTotal) {
|
||||
console.log(`Invalid transaction from
|
||||
${paymenttransaction.input.address}.`);
|
||||
return;}
|
||||
if (!PaymentTransaction.verifyPaymentTransaction(
|
||||
paymenttransaction)) {
|
||||
console.log(`Invalid signature from
|
||||
${paymenttransaction.input.address}.`);
|
||||
return;}
|
||||
return paymenttransaction;
|
||||
|
||||
if (transaction.input.amount !== outputTotal) {
|
||||
console.log(`Invalid transaction from ${transaction.input.address}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Transaction.verifyTransaction(transaction)) {
|
||||
console.log(`Invalid signature from ${transaction.input.address}.`);
|
||||
return;
|
||||
}
|
||||
|
||||
return transaction;
|
||||
});
|
||||
}
|
||||
validMetaDataTransactions(){
|
||||
if (!MetaDataTransaction.verifyMetaDataTransaction(
|
||||
metaDataTransaction)) {
|
||||
console.log(`Invalid signature from
|
||||
${metaDataTransaction.Signiture.address}.`);
|
||||
return;
|
||||
}
|
||||
return metaDataTransaction;
|
||||
|
||||
validMetadataS(){
|
||||
return this.metadataS.filter(metadata => {
|
||||
if (!Metadata.verifyMetadata(metadata)) {
|
||||
console.log(`Invalid signature from ${metadata.Signiture.address}.`);
|
||||
return;
|
||||
}
|
||||
return metadata;
|
||||
});
|
||||
}
|
||||
validCompTransactions(){
|
||||
if (!CompTransaction.verifyCompTransaction(
|
||||
CompTransaction)) {
|
||||
console.log(`Invalid signature from
|
||||
${CompTransaction.Signiture.address}.`);
|
||||
return;
|
||||
}
|
||||
return compTransaction;
|
||||
}
|
||||
validIntegrationTransactions(){
|
||||
if (!IntegrationTransaction.verifyIntegrationTransaction(
|
||||
integrationTransaction)) {
|
||||
console.log(`Invalid signature from
|
||||
${integrationTransaction.Signiture.address}.`);
|
||||
return;
|
||||
}
|
||||
return integrationTransaction;
|
||||
}
|
||||
clearAll() {
|
||||
this.cointransactions = [];
|
||||
this.metaDataTransactions = [];
|
||||
this.comptransactions = [];
|
||||
this.integrationTransactions = [];
|
||||
|
||||
clear() {
|
||||
this.transactions = [];
|
||||
this.metadataS = [];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = TransactionPool;
|
|
@ -1,44 +1,72 @@
|
|||
const TransactionPool = require('./transaction-pool');
|
||||
const Transaction = require('./Cointransaction');
|
||||
const Transaction = require('./transaction');
|
||||
const Metadata = require('./metadata')
|
||||
const Wallet = require('./index');
|
||||
const Blockchain = require('../blockchain');
|
||||
|
||||
describe('TransactionPool', () => {
|
||||
let tp, wallet, transaction, bc;
|
||||
let tp, wallet, transaction, metadata, bc;
|
||||
|
||||
beforeEach(() => {
|
||||
tp = new TransactionPool();
|
||||
wallet = new Wallet();
|
||||
wallet2 =new Wallet();
|
||||
bc = new Blockchain();
|
||||
transaction = wallet.createCoinTransaction('r4nd-4dr355', 30,20,9014,'temp','123abc', bc, tp);
|
||||
transaction = wallet.createTransaction('r4nd-4dr355', 30, bc, tp);
|
||||
// senderWallet = 'address';
|
||||
// Name = 'IoT_Lab_Temp_Sensor'
|
||||
// Geo = [1.045,0.0135]
|
||||
// IP_URL = 'www.IoT-locationbar.com/sensors/temp'
|
||||
// Topic_Token = 'ACCESS_TOKEN'
|
||||
// Permission = 'Public'
|
||||
// RequestDetail = 'Null'
|
||||
// OrgOwner = 'Swinburne_University'
|
||||
// DepOwner = 'Computer_Science'
|
||||
// PrsnOwner = 'Anas_Dawod'
|
||||
// PaymentPerKbyte = 10
|
||||
// PaymentPerMinute = 5
|
||||
// Protocol = 'MQTT'
|
||||
// MessageAttributes = 'null'
|
||||
// Interval = 10
|
||||
// FurtherDetails = 'null'
|
||||
// SSNmetadata = 'null'
|
||||
|
||||
metadata = wallet.createMetadata('IoT_Lab_Temp_Sensor',[1.045,0.0135],"www.IoT-locationbar.com/sensors/temp" ,'ACCESS_TOKEN' , 'Public',
|
||||
'Null', 'Swinburne_University', 'Computer_Science','Anas_Dawod', 10,
|
||||
5, 'MQTT', 'null', 10,
|
||||
'FurtherDetails', 'SSNmetadata',tp);
|
||||
});
|
||||
|
||||
it('adds a transaction to the pool', () => {
|
||||
expect(tp.paymenttransactions.find(t => t.id === transaction.id)).toEqual(transaction);
|
||||
expect(tp.transactions.find(t => t.id === transaction.id)).toEqual(transaction);
|
||||
});
|
||||
it('adds a metadata to the pool', () => {
|
||||
expect(tp.metadataS.find(t => t.id === metadata.id)).toEqual(metadata);
|
||||
});
|
||||
|
||||
it('updates a transaction in the pool', () => {
|
||||
const oldTransaction = JSON.stringify(transaction);
|
||||
const newTransaction = transaction.update(wallet, 'foo-4ddr355', 40,20,9014,'temp','123abc');
|
||||
tp.updateOrAddPaymentTransaction(newTransaction);
|
||||
const newTransaction = transaction.update(wallet, 'foo-4ddr355', 40);
|
||||
tp.updateOrAddTransaction(newTransaction);
|
||||
|
||||
expect(JSON.stringify(tp.paymenttransactions.find(t => t.id === newTransaction.id)))
|
||||
expect(JSON.stringify(tp.transactions.find(t => t.id === newTransaction.id)))
|
||||
.not.toEqual(oldTransaction);
|
||||
});
|
||||
|
||||
it('clears transactions', () => {
|
||||
it('clears transactions and metadata', () => {
|
||||
tp.clear();
|
||||
expect(tp.paymenttransactions).toEqual([]);
|
||||
expect(tp.transactions).toEqual([]);
|
||||
expect(tp.metadataS).toEqual([]);
|
||||
});
|
||||
|
||||
describe('mixing valid and corrupt transactions', () => {
|
||||
let validTransactions;
|
||||
|
||||
|
||||
beforeEach(() => {
|
||||
validTransactions = [...tp.paymenttransactions];
|
||||
validTransactions = [...tp.transactions];
|
||||
for (let i=0; i<6; i++) {
|
||||
wallet = new Wallet();
|
||||
transaction = wallet.createCoinTransaction('r4nd-4dr355', 30,20,9014,'temp','123abc', bc, tp);
|
||||
transaction = wallet.createTransaction('r4nd-4dr355', 30, bc, tp);
|
||||
if (i%2==0) {
|
||||
transaction.input.amount = 99999;
|
||||
} else {
|
||||
|
@ -48,7 +76,7 @@ describe('TransactionPool', () => {
|
|||
});
|
||||
|
||||
it('shows a difference between valid and corrupt transactions', () => {
|
||||
expect(JSON.stringify(tp.paymenttransactions)).not.toEqual(JSON.stringify(validTransactions));
|
||||
expect(JSON.stringify(tp.transactions)).not.toEqual(JSON.stringify(validTransactions));
|
||||
});
|
||||
|
||||
it('grabs valid transactions', () => {
|
||||
|
|
69
wallet/transaction.js
Normal file
69
wallet/transaction.js
Normal file
|
@ -0,0 +1,69 @@
|
|||
const ChainUtil = require('../chain-util');
|
||||
const { MINING_REWARD } = require('../config');
|
||||
|
||||
class Transaction {
|
||||
constructor() {
|
||||
this.id = ChainUtil.id();
|
||||
this.input = null;
|
||||
this.outputs = [];
|
||||
}
|
||||
|
||||
update(senderWallet, recipient, amount) {
|
||||
const senderOutput = this.outputs.find(output => output.address === senderWallet.publicKey);
|
||||
|
||||
if (amount > senderOutput.amount) {
|
||||
console.log(`Amount: ${amount} exceeds balance.`);
|
||||
return;
|
||||
}
|
||||
|
||||
senderOutput.amount = senderOutput.amount - amount;
|
||||
this.outputs.push({ amount, address: recipient });
|
||||
Transaction.signTransaction(this, senderWallet);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
static transactionWithOutputs(senderWallet, outputs) {
|
||||
const transaction = new this();
|
||||
transaction.outputs.push(...outputs);
|
||||
Transaction.signTransaction(transaction, senderWallet);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
static newTransaction(senderWallet, recipient, amount) {
|
||||
if (amount > senderWallet.balance) {
|
||||
console.log(`Amount: ${amount} exceeds balance.`);
|
||||
return;
|
||||
}
|
||||
|
||||
return Transaction.transactionWithOutputs(senderWallet, [
|
||||
{ amount: senderWallet.balance - amount, address: senderWallet.publicKey },
|
||||
{ amount, address: recipient }
|
||||
]);
|
||||
}
|
||||
|
||||
static rewardTransaction(minerWallet, blockchainWallet) {
|
||||
return Transaction.transactionWithOutputs(blockchainWallet, [{
|
||||
amount: MINING_REWARD, address: minerWallet.publicKey
|
||||
}]);
|
||||
}
|
||||
|
||||
static signTransaction(transaction, senderWallet) {
|
||||
transaction.input = {
|
||||
timestamp: Date.now(),
|
||||
amount: senderWallet.balance,
|
||||
address: senderWallet.publicKey,
|
||||
signature: senderWallet.sign(ChainUtil.hash(transaction.outputs))
|
||||
}
|
||||
}
|
||||
|
||||
static verifyTransaction(transaction) {
|
||||
return ChainUtil.verifySignature(
|
||||
transaction.input.address,
|
||||
transaction.input.signature,
|
||||
ChainUtil.hash(transaction.outputs)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Transaction;
|
|
@ -1,4 +1,4 @@
|
|||
const Transaction = require('./Cointransaction');
|
||||
const Transaction = require('./transaction');
|
||||
const Wallet = require('./index');
|
||||
const { MINING_REWARD } = require('../config');
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue