clarity-lang / reference

The Clarity Reference
149 stars 34 forks source link

Natively retrieve burn chain & native transactions from `txid` #49

Closed Zk2u closed 3 years ago

Zk2u commented 3 years ago

Uses aliases defined in #48

Add functions to retrieve parsed burn chain & native transactions for use in contracts.

;; -------------------------------
;; getting burn chain transactions
;; -------------------------------

;; NOTE: the responses for these functions below are for bitcoin burn chain tx's
;; in appchain VMs, it will return the same response type as the native transactions 

(get-burn-tx? (txid (buff 32)))

(
    (txid (buff 32))
    (version uint)
    (locktime uint)
    (vin (list 16 (tuple
        (txid (buff 32))
        (vout uint)
        (prevout (tuple
            (pubkey (buff 32))
            (asm (ascii 1024))
            (type (ascii 8))
            (address (ascii 48))
            (value uint)
        ))
        (scriptsig (buff 4096))
        (asm (ascii 1024))
        (is-coinbase bool)
        (sequence uint)
    )))
    (vout (list 16 (tuple
        (pubkey (buff 32))
        (asm (ascii 1024))
        (type (ascii 8))
        (address (ascii 48))
        (value uint)
    )))
    (size uint)
    (weight uint)
    (fee uint)
    (status (tuple
        (confirmed bool)
        (block uint)
        (block-hash (buff 32))
        (block-time uint)
    ))
)

(get-burn-tx-compact? (txid (buff 32)))

(
    (txid (buff 33))
    (version uint)
    (locktime uint)
    (vin (list 16 (tuple
        (vout uint)
        (prevout (tuple
            (type (ascii 8))
            (address (ascii 48))
            (value uint)
        ))
        (is-coinbase bool)
    )))
    (vout (list 16 (tuple
        (type (ascii 8))
        (address (ascii 48))
        (value uint)
    )))
    (size uint)
    (weight uint)
    (fee uint)
    (status (tuple
        (confirmed bool)
        (block uint)
        (block-hash (buff 32))
        (block-time uint)
    ))
)

;; ---------------------------
;; getting native transactions
;; ---------------------------

(get-tx? (txid (buff 32)))

(
    (txid (buff 33))
    (failure bool)
    (success bool)
    (fee-rate uint)
    (sender principal)
    (sponsored bool)
    (pc-allow bool)
    (unanchored bool)
    (microblock (tuple
        (hash (buff 32))
        (sequence uint)
        (canonical bool)
    ))
    (block uint)
    (burn-block-time uint)
    (canonical bool)
    (tx-index uint)
    (result-hex (buff 32))
    (coinbase-payload (buff 32))
)
cryptopanter commented 3 years ago

So we have 3 functions here.. Would u pls explain a little what does each of them do?.. Tnx

Zk2u commented 3 years ago

So we have 3 functions here.. Would u pls explain a little what does each of them do?.. Tnx

(get-btc-tx? (txid (buff 32)))

Retrieves a bitcoin transaction that's parsed into a Clarity tuple, so a contract could call this function to get a Bitcoin transaction and easily verify if it was confirmed or not, the values of input addresses etc. This one has some more technical fields in it, so most of the time I'd expect contracts to use (get-btc-tx-compact? (txid (buff 32))) which takes out some of the lesser-used data to be less expensive

(get-tx? (txid (buff 32)))

Retrieves a Stacks transaction and parses it into a Clarity tuple. Same as above, but simpler (Stacks transactions are simpler to parse) so contracts can get data from a Stacks transaction (whether it's confirmed or not, who sent it etc)

Zk2u commented 3 years ago

We may have to add another function that is identical to get-tx? but is get-stx-tx? for app chains, so they can retrieve STX transactions (their burn chain), their own transactions (on the app chain) and bitcoin transactions (from the base layer).

On native Stacks, get-tx? and get-stx-tx? would be identical, but on burn chains they would retrieve a tx from their own chain and retrieve one from the Stacks chain respectively.

We can do this since each Stacks node needs a Bitcoin node to 'find' the Stacks blocks to download (the main reason you need to 51% Bitcoin in order to 51% Stacks, because Stacks nodes just steal the security of BTC by checking for its own blocks on the burn chain).

cryptopanter commented 3 years ago

Awesome! .. What about flash blocks or missed Bitcoin blocks?.. I mean those stacks blocks that miss their relevant anchored Bitcoin blocks and are sent to next.. Does that influence your logic?

Zk2u commented 3 years ago

What about flash blocks or missed Bitcoin blocks?... does that influence your logic?

No, since these aren't tied to one another. The Stacks/app chain node would retrieve the Bitcoin transaction from the Bitcoin node it's connected to (when retrieving Bitcoin transactions)

friedger commented 3 years ago

Naming could be get-burn-tx? and get-tx? where get-burn-tx? has a parameter for the level chains. On an app chain on an app chain on stx on btc you could call (get-burn-tx? 3 txid) to get a bitcoin tx. (get-burn-tx? 0 txid) would be equal to (get-tx? txid).

Zk2u commented 3 years ago

have updated this proposal with @friedger's suggestions

friedger commented 3 years ago

I think we need extra fields for segwit flag and witnesses in btc tx structure.

Zk2u commented 3 years ago

I think we need extra fields for segwit flag and witnesses in btc tx structure.

@friedger what would this look like?

Zk2u commented 3 years ago

@jcnelson what are your thoughts on this?

jcnelson commented 3 years ago

While I agree that Clarity programs should be able interact with any burnchain transaction, I don't think this is the right way to go about doing it.

First, this is expensive. In order for such methods to work reliably, the Stacks node would need to download and store not only every single Bitcoin transaction into its own chainstate, but also an index over them so that they could be efficiently queried by txid. This is at least 400 GB of extra space today -- over 30x the size of the Stacks chainstate.

Second, this is inefficient. Nearly every Bitcoin transaction will not be queried by Clarity smart contracts, so we'd be storing them for nothing. Even if every Stacks transaction from 2.1 onwards queried a unique Bitcoin transaction, it would take decades to query them all (since after all the Bitcoin chain is growing in tandem with the Stacks chain).

Instead, I think Clarity should have native methods for the following:

If it can do both of these things, then the system would achieve the goals of this issue: it would store only the Bitcoin transactions that Clarity programs actually need, and it would ensure that any stored Bitcoin transaction was actually mined in a Bitcoin block.

This can kinda-sorta be done in Clarity today, but it would be better to have native support since then the methods wouldn't be limited by Clarity's type system (i.e. you wouldn't need to know the lengths of any data in advance).

Zk2u commented 3 years ago

This sounds awesome. thinking about it, that is definitely the way to go.