Ethereum transaction hash: how to get in advance? - hash

Please tell me how can I get transactionHash in avance?
// I have these tx opts:
var txOpts = {
"to":"0x345cA3e014Aaf5dcA488057592ee47305D9B3e10",
"nonce":"0x8",
"gasPrice":1,
"gas":250000,
"value":"0xde0b6b3a7640000",
"data":"0xd0e30db0"
}
// I create and sign tx:
var tx = new ethereumjs.Tx(txOpts);
tx.sign(new ethereumjs.Buffer.Buffer("c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", "hex"));
// I've got raw tx:
var rawTx = tx.serialize().toString('hex');
"f86c08018303d09094345ca3e014aaf5dca488057592ee47305d9b3e10880de0b6b3a764000084d0e30db01ca0625e358100f4aacb9a65e6e054d963138565e3ceafb20eae4c9c8aaa583a29eea01d8f74faba33ab577ec36ac383dd5bd5298216bcf69fe2c09bba2d3003ecd008"
When I send this tx to ganache-cli, I receive this logs:
eth_sendRawTransaction
> {
> "jsonrpc": "2.0",
> "id": 7,
> "method": "eth_sendRawTransaction",
> "params": [
> "0xf86c08018303d09094345ca3e014aaf5dca488057592ee47305d9b3e10880de0b6b3a764000084d0e30db01ca0625e358100f4aacb9a65e6e054d963138565e3ceafb20eae4c9c8aaa583a29eea01d8f74faba33ab577ec36ac383dd5bd5298216bcf69fe2c09bba2d3003ecd008"
> ],
> "external": true
> }
Transaction: 0x73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc
Gas usage: 29634
Block Number: 9
Block Time: Fri Jan 12 2018 23:21:22 GMT-0700
Transaction hash is 0x73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc
How to get it in advance?
// use ethereumjs.hash function (is that rlp-hash?):
var hash = tx.hash().toString('hex')
"**71ef26c4c1c1b01a5f87525e8e9b3ca7ffe5c9ae30ee1e70b353bf9b14db96be**"
This is not equal to 73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc!
Is there any possibility to calculat CORRECT transaction hash in advance before mining? Please tell me what functions should I use.
Thanks a lot!

I digged a little bit to get the answer.
Instead of just call tx.hash().toString('hex'), you need to call like this tx.hash(true).toString('hex'), in which true stands for includeSignature when computing the hash.
In case you're curious, this is the method(https://github.com/ethereumjs/ethereumjs-tx/blob/9a6324f64f4da1cb550a3eec4eaef95da4ab441b/src/transaction.ts#L177).
And you could also get the same result from rawTx like this:
import * as ethUtil from 'ethereumjs-util';
const rawTx = `0x${signedTx.serialize().toString('hex')}`; // 0x is important
const res1 = `0x${ethUtil.keccak(rawTx).toString('hex')}`;
const res2 = `0x${signedTx.hash(true).toString('hex')}`;
res1 === res2; // true
I hope this will help.

This is just an issue with ganache. queueRawTransaction uses a FakeTransaction, which ignores the actual signature on your transaction and instead fakes it. I'm not entirely sure why it works this way, but I believe your code will do the right thing for a transaction submitted to an actual Ethereum network.
If you want to get the same transaction hash ganache is computing, this does the trick, but it won't be the transaction hash you get from Ethereum proper:
const EthereumTx = require('ethereumjs-tx');
const FakeTx = require('ethereumjs-tx/fake.js');
var txOpts = {
"to":"0x345cA3e014Aaf5dcA488057592ee47305D9B3e10",
"nonce":"0x8",
"gasPrice":1,
"gas":250000,
"value":"0xde0b6b3a7640000",
"data":"0xd0e30db0"
}
var tx = new EthereumTx(txOpts);
tx.sign(Buffer.from("c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", "hex"));
const raw = tx.serialize().toString('hex');
const fake = new FakeTx(raw);
fake.from = tx.getSenderAddress();
console.log(fake.hash(true).toString('hex'));
// Output:
// 71ef26c4c1c1b01a5f87525e8e9b3ca7ffe5c9ae30ee1e70b353bf9b14db96be

