Issues during implementation of custom ETH settler - kotlin

I have investigated and played with corda-settler project. Following the recommendations within the documentation, I have created a custom ethereum module (with an outline similar to the ripple module), providing the option to settle obligations using off-ledger payments in ETH. The implementation (https://github.com/vladichhh/corda-settler)
consists of the following significant pieces:
flows
MakeEthPayment
services
ETHClient
ETHService
types
EthPayment
EthSettlement
token
registered DigitalCurrency for ETH
oracle
added logic for ETH payment verification
MakeEthPayment.kt
#Suspendable
override fun makePayment(obligation: Obligation<*>, amount: Amount<T>): EthPayment<T> {
// get ETHService client
val ethClient = serviceHub.cordaService(ETHService::class.java).client
val recipient = obligation.settlementMethod?.accountToPay.toString()
val amountToSend = amount.quantity.toString()
// trigger ETH transfer
val txHash = ethClient.sendEth(recipient, amountToSend)
// return the payment
return EthPayment(txHash, amount, PaymentStatus.SENT)
}
ETHClient.kt
fun sendEth(recipient: String, amount: String): String {
val weiAmount: BigInteger = Convert.toWei(amount, Convert.Unit.GWEI).toBigInteger()
val credentials: Credentials = WalletUtils.loadCredentials(walletPassword, walletFile)
val transactionReceipt: TransactionReceipt = Transfer
.sendFunds(web3j, credentials, recipient, BigDecimal(weiAmount), Convert.Unit.WEI)
.send()
return transactionReceipt.transactionHash
}
In order to send the required ETH amount to the specified recipient account, we have to do some Ethereum specific stuff:
we are connecting to Ethereum public blockchain environment, using “web3j” library
in order to trigger am Etherem transaction and transfer specified ETH amount, "web3j" requires an access to the file, containing encrypted sender's wallet
thus we have to provide password (to decrypt wallet) and location of the file, containing encrypted sender's wallet
And here are the issues:
I got the exception that the file could not be found, no matter where I am putting it. I have checked even the “swift” implementation and tried to use the class loader to load my file, but without success.
I suppose, the file with encrypted sender’s wallet should be located on one of the following places:
corda-settler/ethereum/src/main/resources/file.tmp
corda-settler/cordapp/src/main/resources/file.tmp
Finally I have hardcoded the location in that way:
/Users/vladimirhristov/WebstormProjects/Corda/corda-settler/cordapp/src/main/resources/file.tmp
and seems that the file was found but got another exception:
java.lang.OutOfMemoryError - screenshot
Seems that the operation of wallet decryption is highly consuming, which breaks maybe the flow. There is an option to reduce the algorithm complexity of the wallet generation, which will reflect in lower resources required to decrypt the same wallet at the next step, but this will reduce the security as well.
And here are my three basic questions ...
How could I specify (location/mechanism) and make flow to find successfully my file, containing the sender’s encrypted wallet ?
How could I access a files in the flow, or if there is another mechanism to attach only the file with encrypted wallet and pass the decryption to core Corda ?
Do I need just to increase node resources (tuning JVM params increasing -Xms/-Xmx) in order to avoid OutOfMemoryError ?
Content of the file (containing encrypted sender’s wallet):
file.tmp
{"version":3,"id":"ecb51768-8564-498a-bb11-3a5a5c8dc0bb","address":"2bafc482bd227dfd5ba250521a00be3a4cc88bbd","crypto":{"ciphertext":"e0511415792dfa7221ba1b8f32b8ec98e1410f45e612e2100df1aceddfdb22bd","cipherparams":{"iv":"7ffa2af08f502c63d57e62440ad77539"},"cipher":"aes-128-ctr","kdf":"scrypt","kdfparams":{"dklen":32,"salt":"8051a5df1c02eb3eba81d2920fbb84b76b948a1248bbba62ffff684e733948cf","n":131072,"r":8,"p":1},"mac":"be23fe0e261ba38892581d80afd0c86563748377b5cc702b6ed3285a13cceff6"}}
I will appreciate any help! Thanks in advance :)

