Can't corda observer node reissue cash? - corda

I am trying to persist only specific states into vault state of Observer node.
In my usecase Observer is cash issuer, Where observer issues cash and transfer to other nodes in corda network. When corda nodes perform transaction, as observer all cash states of nodes also gets persist on observer node.
When try to reissue cash from Observer gives below error:
java.util.NoSuchElementException: Collection contains no element matching the predicate.
at net.corda.node.services.keys.PersistentKeyManagementService.getSigningKeyPair(PersistentKeyManagementService.kt:110) ~[corda-node-3.3-corda.jar:?]
at net.corda.node.services.keys.PersistentKeyManagementService.sign(PersistentKeyManagementService.kt:101) ~[corda-node-3.3-corda.jar:?]
at net.corda.core.transactions.TransactionBuilder.toSignedTransaction(TransactionBuilder.kt:224) ~[corda-core-3.3-corda.jar:?]
at net.corda.core.node.ServiceHub$DefaultImpls.signInitialTransaction(ServiceHub.kt:219) ~[corda-core-3.3-corda.jar:?]
at net.corda.core.node.ServiceHub$DefaultImpls.signInitialTransaction(ServiceHub.kt:233) ~[corda-core-3.3-corda.jar:?]
at net.corda.node.services.api.ServiceHubInternal$DefaultImpls.signInitialTransaction(ServiceHubInternal.kt) ~[corda-node-3.3-corda.jar:?]
at net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.signInitialTransaction(AbstractNode.kt:836) ~[corda-node-3.3-corda.jar:?]
at net.corda.core.node.ServiceHub$DefaultImpls.signInitialTransaction(ServiceHub.kt:255) ~[corda-core-3.3-corda.jar:?]
at net.corda.node.services.api.ServiceHubInternal$DefaultImpls.signInitialTransaction(ServiceHubInternal.kt) ~[corda-node-3.3-corda.jar:?]
at net.corda.node.internal.AbstractNode$ServiceHubInternalImpl.signInitialTransaction(AbstractNode.kt:836) ~[corda-node-3.3-corda.jar:?]
at net.corda.finance.flows.CashPaymentFlow.call(CashPaymentFlow.kt:66) ~[corda-finance-3.3-corda.jar:?]
at net.corda.finance.flows.CashPaymentFlow.call(CashPaymentFlow.kt:26) ~[corda-finance-3.3-corda.jar:?]
at net.corda.core.flows.FlowLogic.subFlow(FlowLogic.kt:290) ~[corda-core-3.3-corda.jar:?]
at net.corda.finance.flows.CashIssueAndPaymentFlow.call(CashIssueAndPaymentFlow.kt:41) ~[corda-finance-3.3-corda.jar:?]
at net.corda.finance.flows.CashIssueAndPaymentFlow.call(CashIssueAndPaymentFlow.kt:24) ~[corda-finance-3.3-corda.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:96) [corda-node-3.3-corda.jar:?]
at net.corda.node.services.statemachine.FlowStateMachineImpl.run(FlowStateMachineImpl.kt:44) [corda-node-3.3-corda.jar:?]
at co.paralleluniverse.fibers.Fiber.run1(Fiber.java:1092) [quasar-core-0.7.9-jdk8.jar:0.7.9]
at co.paralleluniverse.fibers.Fiber.exec(Fiber.java:788) [quasar-core-0.7.9-jdk8.jar:0.7.9]
I want to reissue new cash from observer node, but however it try to use unconsumed cash state persist during observing transaction. I think observer can't issue or transfer cash.
Edit:
On Regulator node, calling CashIssueAndPaymentFlow through API as below:
rpcOps.startFlow(::CashIssueAndPaymentFlow, issueAmount, OpaqueBytes.of(0), toTransferNode, false, notaryIdentity).returnValue.get()
On Other Node Flow sending transaction to observer:
val observer = serviceHub.networkMapCache.getPeerByLegalName(CordaX500Name.parse(FundTransferConstants.OBSERVER_NAME)) ?: throw IllegalArgumentException("Unknown observer name.")
subFlow(BroadcastTransactionTransfer.BroadcastTransactionToObserversTransfer(finalTx, listOf(observer)))
Scenario is below:
Cash issue and Transfer to node using CashIssueAndPaymentFlow on Regulator node.
Do transaction involving cash and send transaction to observer (Regulator). Cash is spend to other party using Cash.generateSpend()
Again try to reissue cash, gives above issue.
I think similar issue posted on git at https://github.com/corda/corda/issues/4368
Need help in this regard.