The actual tx hash we've got from ganache is:
0x73d419e3a9a63aab7ee4f3be43c0df0175f4395615945d395c827bffb3bbfecc
Both FakeTx and ethereumjs-tx returns the same hash for signed transaction:
71ef26c4c1c1b01a5f87525e8e9b3ca7ffe5c9ae30ee1e70b353bf9b14db96be
However if thransaction is not signed "tx.hash().toString('hex')" returns exactly the same value as ganache cli. Even without adding 'from' to txOpts.

It is not possible to get transaction hash in advance, you can only get transaction hash just after performing transaction.
But whenever transaction not pick by any miner this transaction hash will temporary, there is possibility that if you send very less fees with your transaction then your transaction might be not picked by any miner.

Related

Key-pair generation for Kadena

Chainweaver uses the following code to generate a key-pair from a Bip 39-generated seed: https://github.com/kadena-io/cardano-crypto.js/blob/c50fb8c2fcd4e8d396506fb0c07de9d658aa1bae/kadena-crypto.js#L336
Is there any documentation regarding this algorithm, specifically about the reasons for the 1000X loop and about not following a BIP 44 or similar HD wallet derivation?
for (let i = 1; result === undefined && i <= 1000; i++) {
try {
const digest = crypto.hmac_sha512(seed, [Buffer.from(`Root Seed Chain ${i}`, 'ascii')])
const tempSeed = digest.slice(0, 32)
const chainCode = digest.slice(32, 64)
result = trySeedChainCodeToKeypairV1(pwd, tempSeed, chainCode)
...
It also looks like this is a fork of Cardano code, so is there any reason Cardano was used as inspiration for Kadena as opposed to some other coin/chain? I would really like some historical context to why some of these decisions were made.
BIP-44 is designed for P2PKH, not ED25519. At the time the cardano-crypto library seemed like the best available option.

Gatling - how to achieve feeders to pick a new value in loop

In Gatling, I am using feeders to pass the values of the coordinates in a request, below is the code. I want on each repeat a new value from the feeder to be picked up. I am get the following error --
/mapping/v2/: Failed to build request: No attribute named 'map 30 (100.0%) x' is defined
Could someone please advice how this can be achieved. thanks.
val mapfeeder = csv(fileName = "data/cordinates.csv").circular
object PDP {
val pdp = group("ABC_01_DetailsPage") {
exec(http("PropertyDetailsPage")
.get("/abc/property/detail.html?propertyId=12345&index=0&q=${address_json6}&qt=address&_qt=address&offset=1&sort=address&limit=20&view=property&mode=&radius=1.0Km&landuse=All")
.check(substring("Change in Median Price")))
}
.pause(duration = 1)
.feed(mapfeeder) //this works but only take the fist value and repeats it 30 times
.group("ABC_02_DetailsPage_MAP") {
repeat(30) {
feed(mapfeeder) // this one fails with the error mentioned in the post
exec(http("/mapping")
.get(uri22 + "?mapTypeId=1006&x=${mapx}&y=${mapy}&z=19&access_token=${maptoken}"))
}
val scn = scenario("RecordedSimulation")
.feed(SearchFeeder)
.exec(Homepage.homepage, Login.login, SearchLink.search, SearchEntry.searchentry, PDP.pdp, Logout.logout)
setUp(scn.inject(atOnceUsers(1))).protocols(httpProtocol)
You're missing a dot to attach your feed and the following exec, so only the result of the last instruction (the exec) is passed to the repeat method.
It should be:
repeat(30) {
feed(mapfeeder)
.exec(
http("/mapping") // <== HERE, DOT WAS MISSING
.get(uri22 + "?mapTypeId=1006&x=${mapx}&y=${mapy}&z=19&access_token=${maptoken}")
)
}

Swift strings are not being stored in struct

I have a bare bones struct.
struct Transaction {
var value: String = ""
var date: String = ""
var title: String = ""
}
In my project, Transaction is used like so...
var transaction:Transaction = Transaction()
//loops 3 times
repeat {
let parsed = stringAndType(from:myParser)//-> (string:String, type:UInt8)
switch parsed.type {
case 1:
print("1 -- \(parsed.string")
transaction.value = parsed.string
case 2:
print("2 -- \(parsed.string)")
transaction.date = parsed.string
case 4:
print("4 -- \(parsed.string)")
transaction.title = parsed.string
default: break
}
} while myParser.isOk
print("Returning transaction: \(transaction)")
return transaction
In this code, a structure is created. The parser feeds the data to the switch, which assigns the parsed string to the appropriate Transaction variable. When I run the following code, the output indicates that the assignments to transaction.date and transaction.value are not sticking.
Output:
2 -- 12/22/2015
1 -- -5.00
4 -- RECURRING PAYMENT BACKBLAZE
Returning transaction: Transaction(value: "", date: "", title: "RECURRING PAYMENT BACKBLAZE")
There is complex buffering behind the scenes in stringAndType(). Looking at this as a C programmer, I really want to think that function might be the problem. However, I was under the impression that Swift strings are structures, and are therefore copy on write, just like an integer or double. Hoping you can provide insight. Thank you for your time.
Update 02/15/17
The logic in this code is functioning as expected. I think the problem here is memory management. To help drive this point, I've...
Removed the print lines from my switch
Added didSet {} to each variable in Transaction
Like so...
struct Transaction {
var value: String = "" {
didSet {
print("The VALUE has changed from \(oldValue) to \(value)")
}
}
//this is repeated appropriately for the other two variables
}
The given output rules out any logical issues. Output:
The DATE has changed from to 12/22/2015
The VALUE has changed from to -5.00
The TITLE has changed from to RECURRING PAYMENT BACKBLAZE
Returning transaction: Transaction(value: "", date: "", title: "RECURRING PAYMENT BACKBLAZE")
stringAndType() does read from an unsafe buffer, but it copies the bytes to a Data structure, and returns a string initialized from the COPIED data. I thought this would insulate me from safety issues...perhaps theres an implementation detail to String I'm missing?
Credit to #unkgd, you were on the right track with your initial answer before you retracted it. There was a logical error between the while parser.isOk loop and the parent loop (omitted to keep the code short) that was wiping Transaction between value and title being set. There was no indication of this happening in the output. The loop posted above was not looping three times, rather, it was looping once, but that single loop was iterated three times by the parent. Therefore, only the most recent parsed value was stored in the structure, in this case, title. Again, full credit to #unkgd (if you repost your answer and I will mark it as correct). Thanks to everyone for their ideas.

What could cause a meteor app to sometimes create two documents?

I have a meteor app that takes the text of an article and splits it into paragraphs, sentences, words, and characters and then stores that in a json which I then save as a document in a collection. The document I am testing now ends up as 15133 bytes in mongodb.
When I insert the document it takes about 20 or 30 seconds to insert. Then sometimes it starts going through my article creation routine again and inserts another document. Sometimes it ends up inserting 3 or more documents. Sometimes it behaves as it should and only inserts 1 document into the collection.
What should I be looking for that could be causing this behavior?
Here is my code, as requested:
Meteor.methods({
'createArticle': function (text, title) {
var article = {}
article.title = title
article.userID = "sdfgsdfg"
article.text = text
article.paragraphs = []
var paragraphs = splitArticleIntoParagraphs(text)
console.log("paragraphs", paragraphs)
_.each(paragraphs, function (paragraph, p) {
if (paragraph !== "") {
console.log("paragraph", paragraph)
article.paragraphs[p] = {}
article.paragraphs[p].read = false
article.paragraphs[p].text = paragraph
console.log("paragraphs[p]", article.paragraphs[p])
var sentences = splitParagraphIntoSentences(paragraph)
article.paragraphs[p].sentences = []
}
_.each(sentences, function (sentence, s) {
if (sentence !== "") {
article.paragraphs[p].sentences[s] = {}
console.log("sentence", sentence)
article.paragraphs[p].sentences[s].text = sentence
article.paragraphs[p].sentences[s].read = false
console.log("paragraphs[p].sentences[s]", article.paragraphs[p].sentences[s])
var wordsForward = splitSentenceIntoWordsForward(sentence)
console.log("wordsForward", JSON.stringify(wordsForward))
article.paragraphs[p].sentences[s].forward = {}
article.paragraphs[p].sentences[s].forward.words = wordsForward
// var wordsReverse = splitSentenceIntoWordsReverse(sentence)
_.each(wordsForward, function (word, w) {
if (word) {
// console.log("word", JSON.stringify(word))
// article.paragraphs[p].sentences[s] = {}
// article.paragraphs[p].sentences[s].forward = {}
// article.paragraphs[p].sentences[s].forward.words = []
article.paragraphs[p].sentences[s].forward.words[w] = {}
article.paragraphs[p].sentences[s].forward.words[w].wordID = word._id
article.paragraphs[p].sentences[s].forward.words[w].simp = word.simp
article.paragraphs[p].sentences[s].forward.words[w].trad = word.trad
console.log("word.simp", word.simp)
var characters = word.simp.split('')
console.log("characters", characters)
article.paragraphs[p].sentences[s].forward.words[w].characters = []
_.each(characters, function (character, c) {
if (character) {
console.log("character", character, p, s, w, c)
article.paragraphs[p].sentences[s].forward.words[w].characters[c] = {}
article.paragraphs[p].sentences[s].forward.words[w].characters[c].text = character
article.paragraphs[p].sentences[s].forward.words[w].characters[c].wordID = Words.findOne({simp: character})._id
}
})
}
})
}
})
})
// console.log("article", JSON.stringify(article))
// console.log(JSON.stringify(article.paragraphs[10].sentences[1].forward))//.words[4].characters[0])
console.log("done")
var id = Articles.insert(article)
console.log("id", id)
return id
}
})
I call the method here:
Template.articleList.events({
"click #addArticle": function(event) {
event.preventDefault();
var title = $('#title').val();
var text = $('#text').val();
$('#title').value = '';
$('#text').value = '';
$('#text').attr('rows', '3');
Meteor.call('createArticle', text, title);
}
})
An important thing to keep in mind is that meteor methods do not work very well when it comes to perform CPU intensive tasks. Since your meteor server only works in a single thread, any kind of blocking computations - like yours - will affect all client connections, e.g. delaying DDP heartbeats. This - in turn - can result in clients thinking that the connection was dropped.
As #ghybs suggested in one of the comments your method is probably triggered several times by an impatient DDP client who thinks that server has disconnected. The easiest way to prevent this behavior is by adding noRetry flag to Meteor.apply as explained here:
https://docs.meteor.com/api/methods.html#Meteor-apply
I believe Meteor.call does not have this option.
Another strategy would be trying to make sure that your methods are idempotent, i.e. calling them more than once should not produce any additional effects. This is usually true - at least when you use method simulation - because retrying db insert will re-use the same document id which will fail on the second try. For some reason this is not happening in your case.
Finally, the problem you described clearly shows that probably a different pattern should be used for a computationally expensive task like yours. If I were you, I would start by splitting the job in several steps:
First I would make sure that the document is uploaded to the server with a POST request rather than through DDP.
Then I would implement a "process file" server side method that grabs the file which is already on the server or in the database (in case you used files collection). The first thing the method should do would be calling this.unblock(), but thats not all.
Ideally the computational task should be executed in a separated process. Only when that process is completed the method would return telling the actual caller that the job is done. But since we called this.unblock() that caller can perform different tasks, e.g. calling other methods/subscriptions while waiting for the result.
Sometimes, having a separated process will not be good enough. I've experienced situations where I had to delegate the task to another worker server(s).

data-based buffering in Rx

Let me explain what I want to achieve first.
Lets say I have the following data incoming form the event stream
var data = new string[] {
"hello",
"Using",
"ok:michael",
"ok",
"begin:events",
"1:232",
"2:343",
"end:events",
"error:dfljsdf",
"fdl",
"error:fjkdjslf",
"ok"
};
When I subscribe the data source, I would like to get the following result
"ok:michael"
"ok"
"begin:events 1:232 2:343 end:events"
"error:dfljsdf"
"error:fjkdjslf"
"ok"
Basically, I want to get whichever data that start with ok or error and the data between begin and end.
I have tried this so far..
var data = new string[] {
"hello",
"Using",
"ok:michael",
"ok",
"begin:events",
"1:232",
"2:343",
"end:events",
"error:dfljsdf",
"fdl",
"error:fjkdjslf",
"ok"
};
var dataStream = Observable.Generate(
data.GetEnumerator(),
e => e.MoveNext(),
e => e,
e => e.Current.ToString(),
e => TimeSpan.FromSeconds(0.1));
var onelineStream = from d in dataStream
where d.StartsWith("ok") || d.StartsWith("error")
select d;
// ???
// may be need to buffer? I want to get data like "begin:events 1:232 2:343 end:events"
// but it is not working...
var multiLineStream = from list in dataStream.Buffer<string, string, string>(
bufferOpenings: dataStream.Where(d => d.StartsWith("begin")),
bufferClosingSelector: b => dataStream.Where(d => d.StartsWith("end")))
select String.Join(" ", list);
// merge two stream????
// but I have no clue how to merge these twos :(
mergeStream .Subscribe(d =>
{
Console.WriteLine(d);
Console.WriteLine();
});
Since I'm very new to Reactive programming, I can't make myself to think in reactive way. :(
Thanks in advance.
You were so, so very close to the right answer!
Essentially you had the onelineStream & multiLineStream queries just about right.
Merging them together is very easy. Just do this:
onelineStream.Merge(multiLineStream)
However, where your queries fell short was in the Observable.Generate that you used to introduce the delay between values. This creates a observable that, if you have multiple subscribers, kind of "fans out" the values.
Given your data and your definition for dataStream look how this code behaves:
dataStream.Select(x => "!" + x).Subscribe(Console.WriteLine);
dataStream.Select(x => "#" + x).Subscribe(Console.WriteLine);
You get these values:
!hello
#Using
!ok:michael
#ok
#1:232
!begin:events
#2:343
!end:events
!fdl
#error:dfljsdf
!error:fjkdjslf
#ok
Notice that some got handled by one subscription and the others got handled by the other. This means that even though your onelineStream & multiLineStream queries were just about right they would only see some of the data each and thus not behave as you expect.
You can also get race conditions that can skip and duplicate values. So it's best to avoid this kind of observable.
A better approach to introduce a delay between values is to do this:
var dataStream = data.ToObservable().Do(_ => Thread.Sleep(100));
Now this creates a "cold" observable, meaning that every new subscriber will get a fresh subscription of the observable so starting from the first value.
Your multiLineStream query will not work correctly on a cold observable.
To make the data stream a "hot" observable (which shares values amongst the subscribers) we use the Publish operator.
So, multiLineStream now looks like this:
var multiLineStream =
dataStream.Publish(ds =>
from list in ds.Buffer(
ds.Where(d => d.StartsWith("begin")),
b => ds.Where(d => d.StartsWith("end")))
select String.Join(" ", list));
You can then get your results like so:
onelineStream.Merge(multiLineStream).Subscribe(d =>
{
Console.WriteLine(d);
Console.WriteLine();
});
This is what I got:
ok:michael
ok
begin:events 1:232 2:343 end:events
error:dfljsdf
error:fjkdjslf
ok
Let me know if that works for you.