How to call a chaincode from another chaincode deployed on two different organization peers connected using a single channel in hyperledger-fabric? - block

I wrote a chaincode1(deployed on one peer of ORG1) which accepts the details from the user and store it into the ledger. Now I want to write a chaincode2(deployed on a peer of ORG2) which takes some data from the chaincode1 for computation. This chaincode2 should be called by chaincode1 with specific details required for computation.
How can i achieve this thing and where should I test it?

To start with, there are few preconditions such as:
If you'd like to have chaincode1 to invoke chaincode2, you need both chaincodes to be installed the same peer and
Need to make sure this peer part of both channels
Next, you need to leverage following API:
// InvokeChaincode locally calls the specified chaincode `Invoke` using the
// same transaction context; that is, chaincode calling chaincode doesn't
// create a new transaction message.
// If the called chaincode is on the same channel, it simply adds the called
// chaincode read set and write set to the calling transaction.
// If the called chaincode is on a different channel,
// only the Response is returned to the calling chaincode; any PutState calls
// from the called chaincode will not have any effect on the ledger; that is,
// the called chaincode on a different channel will not have its read set
// and write set applied to the transaction. Only the calling chaincode's
// read set and write set will be applied to the transaction. Effectively
// the called chaincode on a different channel is a `Query`, which does not
// participate in state validation checks in subsequent commit phase.
// If `channel` is empty, the caller's channel is assumed.
InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response
Here is an example:
chainCodeArgs := util.ToChaincodeArgs("arg1", "arg2")
response := stub.InvokeChaincode("chaincodeName", chainCodeArgs, "channelID")
if response.Status != shim.OK {
return shim.Error(response.Message)
}

Here is the function which can be used to invoke a chaincode from another chaincode
func (stub *TestAPIStub) InvokeChaincode(chaincode1 string, args [][]byte, channel string) pb.Response {
return pb.Response{}
}
You can refer this document to understand how a smart contract calls or "chaincode" calls another smart contract.

Related

What is the difference between debot fetch and debot start?

I have few different options in the command line: fetch and start. What is the difference between them?
Here https://github.com/tonlabs/tonos-cli/pull/162 Free TON guys says that
"added debot start command as synonym for fetch command."
BUT here https://github.com/tonlabs/TON-SDK/blob/master/docs/mod_debot.md#start thay say
start - Starts the DeBot.
Downloads debot smart contract from blockchain and switches it to context zero.
This function must be used by Debot Browser to start a dialog with debot. While the function is executing, several Browser Callbacks can be called, since the debot tries to display all actions from the context 0 to the user.
When the debot starts SDK registers BrowserCallbacks AppObject. Therefore when debote.remove is called the debot is being deleted and the callback is called with finish=true which indicates that it will never be used again.
type ParamsOfStart = {
debot_handle: DebotHandle
}
function start(
params: ParamsOfStart,
): Promise<void>;
and below https://github.com/tonlabs/TON-SDK/blob/master/docs/mod_debot.md#fetch
fetch - Fetches DeBot metadata from blockchain.
Downloads DeBot from blockchain and creates and fetches its metadata.
type ParamsOfFetch = {
address: string
}
type ResultOfFetch = {
info: DebotInfo
}
function fetch(
params: ParamsOfFetch,
): Promise<ResultOfFetch>;
here in tg chat https://t.me/freeton_dev_exp You can find SDK developers

Why is .call() necessary when I want to see returned values from a smart contract function?

In my contract I have this function (solc 0.8.4):
function makeDecision(address person) external returns (string memory name, bool approved) {
require(msg.sender == loanOfficer, "Only the loan officer can initiate a decision.");
require(bytes(applicants[person].name).length != 0, "That person is not in the pool of applicants.");
if (applicants[person].credScore > 650 && applicants[person].credAge > 5) {
applicants[person].approved = true;
}
return (applicants[person].name, applicants[person].approved);
}
When I go into my truffle console and call my function this way loanContract.makeDecision(accounts[1]) everything works fine, but I get a tx receipt as the response.
When I call my function this way via truffle console loanContract.makeDecision.call(accounts[1]) I get the expected response from my function. I am wanting an explanation that tells me why this difference in response occurs so that I understand what is going on on a deeper level. I hate using things without understanding why they work.
If it helps, my contract (which is named LoanDisbursement) was initialized in the console like so: let loanContract = await LoanDisbursement.deployed() and my accounts variable: let accounts = await web3.eth.getAccounts()
any tips would help since I am still learning and diving into this ecosystem. I've not been able to find any decent documentation on this functionality as of yet. Thanks.
Truffle contract functions create a transaction - and return the transaction data.
The call function doesn't create a transaction, it just makes a call. So it cannot return transaction receipt and the authors of Truffle decided to return the function value instead.
Without transaction, the state of your contract is not changed. Which is probably not what you want, and you should always create a transaction when you need to save state changes to the blockchain.
Truffle doesn't return the function value when you're creating a transaction. Using Truffle, there are two approaches that they recommend:
Reading event logs that the transaction produced
Add an event to your function emit MadeDecision(applicants[person].name, applicants[person].approved);, and then access it in your JS code in result.logs.
Calling a getter in a subsequent call.
Tx setValue(5) and then call getValue(). Or in your case:
Tx makeDecision(0x123) and then call applicants[0x123] (assuming applicants is public).

Scan for rabbit exchanges from iOS

