Problem creating signed transaction for transaction

We are porting LCS to javascript. Deserialization is working but we have a problem with creating the signed transaction for a transaction. All seems fine but when we submit the transaction request we get a major status 11 error. Although all seems fine, we get this error which translates to UNKNOWN_SCRIPT and this has probably to do with a whitelist check.

We are creating the uint8Array for the signed transaction in this way:
writeU32(senderAdrresLength) // 32
writeBytes(senderAddress)
writeU64(sequenceNumber)
writeU32(payloadType) // 2 for program
writePeerToPeerHash() //constant
writeNumberOfArgumentsForProgram() // 2
writeArgumentType() // 0 for amount
writeU64(amount)
writeArgumentType() // 1 for address
writeU32(receiverAddressLength) // 32
writeBytes(receiverAddress)
writeU32(0) // no modules so length 0
writeU64(1000000) // maxGasAmount
writeU64(0) // gasUnitPrice
writeU64(expirationTime)

Now we have a RawTransaction and we create a public key and we create a signature from this transaction. These we add to the Uint8Array.

writeU32(publicKeyCount)
writeBytes(publicKey)
writeU32(signatureCount)
writeBytes(signature)

The generated Uint8Array is a signed transaction which we set in the proto SignedTransaction. Now we submit it for transfer. All seems fine as the signature is correct and when we change gas settings we can get the response that the gaslimit is to low. As said we are currently stuck at the majorStatus 11 error.

We have checked everything but we do not know what is causing this error. We are using the creatInsecure() setting for the grpc connection, but that used to work fine. I hope someone can shed a light on thing.

Cheers

2 Likes

Didn’t see what’s the problem.

But,you make sure writePeerToPeerHash is correct?
Before writing PeerToPeerHash also need to write the length of the U32.

Provide a PeerToPeerHash currently available:

{"code":[76,73,66,82,65,86,77,10,1,0,7,1,74,0,0,0,4,0,0,0,3,78,0,0,0,6,0,0,0,13,84,0,0,0,6,0,0,0,14,90,0,0,0,6,0,0,0,5,96,0,0,0,41,0,0,0,4,137,0,0,0,32,0,0,0,8,169,0,0,0,15,0,0,0,0,0,0,1,0,2,0,1,3,0,2,0,2,4,2,0,3,2,4,2,3,0,6,60,83,69,76,70,62,12,76,105,98,114,97,65,99,99,111,117,110,116,4,109,97,105,110,15,112,97,121,95,102,114,111,109,95,115,101,110,100,101,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,2,0,4,0,12,0,12,1,19,1,1,2],"args":[],"modules":[]}

Thank you for your quick reply. We are providing the length but maybe the hash is incorrect. We will investigate. Thanks!

The base64 output of this hash is: TElCUkFWTQoBAAcBSgAAAAQAAAADTgAAAAYAAAANVAAAAAYAAAAOWgAAAAYAAAAFYAAAACkAAAAEiQAAACAAAAAIqQAAAA8AAAAAAAABAAIAAQMAAgACBAIAAwIEAgMABjxTRUxGPgxMaWJyYUFjY291bnQEbWFpbg9wYXlfZnJvbV9zZW5kZXIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAIABAAMAAwBEwEBAg==
Are you sure this is correct?
We now get a 1020 “Actual Type Mismatch” error ;). We will investigate further

Seems that this indeed a correct p2pHash. So now we have an actual type mismatch. The investigation continues :smiley:

You are our new favorite hero!! Apparently the sequence of argument types is important as well. With this fixed we just made our first transaction. Thanks a BILLION! Transactions are working!

https://libexplorer.com/version/4800

1 Like

It seems the above peer to peer is correct, I use the same.

But I also got stuck for quite long time, still got “submit txn rejected”. I am quite sure that my raw txn bytes are correct, as well as signature bytes. But I doubted by signature bytes. Here how I prepare hash for signature.