VERY strange that Corda is giving you an out of memory error when running that flow.
I'd actually say that we'd need to be able to see the code for the flow in order to know how it could have run out of memory.
Are you running it in a container? Just make sure that you're meeting the requirements to run a JVM with an application on top.
tl;dr use a 8GB RAM machine to run your Corda node on the latest version of corda that should hopefully solve this issue.
Here's the docs page on the memory requirements;
https://docs.corda.net/docs/corda-enterprise/4.5/node/performance-results.html#sizing

Related

Can I allow multiple http clients to consume a Flowable stream of data with resteasy-rxjava2 / quarkus?

Currently I am able to see the streaming values exposed by the code below, but only one http client will receive the continuous stream of values, the others will not be able to.
The code, a modified version of the quarkus quickstart for kafka reactive streaming is:
#Path("/migrations")
public class StreamingResource {
private volatile Map<String, String> counterBySystemDate = new ConcurrentHashMap<>();
#Inject
#Channel("migrations")
Flowable<String> counters;
#GET
#Path("/stream")
#Produces(MediaType.SERVER_SENT_EVENTS) // denotes that server side events (SSE) will be produced
#SseElementType("text/plain") // denotes that the contained data, within this SSE, is just regular text/plain data
public Publisher<String> stream() {
Flowable<String> mainStream = counters.doOnNext(dateSystemToCount -> {
String key = dateSystemToCount.substring(0, dateSystemToCount.lastIndexOf("_"));
counterBySystemDate.put(key, dateSystemToCount);
});
return fromIterable(counterBySystemDate.values().stream().sorted().collect(Collectors.toList()))
.concatWith(mainStream)
.onBackpressureLatest();
}
}
Is it possible to make any modification that would allow multiple clients to consume the same data, in a broadcast fashion?
I guess this implies letting go of backpressure, because that would imply a state per consumer?
I saw that Observable is not accepted as a return type in the resteasy-rxjava2 for the Server Side Events media-tpe.
Please let me know any ideas,
Thank you
Please find the full code in Why in multiple connections to PricesResource Publisher, only one gets the stream?

How to send Lumens to an uninitialised stellar address pragmatically

I am new to stellar so please bear with my question if it sounds too basic.
So, using the stellar laboratory, I created two accounts lets name 1 and 2. I funded the 1st account with test-net coins using friend-bot and left the 2nd account empty. Now as I understand that an account to be active on stellar network, it should have a minimum balance of about 1XLM. So using the transaction builder, I tried to perform a Payment Operation by trying to transfer 2XLM to the 2nd account. However I recieved the following response :
{
"type": "https://stellar.org/horizon-errors/transaction_failed",
"title": "Transaction Failed",
"status": 400,
"detail": "The transaction failed when submitted to the stellar network. The `extras.result_codes` field on this response contains further details. Descriptions of each code can be found at: https://www.stellar.org/developers/learn/concepts/list-of-operations.html",
"extras": {
"envelope_xdr": "AAAAAKNyr+6/r2REKzMV3sOL4jztg1HSdqlQhmthUU41BjPdAAAAZAAEmkQAAAADAAAAAAAAAAAAAAABAAAAAAAAAAEAAAAAmWhqbEZTUrZWFtvR1HU7VUW0pp3BwN4E9h4iQwvMr9kAAAAAAAAAAAExLQAAAAAAAAAAATUGM90AAABAHvtdpnjhq3usHFphQ/4naDHbKVhu+QqD8UFSavo/qlGo7Yiz/dLI3lQ0fmfa37uvwXWsYAn8mObDkrTjofc3Aw==",
"result_codes": {
"transaction": "tx_failed",
"operations": [
"op_no_destination"
]
},
"result_xdr": "AAAAAAAAAGT/////AAAAAQAAAAAAAAAB////+wAAAAA="
}
}
So can someone tell me which operation I need to use to send XLM to an un-initialised address so I can activate it, not by using friendbot.
First, you need to execute Create Account from the Transaction Builder.
Only then you can transfer funds to this address.
I think it's because the Stellar laboratory is not set up for this exact use case. It is more for getting a general feel of the basics. In order to create an account this way using an SDK and communicating with horizon you would have to both create the account and fund it in a single transaction, and therefore you would have to input the source account's secret key.
In the Stellar lab's account creation tab there is no way to input a source address its secret key (or at least I didn't see one).
So in your example, your first account is created and funded by the testbot. However, when you create the second account and try to send a payment to it from the first account, the reason it fails is because the second account is not yet a valid account as it has not been funded yet. Kind of a chicken and egg problem.
The good news is you can definitely do this using the SDK, but I haven't found a way to do it using the lab.
This from stellar.org about building transactions:
https://www.stellar.org/developers/js-stellar-base/reference/building-transactions.html
TransactionBuilder
The TransactionBuilder class is used to construct
new transactions. TransactionBuilder is given an account that is used
as transaction’s “source account”. The transaction will use the
current sequence number of the given Account object as its sequence
number and increments the given account’s sequence number when build()
is called on the TransactionBuilder.
Operations can be added to the transaction calling
addOperation(operation) for each operation you wish to add to the
transaction. See operation.js for a list of possible operations you
can add. addOperation(operation) returns the current
TransactionBuilder object so you can chain multiple calls.
After adding the desired operations, call the build() method on the
TransactionBuilder. This will return a fully constructed Transaction.
The returned transaction will contain the sequence number of the
source account. This transaction is unsigned. You must sign it before
it will be accepted by the Stellar network.
# This is the relevant code
StellarSdk.Network.useTestNetwork();
// StellarBase.Network.usePublicNetwork(); if this transaction is for the public network
// Create an Account object from an address and sequence number.
var account=new StellarBase.Account("GD6WU64OEP5C4LRBH6NK3MHYIA2ADN6K6II6EXPNVUR3ERBXT4AN4ACD","2319149195853854");
var transaction = new StellarBase.TransactionBuilder(account, {
fee: StellarBase.BASE_FEE
})
// add a payment operation to the transaction
.addOperation(StellarBase.Operation.payment({
destination: "GASOCNHNNLYFNMDJYQ3XFMI7BYHIOCFW3GJEOWRPEGK2TDPGTG2E5EDW",
asset: StellarBase.Asset.native(),
amount: "100.50" // 100.50 XLM
}))
// add a set options operation to the transaction
.addOperation(StellarBase.Operation.setOptions({
signer: {
ed25519PublicKey: secondAccountAddress,
weight: 1
}
}))
// mark this transaction as valid only for the next 30 seconds
.setTimeout(30)
.build();
# Note that it is adding different operations to a single transaction.