I'm trying to write something for my iOS app, using RMQClient that scans for existing exchanges on a rabbitmq server. I came up with this so far.
class AMQPExchangeScanner {
static func scan() {
let connection:RMQConnection = RMQConnection(uri: "amqp://user:user#abc.def.com:5672", delegate: RMQConnectionDelegateLogger())
connection.start()
for exchangeName in Foo.pastExchanges() {
let channel = connection.createChannel()
let exchange = channel.fanout(exchangeName, options: .passive)
"scan \(exchangeName) \(exchange)".print()
channel.close()
}
}
}
I'm not sure how to determine if the exchange actually exists though. The print() statement prints exchange objects. I get a whole bunch of output in the console. I had hoped that I would get back an optional so I could do something like
if let exchange... {
}
But that doesn't appear to be the case. How do I programmatically check if the exchange is real or not? Or get at those errors? Do I need my own connection delegate and have to parse a bunch of text?
The best way to scan for existing exchanges is using rabbitmq management HTTP API - it would be under /api/exchanges.
For a single exchange you could call the declare method, with passive parameter set accordingly (quoting from here):
for the declare method
This method creates an exchange if it does not already exist, and if
the exchange exists, verifies that it is of the correct and expected
class.
for the passive bit
If set, the server will reply with Declare-Ok if the exchange already
exists with the same name, and raise an error if not.
...
If not set and the exchange exists, the server MUST check that the existing exchange has the same values for type, durable, and arguments fields. The server MUST respond with Declare-Ok if the requested exchange matches these fields, and MUST raise a channel exception if not.

Azure Queue, AddMessage then UpdateMessage

Is it possible to Add a message to an Azure queue then, in the same flow, update or delete that message?
The idea would be to use the queue to ensure that some work gets done - there's a worker role monitoring that queue. But, the Web role which added the message may be able to make some progress toward (and sometimes even to complete) the transaction.
The worker would already be designed to handle double-delivery and reprocessing partially handled messages (from previous, failed worker attempts) - so there isn't a technical problem here, just time inefficiency and some superfluous storage transactions.
So far it seems like adding the message allows for a delivery delay, giving the web role some time, but doesn't give back a pop-receipt which it seems like we'd need to update/delete the message. Am I missing something?
It seems this feature was added as part of the "2016-05-31” REST API
we now make pop receipt value available in the Put Message (aka Add Message) response which allows users to update/delete a message without the need to retrieve the message first.
I suggest you follow these steps as it worked for me
How to: Create a queue
A CloudQueueClient object lets you get reference objects for queues. The following code creates a CloudQueueClient object. All code in this guide uses a storage connection string stored in the Azure application's service configuration. There are also other ways to create a CloudStorageAccount object. See CloudStorageAccount documentation for details.
// Retrieve storage account from connection string
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the queue client
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
Use the queueClient object to get a reference to the queue you want to use. You can create the queue if it doesn't exist.
// Retrieve a reference to a queue
CloudQueue queue = queueClient.GetQueueReference("myqueue");
// Create the queue if it doesn't already exist
queue.CreateIfNotExists();
How to: Insert a message into a queue
To insert a message into an existing queue, first create a new CloudQueueMessage. Next, call the AddMessage method. A CloudQueueMessage can be created from either a string (in UTF-8 format) or a byte array. Here is code which creates a queue (if it doesn't exist) and inserts the message 'Hello, World':
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(
CloudConfigurationManager.GetSetting("StorageConnectionString"));
// Create the queue client.
CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
// Retrieve a reference to a queue.
CloudQueue queue = queueClient.GetQueueReference("myqueue");
// Create the queue if it doesn't already exist.
queue.CreateIfNotExists();
// Create a message and add it to the queue.
CloudQueueMessage message = new CloudQueueMessage("Hello, World");
queue.AddMessage(message);
For more details, refer this link.
http://azure.microsoft.com/en-us/documentation/articles/storage-dotnet-how-to-use-queues/
Girish Prajwal

Servicestack.Redis Pub/Sub limitations with other nested Redis commands

I am having a great experience with ServiceStack & Redis, but I'm confused by ThreadPool and Pub/Sub within a thread, and an apparent limitation for accessing Redis within a message callback. The actual error I get states that I can only call "Subscribe" or "Publish" within the "current context". This happens when I try to do another Redis action from the message callback.
I have a process that must run continuously. In my case I can't just service a request one time, but must keep a thread alive all the time doing calculations (and controlling these threads from a REST API route is ideal). Data must come in to the process on a regular basis, and data must be published. The process must also store and retrieve data from Redis. I am using routes and services to take data in and store it in Redis, so this must take place async from the "calculation" process. I thought pub/sub would be the answer to glue the pieces together, but so far that does not seem possible.
Here is how my code is currently structured (the code with the above error). This is the callback for the route that starts the long term "calculation" thread:
public object Get(SystemCmd request)
{
object ctx = new object();
TradingSystemCmd SystemCmd = new TradingSystemCmd(request, ctx);
ThreadPool.QueueUserWorkItem(x =>
{
SystemCmd.signalEngine();
});
return (retVal); // retVal defined elsewhere
}
Here is the SystemCmd.signalEngine():
public void signalEngine(){
using (var subscription = Redis.CreateSubscription())
{
subscription.OnSubscribe = channel =>
{
};
subscription.OnUnSubscribe = channel =>
{
};
subscription.OnMessage = (channel, msg) =>
{
TC_CalcBar(channel, redisTrade);
};
subscription.SubscribeToChannels(dmx_key); //blocking
}
}
The "TC_CalcBar" call does processing on data as it becomes available. Within this call is a call to Redis for a regular database accesses (and the error). What I could do would be to remove the Subscription and use another method to block on data being available in Redis. But the current approach seemed quite nice until it failed to work. :-)
I also don't know if the ThreadPool has anything to do with the error, or not.
As per Redis documentation:
Once the client enters the subscribed state it is not supposed to
issue any other commands, except for additional SUBSCRIBE, PSUBSCRIBE,
UNSUBSCRIBE and PUNSUBSCRIBE commands.
Source : http://redis.io/commands/subscribe