When you call ServiceHub.signInitialTransaction without passing a specific key, the platform tries to sign the transaction with your node's default key:
fun signInitialTransaction(builder: TransactionBuilder): SignedTransaction =
signInitialTransaction(builder, legalIdentityKey)
private val legalIdentityKey: PublicKey get() =
this.myInfo.legalIdentitiesAndCerts.first().owningKey
Because the observer node isn't one of the signers (e.g. because they're not the owner of the cash), this exception is thrown.

Related

Internal JSON-RPC error when swapping from ethers.js on uniswap

I spend a lot of time trying to understand where is the mistake.
I try to swap USDC to any token on uniswap router v3 with ethers.js on frontend.
I use Polygon network in app and in metamask too.
I have a confirmation in my metamask to approve USDC, but after it I have no confirmation about swapping. I see an error in console:
inpage.js:1 MetaMask - RPC Error: Internal JSON-RPC error. code: -32603 data: code: -32000 message: "execution reverted"
This is my code:
const provider = new ethers.providers.Web3Provider(window.ethereum);
const send_account = await provider.getSigner().getAddress(); //my address
//Swap from USDC to MTS or any other token
addressOfUSDC='0x2791bca1f2de4661ed88a30c99a7a9449aa84174' // Address of USDC in Polygon
const ERC20Contract = new ethers.Contract(addressOfUSDC, ERC20ABI, provider);
swapRouterAddress="0xe592427a0aece92de3edee1f18e0157c05861564"; //Uniswap v3 router
indadr="0x440416D85E5D51424da371297E3d7Ef28312BF62"; //Any token address to which I want to swap
approvalAmount=12; //12 USDC
await ERC20Contract
.connect(provider.getSigner())
.approve(swapRouterAddress, approvalAmount*1000000)
//After this step we see confirmation to spend 12$ in metamask
bn=ethers.BigNumber.from(approvalAmount*1000000); //BigNumber from approvalAmount
const params = {
tokenIn: addressOfUSDC,
tokenOut: indadr,
fee: ethers.BigNumber.from(3000),
recipient: send_account,
deadline: ethers.BigNumber.from(Math.floor(Date.now() / 1000) + (60 * 10)),
amountIn: bn,
amountOutMinimum: ethers.BigNumber.from(0),
sqrtPriceLimitX96: ethers.BigNumber.from(0),
}
const UniswapContract= new ethers.Contract(swapRouterAddress, ERC20ABI2, provider);
dd=await UniswapContract
.connect(provider.getSigner())
.exactInputSingle(params)
console.log(dd);
And after this step I have no confirmation in metamask and error in console: MetaMask - RPC Error: Internal JSON-RPC error. execution reverted
Maybe the problem is that I use two different router ABIs?
Please help me to understand the problem! Thanks in advanse!
I tried to change ABI, router address. Also I tried to use Uniswap V2 router with function swapExactTokensForTokens.
I try to swap USDC to any token on uniswap router v3 with ethers.js on
frontend.
you cannot swap USDC with any kind token. you need to have pool pair contract. for example ETH/USD, you have to find the pool address for WETH/USDC and create a pool contract. WETH is ERC20 version of ETH
you need to get the pool address and create a pool contract to get the immutables.
const poolContract = new ethers.Contract(
poolAddress,
IUniswapV3PoolABI,
provider
);
this is what you set as the first params
tokenIn: immutables.token1,
tokenOut: immutables.token0,
Then you have to have a swap router contract
const swapRouterContract = new ethers.Contract(
swapRouterAddress,
SwapRouterABI,
provider
);
the way how you created the swap router contract is wrong
const UniswapContract= new ethers.Contract(swapRouterAddress, ERC20ABI2, provider);
you are passing ERC20ABI2 here. this should be SwapRouterABI. ERC20ABI2 is used to construct the USDC token contract and other token contract that you are going to swap. Because eventually, you are swapping two ERC20 contracts
If you need to swap ERC20 tokens, first you have to allow the swap amount, so you have to call approve method of token contracts that you construct. you need to allow Uniswap to withdraw money from token contracts.
Finally you call the contract function
dd=await UniswapContract
// maybe you should have const signer= await provider.getSigner()
.connect(provider.getSigner())
.exactInputSingle(params)