How to test contract with multiple accounts / addresses in truffle?

I want to test my truffle contract with multiple msg.sender addresses. Like "the first user sell token, the second user buys this token". For one address I simply write something like contract.buy.value(10 wei)();. But where I could get another address and how to send money from him?
I write my tests on solidity, not on javascript.
as you can see in the Truffle docs, you can specify two different accounts to interact with your deployed smart contract like below (Metacoin example):
var account_one = "0x1234..."; // an address
var account_two = "0xabcd..."; // another address
var meta;
MetaCoin.deployed().then(function(instance) {
meta = instance;
return meta.sendCoin(account_two, 10, {from: account_one});
}).then(function(result) {
// If this callback is called, the transaction was successfully processed.
alert("Transaction successful!")
}).catch(function(e) {
// There was an error! Handle it.
})
This is about how you can do with your own created token.
If you want to transfer Ether between accounts, you can specify accounts in your truffle execution file (a javascript file). And these accounts may come from your configured local blockchain (Ganache, if you are using Truffle Suite to test your smart contract, it will provide you with several accounts and you can configure these by yourself).
Moreover, you may need javascript API to specify the sender and receiver: web3.eth.sendTransaction.
First time to answer a question, hope this will help.

MobileFirst 8 : Unexpected error encountered while storing data

