3

Relevant Information before starting : I've seached stackoverflow already, and have found similar title questions, but I don't believe they are duplicates of mine, because they have a key difference, they seem to have objects which contain a reference to themselves, causing the circle. I don't have that. <-- Please read this instead of instantly marking as a dupe - I need real help with this.

EDIT : I have found the answer, but stackoverflow wont let me post the answer for a few days, turns out elliptic can only accept hex values - meaning that you would have to call it like this :

this.keyPair.sign(dataHash).toHex();

Leaving question below for anyone else who might have this issue going forward.

I have this javascript object :

Transaction {
  id: '2ec34280-567d-11e9-9685-4903db7a1a5b',
  type: 'TRANSACTION',
  input:
   { timestamp: 1554343126696,
     from:
      '6db64cd01c27a723395a833d72b3cc81f9110b5ffb34429d91f45fcbfd87ec9b',
     signature:
      Signature {
        eddsa: [EDDSA],
        _R: [Point],
        _S: [BN],
        _Rencoded: [Array],
        _Sencoded: undefined } },
  output: { to: 'rand-address', amount: 9, fee: 1 } }

When I try to do a res.json on it, I seem to get this error :

TypeError: Converting circular structure to JSON

Some code that may be relevant :

// Endpoint that a user accesses (the start of the event)
app.post("/transact", (req, res) => {
  const { to, amount, type } = req.body;
  const transaction = wallet.createTransaction(
    to,
    amount,
    type,
    blockchain,
    transactionPool
  );

  res.redirect("/transactions");
});

the createTransaction method which is mentioned above, looks like this :

  createTransaction(to, amount, type, blockchain, transactionPool) {
    this.balance = this.getBalance(blockchain);
    if (amount > balance) {
      console.log(
        `Amount: ${amount} exceeds the current balance: ${this.balance}`
      );
      return;
    }
    let transaction = Transaction.newTransaction(this, to, amount, type);
    transactionPool.addTransaction(transaction);
    return transaction;
  }

the newTransaction method :

  static newTransaction(senderWallet, to, amount, type) {
    if (amount + TRANSACTION_FEE > senderWallet.balance) {
      console.log(`Not enough balance`);
      return;
    }

    return Transaction.generateTransaction(senderWallet, to, amount, type);
  }

Which calls the generateTransaction method below :

  static generateTransaction(senderWallet, to, amount, type) {
    const transaction = new this();
    transaction.type = type;
    transaction.output = {
      to: to,
      amount: amount - TRANSACTION_FEE,
      fee: TRANSACTION_FEE
    };
    Transaction.signTransaction(transaction, senderWallet);
    return transaction;
  }

Which in turn calls the signTransaction method :

  static signTransaction(transaction, senderWallet) {
    transaction.input = {
      timestamp: Date.now(),
      from: senderWallet.publicKey,
      signature: senderWallet.sign(ChainUtil.hash(transaction.output))
    };
  }

the chainUtil hash function looks like this :

static hash(data){
    return SHA256(JSON.stringify(data)).toString();
}

The sign method on the wallet class :

  sign(dataHash){
    return this.keyPair.sign(dataHash);
  }

they all return and I get the object I mentioned at the top of this question. I'm not seeing how the issue is a circular error at all. Please, educate me.

Slippy
  • 1,253
  • 5
  • 22
  • 43
  • It's hard to say which part of your `console.log()` is circular, but generally I would say that it's a really great idea to take control of transforming your objects into a JSON-compatible structure manually yourself using only primitives (numbers, floats, boolean, null, array, object). You don't really want to rely on all your internal data structures to stay compatible and it's way too easy to leak irrelevant data. Chances are that the recusion is in `EDDSE`, `Point` or `BN`. – Evert Apr 04 '19 at 02:22
  • Are you assuming the `signature` property will be a string? It isn't right now – Evert Apr 04 '19 at 02:22
  • I am assuming that actually, yeah, and I did notice that it has "Signature" as a type going on there, which is confusing to me, because I haven't got a "Signature" custom type anywhere in my code... – Slippy Apr 04 '19 at 02:25
  • You must have a `.sign` method, no? That is what's returning the signature structure. – James Apr 04 '19 at 02:28
  • @James I do indeed have a .sign method, I thought I pasted it in the question, but I accidentally left it out, I have added that now, but I don't see how it would do anything overly weird? You see anything? Thanks for your help so far! – Slippy Apr 04 '19 at 02:49
  • Possible duplicate of [JSON.stringify, avoid TypeError: Converting circular structure to JSON](https://stackoverflow.com/questions/11616630/json-stringify-avoid-typeerror-converting-circular-structure-to-json) – Laxmikant Dange Apr 04 '19 at 02:52
  • @LaxmikantDange - I literally explained in the first sentence why it isn't. – Slippy Apr 04 '19 at 02:56
  • So you should 1) figure out what "signature" should be (some kind of string?), and then 2) figure out how to get that out of whatever object keypair.sign gives you. The json circular thing is just because you're not doing 1 and 2. – James Apr 04 '19 at 02:58
  • @James - I am investigating, thanks - I don't see a string inside the series of returned stuff, I'll keep looking, will post an answer if I come across one, it looks more like a bug in the elliptic library to me at the moment. – Slippy Apr 04 '19 at 03:30
  • @James I found the solution! Turns out the elliptic library needs you to do a toHex() on the value you are sending to it!! so the sign method needs to be returning like this : return this.keyPair.sign(dataHash).toHex(); – Slippy Apr 04 '19 at 05:32
  • I will add this as the answer when StackOverflow allows it! – Slippy Apr 04 '19 at 05:33
  • Brilliant question but for a moment there I thought the title said *"Epileptic"*. – Malekai Apr 04 '19 at 06:50
  • haha! @LogicalBranch - I am epileptic anyways, so there is likely a joke there somewhere! – Slippy Apr 05 '19 at 19:33

1 Answers1

0

I have found the answer, Turns out Elliptic only allows you to work with hex strings... so the change to make this work was in my wallet code, as follows :

this.keyPair.sign(dataHash).toHex();

Instead of

this.keyPair.sign(dataHash);
Slippy
  • 1,253
  • 5
  • 22
  • 43