Is it okay to modify application state in a firestore transaction on the server?

The docs state
Do not modify application state inside of your transaction functions. Doing so will introduce concurrency issues, because transaction functions can run multiple times and are not guaranteed to run on the UI thread.
When using the admin SDK there'll be pessimistic concurrency control and I don't need to think about a UI thread. Does that mean its okay to modify state in admin SDK transactions?
Transactions may fail to commit for various reasons. In such cases the SDK can retry the transaction up to 5 times, causing the update function to execute multiple times (see API docs). So it's still not a good idea to do state changes in the body of the transaction update. It's best to observe the transaction commit status before making a state change:
try {
await db.runTransaction(async (t) => {
const doc = await t.get(cityRef);
const newPopulation = doc.data().population + 1;
t.update(cityRef, {population: newPopulation});
});
console.log('Transaction success!');
// DO STATE CHANGES HERE
} catch (e) {
console.log('Transaction failure:', e);
}

Asterisk AsterNET How to move from parking to queue?

Im using C# AsterNET to manage my Asterisk commands and events, and now I do have a new feature to work on.
This is simple (I think) but I'm stucked right now.
Scenario
I do have two queues, 8100 and 8300, and 2 extensions being 8101 and 8301. When I do have a call from PSTN it is driven to 8100 queue. When the 8101 extension become available I do add this extension to the 8100 queue, so the calling PSTN device will be redirected to this 8101 extension.
Everything is working fine till here.
Sometimes I do park the calling device and let 8301 knows it using my app, so 8301 user using the same app can send a command asking for that parked channel to be redirect to his SIP Phone. Also working fine.
Scope
Now I want to have some feature to let 8101 transfer this calling device to my other queue, the 8300. So I just tried to reuse my parked method and redirect method
internal void Park(string channel, int parkTimeout)
{
ParkAction pa = new ParkAction(channel, channel, parkTimeout.ToString());
ManagerResponse mr = manager.SendAction(pa);
}
internal void RedirectFromParking(string channel, string exten)
{
RedirectAction ra = new RedirectAction
{
Priority = 1,
Context = "default",
Channel = channel,
Exten = exten
};
ManagerResponse mr = manager.SendAction(ra);
}
Park("abc123456", 10000);
RedirectFromParking("abc123456", "8300")
Issue
I'm parking fine but when I try to redirect from parking to my queue the calling device is just disconnected and the connection is lost.
How can I transfer a parked call to my queue or transfer it directly to the queue (would be better) without needing to originate?
Just do hold instead of parking and make your own list of such calls.
To transfer to a queue I can do a blind transfer as documented on Asterisk website. Links below:
ManagerAction_BlindTransfer
ManagerEvent_BlindTransfer
To achieve this using AsterNET, I can use the same RedirectAction I was using but I do need to change the context. It can't be default for context, as default we are letting Asterisk manage it and somehow it can't handle as I expetected. So it need to be clearly specified as internar transfer. The event raised after this context transfer is the Manager_BlindTransfer.
Manager_Action_RedirectAction
So using my SIP Phone I manage to transfer a call while I was debugging that raised event method, so I could catch the context used in. Using the correct context
ManagerConnection manager = new ManagerConnection(address, port, user, password);
manager.BlindTransfer += Manager_BlindTransfer;
private void Manager_BlindTransfer(object sender, BlindTransferEvent e)
{
}
After this I created another method to transfer to directly to a queue using the correct context.
internal void TransferToQueue(string channel, string queue)
{
RedirectAction ma = new RedirectAction
{
Priority = priority,
Context = "from-internal-xfer",
Channel = channel,
Exten = queue
};
ManagerResponse mr = manager.SendAction(ma);
}
TransferToQueue("abc123456", "8300")
Summary
Was just a matter of the correct context to be used in.
from-internal-xfer

Corda MQ node error - Message for incorrect endpoint using a p2pAddress hostname