const hash = sha3_256
    .update(
      Buffer.from(
        '46f174df6ca8de5ad29745f91584bb913e7df8dd162e3e921a5c1d8637c88d16',
        'hex'
      )
    )
    .update(message)
    .digest()

const signature = signKey.sign(hash).toBytes()

Where the message is raw txn bytes.
Still in the process of digging as well :slight_smile:

Seems correct to me. We use the same salt hash as you are using. Running into transaction rejected usually means your rawtransaction is incorrect. We have it working now. Probably for a week and then something else will break :smiley:

@olibaron Congrates for your success, and thank you for the info. I think I did the same steps as yours, still under investigate. Hope to succeed soon. :blush:

What we learned by digging through the Libra source code, is that sequence is very important. LCS is very fragile. Having a serializer and deserializer working together to check with existing transactions helped us in the reverse engineering of things. Little Endian is also something to look at

1 Like

I am not clear what your writePeerToPeerHash is and if it is what the name suggests then that may be the problem.
A transaction SignedTransaction -> RawTransaction in our codebase carries the compiled code in the Program payload and not the hash. Moreover please move to a Script payload because Program will be removed soon. The exact code to compile and submit can be found in the codebase under libra/language/stdlib/transaction_scripts/peer_to_peer_transfer.mvir.
Not sure if this is too terse and let us know if you want us to expand on this answer.
Also tagging @runtianz who has done a lot of work in this space lately

edit: it seems this was resolved and by looking at the binary for the program that looks like a compiled program so all may be good here, sorry I did not see the all the replies before posting mine… :slight_smile:

Given below transaction. I got LCS raw bytes code, but it still doesn’t go through, the submitted signed txn got ac_status “Rejected”.

const txnScript = {
    code: '4c49425241564d0a010007014a00000004000000034e000000060000000d54000000060000000e5a0000000600000005600000002900000004890000002000000008a90000000f00000000000001000200010300020002040200030204020300063c53454c463e0c4c696272614163636f756e74046d61696e0f7061795f66726f6d5f73656e6465720000000000000000000000000000000000000000000000000000000000000000000100020004000c000c0113010102',
    args: [
      { amount: 8000000 },
      {
        address:
          'c618ddea3030b4f94152a20b5c31df2f6e0ac42ef2ecf0ecb6c091fc08f1ffce'
      }
    ]
 }

const rawTxn = {
  address: '5d43fff83cfde40ac05c91575185bef36a714a93f86a2e799d4ee3c40185443c',
  sequenceNumber: 0,
  payload: txnScript,
  maxGasAmount: 140000,
  gasUnitPrice: 0,
  expirationTime: 1569591601
}

// base64
const privateKey = 'McvB8atpS+LpKz81FXq3ecJIFmvblYNG23+N84IU+h/HPqJ7Yvo1LbxjI7iFiJ1CNkmdOAZIVtensH20P2yGUg=='

const publicKey = 'xz6ie2L6NS28YyO4hYidQjZJnTgGSFbXp7B9tD9shlI='

Here is my LCS raw bytes.

[200000005d43fff83cfde40ac05c91575185bef36a714a93f86a2e799d4ee3c40185443c000000000000000002000000b80000004c49425241564d0a010007014a00000004000000034e000000060000000d54000000060000000e5a0000000600000005600000002900000004890000002000000008a90000000f00000000000001000200010300020002040200030204020300063c53454c463e0c4c696272614163636f756e74046d61696e0f7061795f66726f6d5f73656e6465720000000000000000000000000000000000000000000000000000000000000000000100020004000c000c0113010102020000000000000000127a00000000000100000020000000c618ddea3030b4f94152a20b5c31df2f6e0ac42ef2ecf0ecb6c091fc08f1ffce00000000e022020000000000000000000000000031118e5d00000000]

Can’t figure out what wrong.

The issue was fixed, it just because of me using outdated proto files. And as @olibaron said, the sequence of arguments is important, address must come before u64 for peer to peer txn. :grinning:

2 Likes

Thank you for your reply. Yes that was the issue. And thank you for mentioning moving over to the Script payload. This would have been a breaking change.