We are using UserAuthenticationSecurityCheck to authenticate user.
If verification is successful, the MFP server will store the user attributes.
public class AuthSecurityCheck extends UserAuthenticationSecurityCheck {
static Logger logger = Logger.getLogger(AuthSecurityCheck.class.getName());
private String userId, displayName;
private JSONObject attrObject;
private String errorMessage;
#Override
protected AuthenticatedUser createUser() {
Map<String, Object> userAttrsMap = new HashMap<String, Object>();
userAttrsMap.put("attributes",attrObject);
return new AuthenticatedUser(userId, displayName, this.getName(), userAttrsMap);
}
...
}
But if we store larger data(when userAttrsMap is large enough), we will get the 500 error.
errorMsg: Unexpected error encountered while storing data
The error is shown below:
Full source is on Github: https://github.com/DannyYang/PMR_CreateUserStoredLargeData
MFP version:
cordova-plugin-mfp 8.0.2017102115
MFP DevelopKit : 8.0.0.00-20171024-064640
The issue happens owing to the size of the data you are holding within the AuthenticatedUser object and thereby the Securitycheck's state.
MFP runtime saves the state of the securitycheck along with all the attributes to the attribute store . This involves serializing the security check state and persisting it to the DB. With a large object ( the custom map you have) this persistence operation fails and ends in a transaction rollback. This happens because the data you are trying to persist is too big and exceeds the allocated size.
SecurityCheck’s design consideration is to use it for a security check ( validation) and creating an identity object. Within your security check implementation, you have the following:
//Here the large data is assigned to the variable.
attrObject = JSONObject.parse(largeJSONString);
//This data is set into the AuthenticatedUser object.
Map<String, Object> userAttrsMap = new HashMap<String, Object>();
userAttrsMap.put("attributes",attrObject);
return new AuthenticatedUser(userId, displayName, this.getName(), userAttrsMap);
In this scenario this large data becomes part of the Securitycheck itself and will be serialized and attempted for persistence into the attribute store. When this data does not fit in the column, the transaction is rolled back and the error condition is propagated to the end user. Hence the error message you see - ” Unexpected error occured while storing data”. Enabling detailed trace will indicate the actual cause of the issue in the server trace logs.
Either way, this approach is not recommended at all in production systems because:
a) Every request from the client reaching the server goes through security introspection which will involve the server to load, check and update the securitycheck’s state. On systems taking heavy load ( production ) this can and will have performance costs. The process involves serializing the data and deserializing it later. In a distributed topology ( cluster or farms ) the request may end up in any of the nodes and these nodes will have to load and later save the security check's state to the store. All this will impact performance of your system.
b) At the end of successful authentication, the AuthenticatedUser object is propagated to the client application indicating completion of the login flow . Even if the SecurityCheck state were to be stored successfully in the attribute store ( with large data) transmitting large payloads over the network just to indicate successful login will be counter productive. For the enduser it may appear as if nothing has happened since they entered the credentials, while data indicating success is still getting downloaded.
c) Under heavy loads , the server will be strained from both a) and b) above.
You should consider cutting down the data that is propagated to the client within the authenticateduser object. Keep the data minimal within the AuthenticatedUser object. Instead, you should offload obtaining large data to resource adapters , that can be accessed post successful login .

Transaction on bitcoin address derived from bitcoinjs-lib not showing in Bitcoin core

I have generated the xpub using bip32.org and derieved random address using xpub
var hdNode = bitcoinjs.HDNode.fromBase58(derivedPubKey);
hdNode.derive(index).pubKey.getAddress().toString();
the Private wif generated via bip32.org imported in the Bitcoin core. On transferring amount on the address generated by above code., amount is not showing in my bitcoin-core..
If you have imported the main pubkey into Core but the address you send to is a derived address then you are just sending to different address than you are expecting the funds to receive at.
Every derived address has its own private key so you have to import the keys of individual derived addresses not just the key of the chain:
var addr = hdNode.derive(i);
/* Derived address: */
addr.getAddress();
/* Corresponding privkey: */
addr.keyPair.toWIF();
In fact every derived address is possibly also a new chain (derive() returns a new HDNode). Also your hdNode is intended to be used only for address derivation yet it has own address too (the one you have sent your funds too), just because there are no separate datatypes for addresses and for chains. To access that funds just generate private key without derivation:
hdNode.keyPair.toWIF();
On the other hand if you use Electrum instead of Core you may just extract the main key of one of address chains of an Electrum wallet (it does not work the opposite way as Electrum uses checksum for wallet seed and you cannot just import non-electrum chain). This way you will be able to independently generate new addresses (also just new addresses without privKeys, for security reasons) which would be recognized by the wallet without importing them explicitly.
By the way, https://bitcoin.stackexchange.com/ is better place to ask bitcoin-related questions.
Yes you can create address from private key using below code
const bitcoin = require('bitcoinjs-lib');
let testnet = bitcoin.networks.testnet;
const keyPair = bitcoin.ECPair.fromWIF('cQnWufBcGz5fDtAPH8DVzrayXY1BJVCohCSHhgHXV8xnWfkGKQGL', testnet )
const { address } = bitcoin.payments.p2pkh({ pubkey: keyPair.publicKey })
console.log(address)