Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

sign & push transaction separately #306

Closed
MarcelBlockchain opened this issue Aug 14, 2018 · 8 comments
Closed

sign & push transaction separately #306

MarcelBlockchain opened this issue Aug 14, 2018 · 8 comments

Comments

@MarcelBlockchain
Copy link

Goal: be able to separately create, sign and broadcast a transaction:

Global for both approaches:

const privkey = '5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3';

Approach 1:

    transferSignPushTr1 : async (from, to, amount, memo) => {
      const options = {
        authorization: `${from}@active`, //@active for activeKey, @owner for Owner key
        //default authorizations will be calculated.
        broadcast: false,
        sign: false,
      };

      const transaction = await eos.transaction(
        'eosio.token',
        acc => {
          acc.transfer(from, to, amount, memo);
        },
        options
      );
      const data = transaction.transaction.transaction.actions[0].data;
      const sig = await ecc.sign(data, privkey);
      const trFinal = await eos.pushTransaction({ compression: 'none', transaction: transaction, signatures: sig })
    },

returns "Invalid packed transaction"
Possible problem. Wrong transaction file in eos.pushTransaction() or wrong data for ecc.sign(data, ...)

Approach 2:

    transferSignPushTr2 : async (from, to, amount, memo) => {
      const options = {
        authorization: `${from}@active`, //@active for activeKey, @owner for Owner key
        //default authorizations will be calculated.
        broadcast: false,
        sign: false,
      };

      const transaction = await eos.transaction(
        'eosio.token',
        acc => {
          acc.transfer(from, to, amount, memo);
        },
        options
      );
      const data = transaction.transaction.transaction.actions[0].data;
      const sig = await ecc.sign(data, privkey);
      transaction.transaction.signatures.push(sig);
      const trFinal = await eos.pushTransaction(transaction.transaction);
    },

returns :

api < error      { message:
   'transaction declares authority \'{"actor":"inita","permission":"active"}\', but does not have signatures for it under a provided delay of 0 ms, provided permissions [], and provided keys ["EOS7pDBdW8JeB8wxc9HyECgFtL3pYewYeimQ9uThoGLc1HE5cCikG"]',
  file: 'authorization_manager.cpp',
  line_number: 411,

possible problem:
ecc.sign() hast the wrong input. I tried to generate a digest as suggested here, but could not find the option in eosjs.
In https://github.com/EOSIO/eosjs/blob/v14.1.1/src/write-api.js#L406-L419 , a Buffer is used. I was not yet able to replicate it since I did not find the Transaction object/arg.

@MarcelBlockchain
Copy link
Author

Got the following answer. Gonna work on make it run using eosjs. The docs don't go so much into detail, I try to find more information about fcbuffer in the repo.

The EOS code uses fcbuffer to pack the transactions. Once packed, the packed data is combined with the chain ID and the Context Free Data to generate the signature. Specifically, the chain ID, packed data, and hash of the context free data are concatenated then run through the hash function. Once the hash is generated, it can be signed by the private key. An example, in Java, can be found on our GitHub page.

It is important to remember that the private key that signs the transaction must be the private key belonging to the user listed in the authorization section.

@jcalfee
Copy link
Contributor

jcalfee commented Aug 15, 2018

@jcalfee jcalfee added the help label Aug 15, 2018
@MarcelBlockchain
Copy link
Author

I did. It shows how to push separately. I'm interested in signing separately and then push it separately.

  1. transfer using sign: false, broadcast: false, OK
  2. sign it using ecc.sign(???, privKey) <----------------
  3. broadcast using pushTransaction(), OK

@aaroncox
Copy link

aaroncox commented Aug 16, 2018

@MarcelBlockchain You can use sign: true, broadcast: false with the transaction method of eosjs as one potential method.

https://github.com/greymass/eos-voter/blob/master/app/shared/actions/transaction.js#L113-L124

That's how we're currently doing it. Keep in mind that if it's an action on a contract besides eosio or eosio.token, and the machine is not connected to the eos network, you'll also need to pass along the ABI and add it to the ABI cache (shown on 116).

@MarcelBlockchain
Copy link
Author

@aaroncox I worked through the file. Helped me to understand more, but is not exactly what I'm looking for.
My JS file CAN (create), (create + sign (+ broadcast)), or just (broadcast). Solely the single step (sign) transaction does not work yet. I'm specifically looking for that.

@jcalfee
Copy link
Contributor

jcalfee commented Aug 22, 2018

You never need ecc.sign .. Just make the transaction and don't broadcast it. It returns the signature.

@jcalfee
Copy link
Contributor

jcalfee commented Aug 22, 2018

Use ecc.pushTransaction to broadcast separate from any other action.

@Marxpark
Copy link

Hi, i'm tackling the same issue and have a related question,

when you sign the transaction on the other device, as shown in the mentioned example, you have to give it the transaction headers and prepare the same action. So far so good. But what if i happen to want to prepare the transaction today, and sign it tomorrow, and broadcast it a day later... That seems to invalidate the signature because the headers use expiration time and it is set to max 1 hour... Is there a way to bypass and have the transaction valid for broadcasting indefinitely, so long as the appropriate signature is added at any point in time?

Thanks in advance.

@c0d3ster c0d3ster closed this as completed Apr 8, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants