Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add basic transaction data layout #55

Merged
merged 1 commit into from Jul 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions source/agora/common/Data.d
Expand Up @@ -24,3 +24,6 @@ public alias Hash = BitBlob!256;

/// A network address
public alias Address = string;

/// The type of a signature
public alias Signature = BitBlob!256;
89 changes: 89 additions & 0 deletions source/agora/common/Transaction.d
@@ -0,0 +1,89 @@
/*******************************************************************************

Defines the data structure of a transaction

The current design is heavily influenced by Bitcoin: as we have a UTXO,
starting with a simple input/output approach seems to make the most sense.
Script is not implemented: instead, we currently only have a simple signature
verification step.

Copyright:
Copyright (c) 2019 BOS Platform Foundation Korea
All rights reserved.

License:
MIT License. See LICENSE for details.

*******************************************************************************/

module agora.common.Transaction;

import agora.common.Data;
import agora.common.crypto.Key;


/*******************************************************************************

Currency amount type to use

This is simply an alias to `long` at the moment, and should be made smarter.
Currently this has two major drawbacks:
- It does not do any overflow / underflow checks (over the total amount)
- It can go negative
We should probably wrap this in a smarter type to do currency operations,
and move it to a shared location, as currency operations might be performed
independently of `Transaction`.

*******************************************************************************/

public alias Amount = long;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bitcoin seems to allow negative values (at least internally?), but I'm not sure why. Do you know?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not exactly. I imagine that might be related to dealing with a - b (remember Don hating on unsigned types ? ;) )

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah that's a very good point. I remember the implicit ulong => uint conversion in D1 as well. That was a fun deployment.


/*******************************************************************************

Represents a transaction (shortened as 'tx')

Agora uses a UTXO model for transactions, so the transaction format is
originally derived from that of Bitcoin.

*******************************************************************************/

public struct Transaction
{
/// The list of unspent `outputs` from previous transaction(s) that will be spent
public Input[] inputs;

/// The list of newly created outputs to put in the UTXO
public Output[] outputs;
}

/*******************************************************************************

Represents an entry in the UTXO

This is created by a valid `Transaction` and is added to the UTXO after
a transaction is confirmed.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does it mean that a transaction is confirmed, in this context? It should be documented.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's pretty standard Bitcoin jargon.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't understand though, what does it mean in this context? I know about the "6 confirmations rule", but is that related to this at all?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed == Included in a block

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it!


*******************************************************************************/

public struct Output
{
/// The monetary value of this output, in 1/10^7
public Amount value;

/// The public key that can redeem this output (A = pubkey)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(A = pubkey) - what? where does "A" come from?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oups shall remove

/// Note that in Bitcoin, this is an address (the double hash of a pubkey)
public PublicKey address;
}

/// The input of the transaction, which spends a previously received `Output`
public struct Input
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmmhm.. I dislike that you've ordered them as:

public struct Output { ... }
public struct Input { ... }

Can we make them Input and then Output instead? I know I'm nitpicking.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reasoning is that, while your approach is the natural approach, Input is actually defined in terms of Output, not the other way around. An Output never references an Input, but an Input always reference an Input. Output can exists without Input (Coinbase) but not the other way around.
It sounds backwards but that's the way it's done in BTC and I can't think of something better.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said, I don't mind changing the ordering at all, just wanted to provide a reasoning for the ordering.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that's fair.

{
/// The hash of a previous transaction containing the `Output` to spend
public Hash previous;

/// Index of the `Output` in the `previous` `Transaction`
public uint index;

/// A signature that should be verified using the `previous[index].address` public key
public Signature signature;
}