Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve burrow 0.30.2 support #804

Merged
merged 1 commit into from
Apr 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 124 additions & 51 deletions packages/caliper-burrow/lib/burrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
'use strict';

const fs = require('fs');
const monax = require('@monax/burrow');
const burrowTS = require('@hyperledger/burrow');
const { BlockchainInterface, CaliperUtils, ConfigUtil, TxStatus } = require('@hyperledger/caliper-core');
const logger = CaliperUtils.getLogger('burrow.js');

Expand Down Expand Up @@ -91,33 +91,32 @@ class Burrow extends BlockchainInterface {
*/
async installSmartContract() {
let connection = burrowConnect(this.config);
let options = { objectReturn: true };
let burrow = monax.createInstance(connection.url, connection.account, options);

let burrow = new burrowTS.Burrow(connection.url, connection.account);
let data, abi, bytecode, contract;
try {
data = JSON.parse(fs.readFileSync(CaliperUtils.resolvePath(this.config.contract.path)).toString());
abi = data.Abi;
bytecode = data.Evm.Bytecode.Object;

contract = await burrow.contracts.deploy(abi, bytecode);
logger.info(`Contract: ${contract.address}`);
logger.info('contract address:',contract.address);

} catch (err) {
logger.error('deploy contract error',err);
throw err;
}

let setPayload = {
Input: {
Address: Buffer.from(connection.account, 'hex'),
Amount: 50000
},
Name: 'DOUG',
Data: contract.address,
Fee: 5000
};

// this stores the contract address in a namereg for easy retrieval
return burrow.transact.NameTxSync(setPayload);
return new Promise(function (resolve, reject) {
burrow.namereg.set('DOUG', contract.address, 50000, 5000,(err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
});
}).then(function (result) {
return result;
},err => {
logger.info('namereg reject error:',err);
});
}

/**
Expand All @@ -129,18 +128,29 @@ class Burrow extends BlockchainInterface {
*/
async getContext(name, args) {
let context = this.config.burrow.context;

if (typeof context === 'undefined') {

let connection = burrowConnect(this.config);
let options = { objectReturn: true };
let burrow = monax.createInstance(connection.url, connection.account, options);

let burrow = new burrowTS.Burrow(connection.url, connection.account);
let contractMetaData = JSON.parse(fs.readFileSync(CaliperUtils.resolvePath(this.config.contract.path)).toString());
// get the contract address from the namereg
let address = (await burrow.query.GetName({ Name: 'DOUG' })).Data;
context = { account: connection.account, address: address, burrow: burrow };
return new Promise(function (resolve, reject) {
burrow.namereg.get('DOUG', (err, result) => {
if(err){
reject(err);
}else{
let address=result.getData();
let contract = new burrowTS.Contract(contractMetaData.Abi,contractMetaData.Evm.Bytecode.Object,address,burrow);
context = { account: connection.account, address: address,contract:contract, burrow: burrow };
resolve(context);
}
});
}).then(function(result){
return Promise.resolve(result);
},err => {
logger.info('getContext reject error:',err);
Promise.reject(err);
});
}

return Promise.resolve(context);
}

Expand All @@ -152,20 +162,45 @@ class Burrow extends BlockchainInterface {
async releaseContext(context) {
// nothing to do
}

/**
* Query state from the ledger using a smart contract
* @param {Object} context context object
* @param {String} contractID identity of the contract
* @param {String} contractVer version of the contract
* @param {Array} args array of JSON formatted arguments
* @param {Number} timeout request timeout, in seconds
* @return {Promise} query response object
*/
async querySmartContract(context, contractID, contractVer, args, timeout) {
let promises = [];
args.forEach((item, index) => {
promises.push(this.doInvoke(context, contractID, contractVer, item, timeout));
});
return await Promise.all(promises);
}
/**
* Invoke a smart contract.
* @param {Object} context Context object.
* @param {String} contractID Identity of the contract.
* @param {String} contractVer Version of the contract.
* @param {Array} args Array of JSON formatted arguments for multiple transactions.
* @param {Array} args eg {'verb':'invoke','funName': 'getInt','funArgs': []}
* @param {Number} timeout Request timeout, in seconds.
* @return {Promise<object>} The promise for the result of the execution.
*/
async invokeSmartContract(context, contractID, contractVer, args, timeout) {
let promises = [];
args.forEach((item, index) => {
promises.push(this.burrowTransaction(context, contractID, contractVer, item, timeout));
if(item.verb==='transfer'){
promises.push(this.acccountTransfer(context, item, timeout));
}else if(item.verb==='invoke'){
if (!item.hasOwnProperty('funName')) {
return Promise.reject(new Error(' missed argument:funName '));
}
if (!item.hasOwnProperty('funArgs')) {
return Promise.reject(new Error(' missed argument:funArgs '));
}
promises.push(this.doInvoke(context, contractID, contractVer, item, timeout));
}
});
return await Promise.all(promises);
}
Expand All @@ -175,35 +210,69 @@ class Burrow extends BlockchainInterface {
* @param {Object} context Context object.
* @param {String} contractID Identity of the contract.
* @param {String} contractVer Version of the contract.
* @param {Array} args Array of JSON formatted arguments for multiple transactions.
* @param {Object} arg eg:{'funName': 'setInt','funArgs': [1000]}
* @param {Number} timeout Request timeout, in seconds.
* @return {Promise<TxStatus>} Result and stats of the transaction invocation.
*/
async burrowTransaction(context, contractID, contractVer, args, timeout) {
let status = new TxStatus(args.account);
async doInvoke(context, contractID, contractVer, arg, timeout) {
let status = new TxStatus();
if (context.engine) {
context.engine.submitCallback(1);
}

let tx = {
Input: {
Address: Buffer.from(context.account, 'hex'),
Amount: args.money
},
Address: Buffer.from(context.address, 'hex'),
GasLimit: 5000,
Fee: 5000
};

try {
let execution = await context.burrow.transact.CallTxSync(tx);
status.SetID(execution.TxHash.toString());
//let contract = await context.burrow.contracts.address(context.address);
//Todo: can't get contract with burrow.contracts.address
return context.contract[arg.funName](...arg.funArgs).then(function (result) {
status.SetStatusSuccess();
} catch (err) {
return status;
},err => {
status.SetStatusFail();
logger.info('invoke reject error:',err);
return status;
});
}
/**
* Submit a transaction to the burrow daemon with the specified options.
* @param {Object} context Context object.
* @param {String} arg {toAccount:'',money:''}
* @param {Number} timeout Request timeout, in seconds.
* @return {Promise<TxStatus>} Result and stats of the transaction invocation.
*/
async acccountTransfer(context, arg, timeout) {
let account=context.account;
let toAccount=arg.toAccount;
let amount= parseFloat(arg.money);
let status = new TxStatus(toAccount);
if (context.engine) {
context.engine.submitCallback(1);
}

return status;
let inputTx=new burrowTS.payload.TxInput();
inputTx.setAddress(Buffer.from(account, 'hex'));
inputTx.setAmount(amount);

let sendTx=new burrowTS.payload.SendTx();
sendTx.addInputs(inputTx);
let outputTx=new burrowTS.payload.TxInput();
outputTx.setAddress(Buffer.from(toAccount, 'hex'));
outputTx.setAmount(amount);
sendTx.addOutputs(outputTx);
return new Promise(function (resolve, reject) {
context.burrow.tc.sendTxSync(sendTx, (err, data) => {
if(err){
status.SetStatusFail();
reject(err);
}else{
status.SetID(data.getReceipt().getTxhash_asB64());
status.SetStatusSuccess();
resolve(data);
}
});
}).then(function (result) {
return status;
},err => {
logger.info('sendTx reject error:',err);
return status;
});
}

/**
Expand All @@ -220,9 +289,10 @@ class Burrow extends BlockchainInterface {
if (context.engine) {
context.engine.submitCallback(1);
}

return new Promise(function (resolve, reject) {
context.burrow.query.GetAccount({ Address: Buffer.from(context.address, 'hex') }, function (error, data) {
let getAccountParam=new burrowTS.rpcquery.GetAccountParam();
getAccountParam.setAddress(Buffer.from(context.address, 'hex'));
context.burrow.qc.getAccount(getAccountParam, function (error, data) {
if (error) {
status.SetStatusFail();
reject(error);
Expand All @@ -233,6 +303,9 @@ class Burrow extends BlockchainInterface {
});
}).then(function (result) {
return status;
},error => {
logger.info('queryState reject error:',error);
return status;
});
}

Expand Down
6 changes: 4 additions & 2 deletions packages/caliper-burrow/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@
"npm": ">=5.6.0"
},
"dependencies": {
"@hyperledger/caliper-core": "0.3.1-unstable"
"@hyperledger/caliper-core": "0.3.1-unstable",
"google-protobuf": "^3.11.4"
},
"devDependencies": {
"@monax/burrow": "0.23.0",
"@hyperledger/burrow": "0.30.2",
"google-protobuf": "^3.11.4",
"chai": "^3.5.0",
"eslint": "^5.16.0",
"mocha": "3.4.2",
Expand Down
4 changes: 3 additions & 1 deletion packages/caliper-cli/lib/lib/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ sut:
latest: *sawtooth-latest

burrow:
0.23.0: &burrow-latest
0.23.0:
packages: [ '@monax/burrow@0.23.0' ]
0.30.2: &burrow-latest
packages: [ '@hyperledger/burrow@0.30.2' ]
latest: *burrow-latest

iroha:
Expand Down