I'm running Corda 3.1, and running nodes on separate machines. If I specify my p2pAddress as my hostname, after successful startup, I receive a Message for incorrect endpoint error when attempting transactions in the IOU example:
[ERROR] 2018-05-31T14:48:22,406Z [nioEventLoopGroup-2-1] O=Bank A,L=London,C=GB.write - Error in AMQP write processing {}
java.lang.IllegalArgumentException: Message for incorrect endpoint
at net.corda.nodeapi.internal.protonwrapper.netty.AMQPChannelHandler.write(AMQPChannelHandler.kt:124) [corda-node-api-3.1-corda.jar:?]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:738) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:730) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.channel.AbstractChannelHandlerContext.access$1900(AbstractChannelHandlerContext.java:38) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1089) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1136) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1078) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:403) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:442) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:144) [netty-all-4.1.9.Final.jar:4.1.9.Final]
at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
Here is the snippet of my node.conf:
myLegalName : "O=Bank A,L=London,C=GB"
p2pAddress : "my-load-balancer-hostname.aws.com:10002"
rpcSettings = {
address : "localhost:10003"
adminAddress : "localhost:10004"
}
rpcUsers : [
{ username=user1, password=test, permissions=[ ALL ] }
]
devMode : true
I can resolve this (and make transactions across nodes as expected) by using the IP address of the machine as the p2pAddress. However, my node IP could change, thus I'd like to use the hostname? Is this possible?
This appears to be related to the AWS load balancer.
Did some further debugging on this and discovered the root cause.
The error was thrown from AMQPChannelHandler.kt, line 148, when doing validation for the AMQ destination:
require(inetAddress == remoteAddress) { "Message for incorrect endpoint" }
The InetSocketAddress.java equality returns false because the IP changes. Debugging properties:
inetAddress.hostString: party-corda-node-dev.aws.co.com,
inetAddress.address: party-corda-node-dev.aws.co.com/10.224.8.233
inetAddress.port: 10002
inetAddress.isUnresolved: false
remoteAddress.hostString: liberty-corda-node-dev.aws.co.com
remoteAddress.address: liberty-corda-node-dev.aws.co.com/10.224.10.46
remoteAddress.port: 10002
remoteAddress.isUnresolved: false
Suggested fix to remove that validation check against resolved hostnames.
Documented in pull request https://github.com/corda/corda/pull/3381

Cloud Firestore - QuerySnapshot.toObjects Throws Null Pointer Exception

I've stumbled upon a strange problem. I'm trying to accomplish a simple thing - convert everything from a QuerySnapshot to a collection of a certain type.
fun createReminder(reminder: Reminder) =
remindersCollectionRef.document("${reminder.taskId}").set(reminder)
fun tryRemoveReminder(taskId: Int) =
remindersCollectionRef.document("$taskId").delete()
fun getReminders(onComplete: (List<Reminder>) -> Unit) {
remindersCollectionRef.get()
.addOnSuccessListener { querySnapshot ->
if (!querySnapshot.isEmpty)
onComplete(querySnapshot.toObjects(Reminder::class.java))
}
}
The problem is in the getReminders function. I know that there is one reminder in the collection. It is also 100% of type Reminder and as you can see I already check if querySnapshot is not empty. Still, I get a null pointer exception when I call toObjects.
Stack trace:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.reflect.Constructor.newInstance(java.lang.Object[])' on a null object reference
at com.google.android.gms.internal.zzevb$zza.zza(Unknown Source:57)
at com.google.android.gms.internal.zzevb.zza(Unknown Source:1025)
at com.google.android.gms.internal.zzevb.zza(Unknown Source:2)
at com.google.firebase.firestore.DocumentSnapshot.toObject(Unknown Source:10)
at com.google.firebase.firestore.QuerySnapshot.toObjects(Unknown Source:27)
at com.mypackage.util.FirestoreUtil$Companion$getReminders$1.onSuccess(FirestoreUtil.kt:131)
at com.mypackage.util.FirestoreUtil$Companion$getReminders$1.onSuccess(FirestoreUtil.kt:18)
at com.google.android.gms.tasks.zzj.run(Unknown Source:27)
at android.os.Handler.handleCallback(Handler.java:789)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541) at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Reminder class:
data class Reminder(val taskDocRef: DocumentReference, val taskId: Int)
This issue seems really strange to me. I will appreciate your help :)
If you carefully read documentation for Cloud Firestore query requirements for mapping Custom objects here, there will be notice:
Important: Each custom class must have a public constructor that takes
no arguments. In addition, the class must include a public getter for
each property.
Make Sure that you change the rules in the Firestore
For rules go to https://firebase.google.com/docs/firestore/quickstart#secure_your_data and copy the rules of testmode and paste them in the firestore rules
It take 10 minutes to change the rules.So run the app again after 10 minutes

Resources