Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ and your life will be easier.
.Pull the latest docker image
[source,bash]
----
docker pull
just pull
----

.Run a script from terminal
Expand Down
25 changes: 25 additions & 0 deletions docs/_dev/reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,22 @@ extend_chain to: @alice
extend_chain num_blocks: 101, to: @bob
----

=== Reorganise Chain

You can also roll back a chain to a height or to a blockhash. You can
also rollback the chain up to a point to unconfirm a given
transaction - this enables you to broadcast and confirm the
transaction again along a different chain fork.

[source,ruby]
----
reorg_chain height: 95

reorg_chain blockhash: @blockhash

reorg_chain unconfirm_tx: @reorg_to_tx
----

=== Find Spendable Coinbase Transactions

To look up a coinbase UTXO controlled by a key use
Expand Down Expand Up @@ -258,6 +274,15 @@ assert_confirmed transaction: @alice_tx
assert_confirmed txid: @alice_tx.txid
----

=== Assert an Output is (not) Spent

[source,ruby]
----
assert_output_is_spent(transaction: @alice_tx, vout: 0)

assert_output_is_not_spent(transaction: @alice_tx, vout: 0)
----

`assert_confirmed` takes an optional `at_height` parameter to assert
if the transaction has been confirmed in the block at that height.

Expand Down
33 changes: 28 additions & 5 deletions docs/_dev/setup.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,32 @@
:page-nav_order: 5
:page-show-toc: false

1. Install Ruby using any means. I usually prefer using link:https://rvm.io/[RVM]
2. Install Rust.
3. Install `miniscript-cli` by `cd miniscript-cli && cargo intall --path .`.
This will give your DSL access to `miniscript-cli` binary.
4. Run your DSL scripts as `ruby lib/run.rb -s lib/simple.rb`
The easiest way to run Bitcoin DSL is using the docker image provided
on github.

Install
link:https://github.com/casey/just?tab=readme-ov-file#installation[Just]
and your life will be easier.


.Pull the latest docker image
[source,bash]
----
just pull
----

.Run a script from terminal
[source,bash]
----
# Run a script using pulled docker image
just run <path-to-your-script>

# Example, running the ARK single payment example
just run ./lib/contracts/ark/single_payment.rb
----

.Run Jupyter notebook
[source,bash]
----
just lab
----
8 changes: 6 additions & 2 deletions docs/justfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
default: build

default:
@just --list

publish: build
/usr/local/bin/aws s3 sync _site/ s3://opdup.com/bitcoin-dsl/ --delete --cache-control 'max-age=0'

build:
jekyll build

serve:
jekyll serve
3 changes: 2 additions & 1 deletion lib/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,8 @@
:walletlock,
:walletpassphrase,
:walletpassphrasechange,
:walletprocesspsb
:walletprocesspsb,
:invalidateblock
]

BITCOIN_HASHES = %i[hash160 sha256 hmac_sha256 hmac_sha512].freeze
56 changes: 56 additions & 0 deletions lib/contracts/reorg_chain.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright 2024 Kulpreet Singh
#
# This file is part of Bitcoin-DSL
#
# Bitcoin-DSL is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Bitcoin-DSL is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bitcoin-DSL. If not, see <https://www.gnu.org/licenses/>.

# frozen_string_literal: false

@alice = key :new

# Extend chain to 101, so Alice has a spendable coinbase
extend_chain to: @alice, num_blocks: 101

assert_height 101
@coinbase = spendable_coinbase_for @alice
assert_not_nil @coinbase

# Reorg by height
reorg_chain height: 95
assert_height 95

# Alice has no spendable coinbases anymore
@coinbase = spendable_coinbase_for @alice
assert_nil @coinbase

extend_chain num_blocks: 10

@blockhash = getblockhash height: 95

# Reorg by blockhash
reorg_chain blockhash: @blockhash
assert_height 95

@coinbase = spendable_coinbase_for @alice
assert_nil @coinbase

extend_chain num_blocks: 10

# Reorg by transaction
@reorg_to_tx = get_coinbase_at 98
reorg_chain unconfirm_tx: @reorg_to_tx
assert_height 98

@coinbase = spendable_coinbase_for @alice
assert_nil @coinbase
30 changes: 30 additions & 0 deletions lib/dsl/broadcast.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,36 @@ def extend_chain(to: nil, policy: nil, descriptor: nil, script: nil, num_blocks:
"Generated #{num_blocks} blocks"
end

# Looking at the lightning examples, it seems like it would be
# helpful to have a reorg_chain command along the lines of
# “extend_chain” that combines invalidateblock and generate and
# potentially replaces some previously confirmed transactions.
def reorg_chain(height: nil, blockhash: nil, unconfirm_tx: nil)
raise 'Provide height or blockhash to reorg' unless height || blockhash || unconfirm_tx

if unconfirm_tx
tx = getrawtransaction txid: unconfirm_tx.to_h['txid'], verbose: true
blockhash = tx['blockhash']
end

if blockhash
block = getblock blockhash: blockhash
height = block['height']
end

reorg_chain_to_height(height) if height
end

def reorg_chain_to_height(to_height)
current_height = get_height
raise 'Target height is more than current chain height' if current_height < to_height

(current_height..to_height + 1).step(-1).each do |height|
blockhash = getblockhash height: height
invalidateblock blockhash: blockhash
end
end

# Broadcast a transaction
def broadcast(transaction)
accepted = testmempoolaccept rawtxs: [transaction.to_hex]
Expand Down
2 changes: 1 addition & 1 deletion lib/dsl/query_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def spendable_coinbase_for(key, height: nil)
coinbase = get_coinbase_at h
return coinbase if coinbase['vout'][0]['scriptPubKey']['address'] == address
end
raise 'No coinbase found for the given key'
nil
end

def get_block_confirmed_at(transaction:)
Expand Down
42 changes: 42 additions & 0 deletions spec/dsl/broadcast_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Copyright 2024 Kulpreet Singh
#
# This file is part of Bitcoin-DSL
#
# Bitcoin-DSL is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Bitcoin-DSL is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Bitcoin-DSL. If not, see <https://www.gnu.org/licenses/>.

# frozen_string_literal: false

require 'bitcoin'
require_relative '../../lib/dsl/broadcast'
require_relative '../../lib/dsl'
require_relative '../../lib/node'

RSpec.describe Broadcast do
include DSL
include Broadcast

before(:context) do
@key1 = Bitcoin::Key.generate
@key2 = Bitcoin::Key.generate
end

before(:example) { node :reset }
after(:example) { node :stop }

describe 'Reorganising chain' do
it 'should raise error if neither height not blockhash is provided' do
expect { reorg_chain }.to raise_error('Provide height or blockhash to reorg')
end
end
end
4 changes: 4 additions & 0 deletions spec/runner_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,8 @@
it_behaves_like 'script evaluation', './lib/contracts/lightning/local_close_unilaterally__remote_sweeps_pending_htlc_using_revocation_key.rb'
it_behaves_like 'script evaluation', './lib/contracts/lightning/local_close_unilaterally__remote_sweeps_pending_htlc_using_preimage.rb'
end

describe 'reorg chain' do
it_behaves_like 'script evaluation', './lib/contracts/reorg_chain.rb'
end
end