├── .dockerignore ├── .flake8 ├── .gitignore ├── .ruby-version ├── 404.html ├── CNAME ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── Makefile ├── README.md ├── Rakefile ├── _config.yml ├── _data ├── settings.yml └── social-media.yml ├── _includes ├── footer.html ├── google-analytics.html ├── head.html ├── header.html ├── linkers │ └── meetings-pages.md ├── references.md └── social-media-links.html ├── _layouts ├── default.html ├── home.html ├── page.html ├── post.html └── pr.html ├── _plugins └── auto_logs_markup.rb ├── _posts ├── 2019-05-01-#15557.md ├── 2019-05-08-#10823.md ├── 2019-05-15-#15834.md ├── 2019-05-22-#15450.md ├── 2019-05-29-#15741.md ├── 2019-06-05-#16060.md ├── 2019-06-12-#15996.md ├── 2019-06-19-#15481.md ├── 2019-06-26-#15681.md ├── 2019-07-03-#15443.md ├── 2019-07-10-#16244.md ├── 2019-07-17-#15169.md ├── 2019-07-24-#15713.md ├── 2019-07-31-#15505.md ├── 2019-08-07-#16345.md ├── 2019-08-14-#16115.md ├── 2019-08-21-#15931.md ├── 2019-08-28-#15759.md ├── 2019-09-04-#16512.md ├── 2019-09-11-#16688.md ├── 2019-09-18-#15204.md ├── 2019-09-25-#16202.md ├── 2019-10-02-#16401.md ├── 2019-10-09-#16939.md ├── 2019-10-16-#16279.md ├── 2019-10-23-#15934.md ├── 2019-10-30-#15921.md ├── 2019-11-06-#15845.md ├── 2019-11-13-#17303.md ├── 2019-11-20-#16442.md ├── 2019-11-27-#16698.md ├── 2019-12-04-#16426.md ├── 2019-12-11-#16702.md ├── 2019-12-18-#17639.md ├── 2020-01-08-#14053.md ├── 2020-01-15-#17860.md ├── 2020-01-22-#17477.md ├── 2020-01-29-#17487.md ├── 2020-02-05-#18044.md ├── 2020-02-12-#16902.md ├── 2020-02-19-#17954.md ├── 2020-02-26-#17428.md ├── 2020-03-04-#16981.md ├── 2020-03-11-#17824.md ├── 2020-03-18-#18113.md ├── 2020-03-25-#18238.md ├── 2020-04-01-#18401.md ├── 2020-04-08-#18453.md ├── 2020-04-15-#18521.md ├── 2020-04-22-#17994.md ├── 2020-04-29-#18038.md ├── 2020-05-06-#18806.md ├── 2020-05-07-#18877.md ├── 2020-05-13-#17681.md ├── 2020-05-14-#18960.md ├── 2020-05-20-#15206.md ├── 2020-05-21-#19010.md ├── 2020-05-27-#19055.md ├── 2020-06-03-#16756.md ├── 2020-06-04-#19070.md ├── 2020-06-10-#19105.md ├── 2020-06-17-#18242.md ├── 2020-06-24-#18468.md ├── 2020-07-01-#18991.md ├── 2020-07-08-#19109.md ├── 2020-07-15-#19031.md ├── 2020-07-22-#15644.md ├── 2020-07-29-#17977.md ├── 2020-08-05-#19160.md ├── 2020-08-12-#17977-2.md ├── 2020-08-19-#19509.md ├── 2020-08-26-#19339.md ├── 2020-09-02-#17977-3.md ├── 2020-09-09-#18267.md ├── 2020-09-16-#19845.md ├── 2020-09-23-#19761.md ├── 2020-09-30-#18772.md ├── 2020-10-07-#19843.md ├── 2020-10-14-#19953.md ├── 2020-10-21-#19055-2.md ├── 2020-10-28-#20158.md ├── 2020-11-04-#19905.md ├── 2020-11-11-#19315.md ├── 2020-11-18-#20079.md ├── 2020-11-25-#19858.md ├── 2020-12-02-#19698.md ├── 2020-12-09-#20477.md ├── 2020-12-16-#19935.md ├── 2020-12-23-rc-testing.md ├── 2021-01-06-#20799.md ├── 2021-01-13-#19825.md ├── 2021-01-20-#20546.md ├── 2021-01-27-#20833.md ├── 2021-02-03-#20721.md ├── 2021-02-10-#18261.md ├── 2021-02-17-minisketch-#26.md ├── 2021-02-24-#21224.md ├── 2021-03-03-minisketch-#26-2.md ├── 2021-03-10-#20861.md ├── 2021-03-17-#21142.md ├── 2021-03-24-#19438.md ├── 2021-03-31-#21528.md ├── 2021-04-07-#21061.md ├── 2021-04-14-#14707.md ├── 2021-04-21-minisketch.md ├── 2021-04-28-#17331.md ├── 2021-05-05-#17526.md ├── 2021-05-12-#21767.md ├── 2021-05-19-#18418.md ├── 2021-05-26-#22006.md ├── 2021-06-02-#21527.md ├── 2021-06-09-#21800.md ├── 2021-06-16-#21603.md ├── 2021-06-23-#22261.md ├── 2021-06-30-#21090.md ├── 2021-07-07-#22363.md ├── 2021-07-14-#22350-gdb-notes.md ├── 2021-07-14-#22350.md ├── 2021-07-21-#22383.md ├── 2021-07-28-#22155.md ├── 2021-08-04-#22340.md ├── 2021-08-11-#20295.md ├── 2021-08-18-v22-rc-testing.md ├── 2021-08-25-#22665.md ├── 2021-09-01-#22675.md ├── 2021-09-08-#22009.md ├── 2021-09-15-#22677.md ├── 2021-09-22-#22871.md ├── 2021-09-29-#22950.md ├── 2021-10-06-#23157.md ├── 2021-10-13-#21943.md ├── 2021-10-20-#17631.md ├── 2021-10-27-#22674.md ├── 2021-11-03-#23173.md ├── 2021-11-10-#23280.md ├── 2021-11-17-#23319.md ├── 2021-11-24-#23512.md ├── 2021-12-01-#23614.md ├── 2021-12-08-#10102.md ├── 2021-12-08-#23443.md ├── 2021-12-15-#23724.md ├── 2021-12-29-#20827.md ├── 2022-01-05-#23534.md ├── 2022-01-12-#20726.md ├── 2022-01-19-#23201.md ├── 2022-01-26-#24007.md ├── 2022-02-02-libsecp256k1-#748.md ├── 2022-02-09-#24152.md ├── 2022-02-16-#23542.md ├── 2022-02-23-#24098.md ├── 2022-03-02-#24034.md ├── 2022-03-09-#19602.md ├── 2022-03-16-#24118.md ├── 2022-03-23-#21778.md ├── 2022-03-30-v23-rc-testing.md ├── 2022-04-06-#24571.md ├── 2022-04-13-#21726.md ├── 2022-04-20-#24538.md ├── 2022-04-27-#24644.md ├── 2022-05-04-#24584.md ├── 2022-05-11-#24410.md ├── 2022-05-18-#24148.md ├── 2022-05-25-#24148-2.md ├── 2022-06-01-#25228.md ├── 2022-06-08-#22778.md ├── 2022-06-15-#24170.md ├── 2022-06-22-#23418.md ├── 2022-06-29-#24832.md ├── 2022-07-06-#25077.md ├── 2022-07-13-#25380.md ├── 2022-07-20-#25218.md ├── 2022-07-27-#24858.md ├── 2022-08-03-#25527.md ├── 2022-08-10-#25720.md ├── 2022-08-17-#25665.md ├── 2022-08-24-#25768.md ├── 2022-08-31-#25600.md ├── 2022-09-07-#25957.md ├── 2022-09-14-#25991.md ├── 2022-09-21-#25880.md ├── 2022-09-28-v24-rc-testing.md ├── 2022-10-05-#26114.md ├── 2022-10-12-#26158.md ├── 2022-10-19-#25515.md ├── 2022-10-26-#26265.md ├── 2022-11-02-#26140.md ├── 2022-11-09-#23897.md ├── 2022-11-16-#25261.md ├── 2022-11-23-#26152.md ├── 2022-11-30-#26152-2.md ├── 2022-12-07-#25574.md ├── 2022-12-14-#26631.md ├── 2022-12-21-#26695.md ├── 2023-01-11-#26742.md ├── 2023-01-18-#26697.md ├── 2023-01-25-#26347.md ├── 2023-02-01-#26847.md ├── 2023-02-08-bitcoin-inquisition-#16.md ├── 2023-02-15-#26441.md ├── 2023-02-22-#25038.md ├── 2023-03-01-#25038-2.md ├── 2023-03-08-#25325.md ├── 2023-03-15-#27006.md ├── 2023-03-22-#27050.md ├── 2023-03-29-#26403.md ├── 2023-04-05-#27255.md ├── 2023-04-12-#27255-2.md ├── 2023-04-19-#27039.md ├── 2023-04-26-#27460.md ├── 2023-05-03-#27501.md ├── 2023-05-10-#26485.md ├── 2023-05-17-#27600.md ├── 2023-05-24-v25-rc-testing.md ├── 2023-05-31-#27145.md ├── 2023-06-07-#27711.md ├── 2023-06-14-#27625.md ├── 2023-06-21-#27748.md ├── 2023-06-28-#27307.md ├── 2023-08-02-#28122.md ├── 2023-09-06-#28165.md ├── 2023-10-04-#28107.md ├── 2023-11-01-#28368.md ├── 2023-11-15-v26-rc-testing.md ├── 2023-12-06-#28690.md ├── 2024-01-03-#28956.md ├── 2024-02-07-#28950.md ├── 2024-03-06-bitcoin-inquisition-#39.md ├── 2024-03-13-bitcoin-inquisition-#45.md ├── 2024-03-20-#29221.md ├── 2024-03-27-v27-rc-testing.md ├── 2024-05-01-#30000.md ├── 2024-06-05-#30132.md ├── 2024-07-03-#29775.md ├── 2024-08-07-#30352.md ├── 2024-09-11-v28-rc-testing.md ├── 2024-10-02-#30793.md ├── 2024-11-06-#30239.md ├── 2024-12-04-#31397.md ├── 2025-02-05-#31363.md ├── 2025-03-05-#31405.md ├── 2025-03-19-v29-rc-testing.md ├── 2025-04-02-#31689.md ├── 2025-04-09-#31664.md ├── 2025-04-16-#29532.md ├── 2025-04-23-#31444.md ├── 2025-04-30-#31981.md ├── 2025-05-07-#31375.md ├── 2025-05-14-#32317.md ├── 2025-05-28-#32051.md ├── 2025-06-04-#30605.md └── 2025-06-18-#31829.md ├── assets ├── css │ ├── 1-tools │ │ ├── _-tools-dir.sass │ │ ├── _code.scss │ │ ├── _normalize.scss │ │ ├── _social-media-icons.sass │ │ ├── _syntax.scss │ │ └── normalize │ │ │ ├── _import-now.scss │ │ │ ├── _normalize-mixin.scss │ │ │ ├── _variables.scss │ │ │ └── _vertical-rhythm.scss │ ├── 2-base │ │ ├── _-base-dir.sass │ │ └── _base.sass │ ├── 3-sections │ │ ├── _-sections-dir.sass │ │ └── _default.sass │ ├── Source+Code+Pro.css │ ├── all.sass │ └── font-awesome.min.css ├── fonts │ ├── Source+Code+Pro.ttf │ ├── fontawesome-webfont.ttf │ ├── fontawesome-webfont.woff │ └── fontawesome-webfont.woff2 ├── img │ ├── 18113-coins-table.png │ ├── 18267-signet.png │ ├── 19953-taproot.png │ ├── 20827-pruning.drawio.png │ ├── 22950-full.jpg │ ├── 22950-pimpl.png │ ├── 22950-pure-abstract.png │ ├── cluster219.jpg │ ├── cluster881.jpg │ ├── favicon.ico │ ├── minisketch-26-math-1.jpg │ ├── minisketch-26-math-2.jpg │ ├── minisketch-26-math-3.jpg │ ├── minisketch-26-math-4.jpg │ ├── package_cpfp.png │ ├── package_low_and_modified.png │ ├── package_mempool_examples.jpg │ ├── package_mixed_feerate.png │ ├── package_rich_parent.png │ ├── script_output_types_blank.png │ ├── script_output_types_sols.png │ └── twitter_card.png └── txt │ ├── 18960_1_log.txt │ ├── 22950-abstract-class.cpp │ ├── 22950-abstract-class.h │ ├── 22950-pimpl.cpp │ └── 22950-pimpl.h ├── code-of-conduct.md ├── contrib └── new_post.py ├── docker-compose.yml ├── hosting.md ├── index.md ├── meetings-authors.html ├── meetings-components.html ├── meetings-hosts.html ├── meetings-prs.html ├── meetings.html ├── test ├── test_helper.rb └── test_site_content.rb └── your-first-meeting.md /.dockerignore: -------------------------------------------------------------------------------- 1 | .git 2 | .gitignore 3 | .DS_Store 4 | _site 5 | .sass-cache 6 | .jekyll-cache 7 | .jekyll-metadata 8 | vendor 9 | .bundle 10 | Dockerfile 11 | docker-compose.yml 12 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | extend-ignore = 3 | E302 # expected 2 blank lines, found 1 4 | E501 # line too long (81 > 79 characters) 5 | E741 # ambiguous variable name 6 | E305 # expected 2 blank lines after class or function definition, found 1 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | .DS_Store 3 | .DS_Store? 4 | .Spotlight-V100 5 | .Trashes 6 | ._* 7 | .bundle 8 | .jekyll-cache/ 9 | .jekyll-metadata 10 | .sass-cache/ 11 | Icon? 12 | Thumbs.db 13 | _cache 14 | _site/ 15 | ehthumbs.db 16 | vendor 17 | 18 | # Vim Swap 19 | [._]*.s[a-v][a-z] 20 | [._]*.sw[a-p] 21 | [._]s[a-rt-v][a-z] 22 | [._]ss[a-gi-z] 23 | [._]sw[a-p] 24 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 3.4.0 2 | -------------------------------------------------------------------------------- /404.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: "404: Page not found" 4 | permalink: 404.html 5 | --- 6 | 7 |
8 |

404: Page not found

9 |
10 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | bitcoincore.reviews -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ruby:3.4-slim 2 | 3 | RUN apt-get update && apt-get install -y \ 4 | build-essential \ 5 | curl \ 6 | libcurl4-openssl-dev \ 7 | && rm -rf /var/lib/apt/lists/* 8 | 9 | WORKDIR /app 10 | 11 | COPY Gemfile* ./ 12 | 13 | RUN gem install bundler 14 | RUN bundle install 15 | 16 | EXPOSE 4000 17 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source "https://rubygems.org" 4 | 5 | # Jekyll 6 | gem "jekyll", "~> 3.10.0" 7 | gem "jekyll-paginate", "~> 1.1" 8 | gem "jekyll-sitemap", "~> 1.4" 9 | gem "jekyll-feed", "~> 0.17" 10 | gem "jekyll-seo-tag", "~> 2.8" 11 | gem "kramdown-parser-gfm", "~> 1.1" 12 | gem "logger", "~> 1.7" 13 | gem 'base64', '~> 0.2.0' 14 | gem 'bigdecimal', '~> 3.1.9' 15 | 16 | # Ruby make 17 | gem 'rake' 18 | 19 | # Testing 20 | gem 'minitest' 21 | gem 'minitest-reporters' 22 | gem 'color_pound_spec_reporter' 23 | 24 | # HTTP bindings to libcurl - https://github.com/taf2/curb 25 | gem 'curb' 26 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | addressable (2.8.7) 5 | public_suffix (>= 2.0.2, < 7.0) 6 | ansi (1.5.0) 7 | base64 (0.2.0) 8 | bigdecimal (3.1.9) 9 | builder (3.3.0) 10 | color_pound_spec_reporter (0.0.9) 11 | bundler 12 | minitest 13 | minitest-reporters (>= 0.14.24) 14 | rake 15 | colorator (1.1.0) 16 | concurrent-ruby (1.3.5) 17 | csv (3.3.3) 18 | curb (1.0.9) 19 | em-websocket (0.5.3) 20 | eventmachine (>= 0.12.9) 21 | http_parser.rb (~> 0) 22 | eventmachine (1.2.7) 23 | ffi (1.17.1) 24 | forwardable-extended (2.6.0) 25 | http_parser.rb (0.8.0) 26 | i18n (1.14.7) 27 | concurrent-ruby (~> 1.0) 28 | jekyll (3.10.0) 29 | addressable (~> 2.4) 30 | colorator (~> 1.0) 31 | csv (~> 3.0) 32 | em-websocket (~> 0.5) 33 | i18n (>= 0.7, < 2) 34 | jekyll-sass-converter (~> 1.0) 35 | jekyll-watch (~> 2.0) 36 | kramdown (>= 1.17, < 3) 37 | liquid (~> 4.0) 38 | mercenary (~> 0.3.3) 39 | pathutil (~> 0.9) 40 | rouge (>= 1.7, < 4) 41 | safe_yaml (~> 1.0) 42 | webrick (>= 1.0) 43 | jekyll-feed (0.17.0) 44 | jekyll (>= 3.7, < 5.0) 45 | jekyll-paginate (1.1.0) 46 | jekyll-sass-converter (1.5.2) 47 | sass (~> 3.4) 48 | jekyll-seo-tag (2.8.0) 49 | jekyll (>= 3.8, < 5.0) 50 | jekyll-sitemap (1.4.0) 51 | jekyll (>= 3.7, < 5.0) 52 | jekyll-watch (2.2.1) 53 | listen (~> 3.0) 54 | kramdown (2.5.1) 55 | rexml (>= 3.3.9) 56 | kramdown-parser-gfm (1.1.0) 57 | kramdown (~> 2.0) 58 | liquid (4.0.4) 59 | listen (3.9.0) 60 | rb-fsevent (~> 0.10, >= 0.10.3) 61 | rb-inotify (~> 0.9, >= 0.9.10) 62 | logger (1.7.0) 63 | mercenary (0.3.6) 64 | minitest (5.25.5) 65 | minitest-reporters (1.7.1) 66 | ansi 67 | builder 68 | minitest (>= 5.0) 69 | ruby-progressbar 70 | pathutil (0.16.2) 71 | forwardable-extended (~> 2.6) 72 | public_suffix (6.0.1) 73 | rake (13.2.1) 74 | rb-fsevent (0.11.2) 75 | rb-inotify (0.11.1) 76 | ffi (~> 1.0) 77 | rexml (3.4.1) 78 | rouge (3.30.0) 79 | ruby-progressbar (1.13.0) 80 | safe_yaml (1.0.5) 81 | sass (3.7.4) 82 | sass-listen (~> 4.0.0) 83 | sass-listen (4.0.0) 84 | rb-fsevent (~> 0.9, >= 0.9.4) 85 | rb-inotify (~> 0.9, >= 0.9.7) 86 | webrick (1.9.1) 87 | 88 | PLATFORMS 89 | ruby 90 | 91 | DEPENDENCIES 92 | base64 (~> 0.2.0) 93 | bigdecimal (~> 3.1.9) 94 | color_pound_spec_reporter 95 | curb 96 | jekyll (~> 3.10.0) 97 | jekyll-feed (~> 0.17) 98 | jekyll-paginate (~> 1.1) 99 | jekyll-seo-tag (~> 2.8) 100 | jekyll-sitemap (~> 1.4) 101 | kramdown-parser-gfm (~> 1.1) 102 | logger (~> 1.7) 103 | minitest 104 | minitest-reporters 105 | rake 106 | 107 | BUNDLED WITH 108 | 2.3.5 109 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: build 2 | 3 | clean: 4 | bundle exec jekyll clean 5 | 6 | preview: 7 | ## Don't do a full rebuild (to save time), but always rebuild index.html and meetings pages 8 | rm _site/index.html || true 9 | rm -rf _site/meetings* || true 10 | bundle exec jekyll serve --host 0.0.0.0 --future --drafts --unpublished --incremental 11 | 12 | build: 13 | bundle exec jekyll clean 14 | bundle exec jekyll build --future --drafts --unpublished 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bitcoin-core-review-club 2 | 3 | Simple Jekyll site for hosting the Bitcoin Core PR Review club at https://bitcoincore.reviews/. 4 | 5 | ## Development 6 | 7 | ### Using Docker (recommended) 8 | 9 | You'll need [Docker](https://docs.docker.com/get-docker/) and [Docker 10 | Compose](https://docs.docker.com/compose/install/) installed. 11 | 12 | * Clone the repository and go into the directory 13 | * Run `docker compose up preview` to start the development server with 14 | live reload 15 | * Go to http://localhost:4000 16 | 17 | ### Traditional Setup 18 | 19 | You'll need [Ruby and Jekyll](https://jekyllrb.com/docs/installation/) to run 20 | the site locally. Ruby 3.4 is recommended. Once they are set up: 21 | 22 | * Clone the repository and go into the directory 23 | * Run `bundle install` 24 | * Run `make preview` 25 | * Go to http://localhost:4000 26 | 27 | In case of any issues, don't hesitate to run the following to update rubygems, 28 | bundler, and dependencies: `gem update --system && gem update && bundle update` 29 | 30 | ## Making a new post 31 | 32 | See the [hosting.md](hosting.md) doc for how to create a post for an upcoming meeting. 33 | 34 | ## Changing Site Data 35 | 36 | All site configurations are either contained in `_config.yml` or `_data/settings.yml`. Some data is duplicated between the two due to the way Jekyll injects variables, so be sure to update both. 37 | 38 | ## Running the Test Suite 39 | 40 | To run all tests: `rake test` or just `rake` 41 | 42 | To run one test file: `rake TEST=test/test_site_content` 43 | 44 | To run an individual test in a test file: 45 | `rake TEST=test/test_site_content TESTOPTS=--name=test_site_displays_no_empty_nicks` 46 | 47 | Before running tests for the first time, you may need to run `bundle update`. 48 | 49 | Before running the `test_all_links` test (or all of the tests, which includes 50 | it), the site needs to be started up locally with `make preview`, or with `make 51 | clean preview` if any meeting logs were changed, to pre-render the logs through 52 | the `auto_logs_markup` plugin. 53 | 54 | ## Attributions 55 | 56 | Thanks to [LeNPaul](https://github.com/LeNPaul/jekyll-starter-kit) for the Jekyll starter kit this was forked from and to Will O'Beirne for pointing me in that direction. 57 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # To display all the available rake (Ruby make) tasks, run: 4 | # rake -T 5 | 6 | require 'rake/testtask' 7 | 8 | # To run all tests: 9 | # rake (or) rake test 10 | # 11 | # To run one test file: 12 | # rake test TEST=test/FILENAME 13 | # 14 | # To run an individual test in a test file: 15 | # rake test TEST=test/FILENAME TESTOPTS=--name=TEST_NAME 16 | # 17 | desc 'Run all tests with `rake` or `rake test`' 18 | task default: :test # Make test runner the default rake task. 19 | Rake::TestTask.new do |task| 20 | task.pattern = 'test/test_*.rb' 21 | end 22 | 23 | desc 'Deprecated, use ./contrib/new-post.py instead' 24 | namespace :posts do 25 | task :new do 26 | puts "Error: `rake posts:new` is deprecated, use `./contrib/new-post.py -h` instead" 27 | exit 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | # Build settings 2 | markdown: kramdown 3 | highlighter: rouge 4 | permalink: none 5 | plugins: [jekyll-paginate, jekyll-sitemap, jekyll-feed, jekyll-seo-tag] 6 | 7 | sass: 8 | sass_dir: assets/css 9 | style: :compressed 10 | 11 | # Site settings 12 | author: "Bitcoin Core PR Review Club contributors" 13 | coordinator: "[glozow](https://github.com/glozow) and [stickies-v](https://github.com/stickies-v)" 14 | coordinator_irc: "glozow or stickies-v" 15 | description: "A monthly review club for Bitcoin Core PRs" 16 | meeting_day: "Wednesday and Thursday" 17 | meeting_location: 'the #bitcoin-core-pr-reviews IRC channel on libera.chat' 18 | meeting_time: "17:00 UTC" 19 | title: "Bitcoin Core PR Review Club" 20 | twitter: 21 | card: summary 22 | username: BitcoinCorePRs 23 | twitter_username: BitcoinCorePRs 24 | url: "https://bitcoincore.reviews" 25 | 26 | # Exclude from processing 27 | exclude: 28 | - Gemfile 29 | - Gemfile.lock 30 | - Makefile 31 | - README.md 32 | - Rakefile 33 | - contrib/ 34 | - test/ 35 | 36 | defaults: 37 | - scope: 38 | path: "" ## all pages 39 | values: 40 | image: /assets/img/twitter_card.png 41 | 42 | permalink: :title 43 | -------------------------------------------------------------------------------- /_data/settings.yml: -------------------------------------------------------------------------------- 1 | title: 'Bitcoin Core PR Review Club' 2 | 3 | author: 4 | name: 'Bitcoin Core PR Review Club hosts' 5 | 6 | menu: 7 | - {name: 'Home', url: ''} 8 | - {name: 'Meetings', url: 'meetings/'} 9 | - {name: 'Code of Conduct', url: 'code-of-conduct/'} 10 | - {name: 'Hosting', url: 'hosting/'} 11 | -------------------------------------------------------------------------------- /_data/social-media.yml: -------------------------------------------------------------------------------- 1 | atom: 2 | href: 'feed.xml' 3 | title: 'Atom Feed' 4 | fa-icon: 'fa-rss' 5 | 6 | twitter: 7 | href: 'https://twitter.com/bitcoincoreprs' 8 | title: 'Twitter' 9 | fa-icon: 'fa-twitter-square' 10 | -------------------------------------------------------------------------------- /_includes/footer.html: -------------------------------------------------------------------------------- 1 | 6 | -------------------------------------------------------------------------------- /_includes/google-analytics.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /_includes/head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% if page.title == "home" %} 5 | {{ site.data.settings.title }} 6 | {% else %} 7 | {{ page.title }} | {{ site.data.settings.title }} 8 | {% endif %} 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | {% feed_meta %} 22 | 23 | 24 | {% seo %} 25 | 26 | 27 | -------------------------------------------------------------------------------- /_includes/header.html: -------------------------------------------------------------------------------- 1 |
2 | 8 | 15 |
16 | -------------------------------------------------------------------------------- /_includes/linkers/meetings-pages.md: -------------------------------------------------------------------------------- 1 | {% capture /dev/null %} 2 | 3 | {% assign path = page.path | remove: ".html" %} 4 | 5 | {% if path == "meetings" %} 6 | {% assign _index_links = _index_links | append: "by date" %} 7 | {% else %} 8 | {% assign _index_links = _index_links | append: "by date" %} 9 | {% endif %} 10 | 11 | {% if path == "meetings-prs" %} 12 | {% assign _index_links = _index_links | append: " | by PR number" %} 13 | {% else %} 14 | {% assign _index_links = _index_links | append: " | by PR number" %} 15 | {% endif %} 16 | 17 | {% if path == "meetings-components" %} 18 | {% assign _index_links = _index_links | append: " | by component" %} 19 | {% else %} 20 | {% assign _index_links = _index_links | append: " | by component" %} 21 | {% endif %} 22 | 23 | {% if path == "meetings-hosts" %} 24 | {% assign _index_links = _index_links | append: " | by host" %} 25 | {% else %} 26 | {% assign _index_links = _index_links | append: " | by host" %} 27 | {% endif %} 28 | 29 | {% if path == "meetings-authors" %} 30 | {% assign _index_links = _index_links | append: " | by author" %} 31 | {% else %} 32 | {% assign _index_links = _index_links | append: " | by author" %} 33 | {% endif %} 34 | 35 | {% endcapture %} 36 | | {{_index_links}} | 37 | -------------------------------------------------------------------------------- /_includes/references.md: -------------------------------------------------------------------------------- 1 | {% comment %}{% endcomment %} 2 | {% assign bips = 'https://github.com/bitcoin/bips/' %} 3 | [bips]: {{bips}} 4 | {% assign bitcoin_core = 'https://github.com/bitcoin/bitcoin' %} 5 | [bitcoin_core]: {{bitcoin_core}} 6 | {% assign libsecp256k1 = 'https://github.com/bitcoin-core/secp256k1' %} 7 | [libsecp256k1]: {{libsecp256k1}} 8 | -------------------------------------------------------------------------------- /_includes/social-media-links.html: -------------------------------------------------------------------------------- 1 | {% if site.data.social-media %} 2 |
3 | {% assign sm = site.data.social-media %} 4 | {% for entry in sm %} 5 | {% assign key = entry | first %} 6 | 7 | {% endfor %} 8 |
9 | {% endif %} 10 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include head.html %} 5 | 6 | 7 | 8 |
9 |
10 | {% include header.html %} 11 | {{ content }} 12 | {% include footer.html %} 13 |
14 |
15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /_layouts/home.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {{ content }} 6 | -------------------------------------------------------------------------------- /_layouts/page.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 |
7 | {{ content }} 8 |
9 |
10 | -------------------------------------------------------------------------------- /_layouts/post.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 |
6 |
7 |

{{ page.title }}

8 | 12 |

{{ content }}

13 |
14 |
15 | -------------------------------------------------------------------------------- /_layouts/pr.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | --- 4 | 5 | {% capture components %} 6 | {%- for comp in page.components -%} 7 | {{comp}}{% unless forloop.last %}, {% endunless %} 8 | {%- endfor -%} 9 | {% endcapture %} 10 | 11 | {% capture authors %} 12 | {%- for author in page.authors -%} 13 | {{author}} 14 | 15 | {% unless forloop.last %}, {% endunless %} 16 | {%- endfor -%} 17 | {% endcapture %} 18 | 19 |
20 |
21 |

{{ page.title }} ({{components}})

22 | 23 | 32 | 33 | {% if page.pr %} 34 |

35 | 36 | https://github.com/bitcoin/bitcoin/pull/{{ page.pr }} 37 | 38 |

39 | {% elsif page.link %} 40 |

41 | 42 | {{ page.link }} 43 | 44 |

45 | {% endif %} 46 | 47 |

48 | Host: 49 | {{ page.host }} 50 | 51 | {% unless authors == empty %} 52 |  -  53 | 54 | PR author{% if page.authors.size > 1 %}s{% endif %}: {{authors}} 55 | 56 | {%- endunless -%} 57 |

58 | 59 | {% if page.status == "past" %} 60 | {% if page.commit %} 61 |

The PR branch HEAD was {{ page.commit }} at the time of this review club meeting.

62 | {%- endif -%} 63 | {%- endif -%} 64 | 65 |

66 | {{ content }} 67 |

68 |
69 |
70 | -------------------------------------------------------------------------------- /_plugins/auto_logs_markup.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'uri' 4 | 5 | module Jekyll 6 | class IRCBlock < Liquid::Block 7 | # Convert IRC meeting logs from plain text to HTML with functional links 8 | # and log lines by enclosing them in {% irc %} and {% endirc %} tags. 9 | 10 | # URI schemes to accept for extraction. 11 | URI_SCHEMES = %w(http https).freeze 12 | 13 | # Trailing chars (all punctuation except "/") to remove from URIs. 14 | TRAILING = /[^\/[:^punct:]]+$/ 15 | 16 | # Regex to select lines starting with "HH:MM " time. 17 | HH_MM = /^([0-1][0-9]|[2][0-3]):[0-5][0-9] .*/ 18 | 19 | # Regex to select IRC . 20 | IRC_NICK = /^(?:\s*)(<.+?>)/ 21 | 22 | # Regex to select "<" and ">" chars. 23 | LT_GT = /[<>]/ 24 | 25 | # Maximum digits to display for log lines. 26 | LINE_DIGITS = 3 27 | 28 | # Length of timestamp string being used. 29 | TIME_SIZE = 'HH:MM'.size 30 | TIME_SIZE_PLUS_1 = TIME_SIZE + 1 # Micro-perf optimization 31 | 32 | NON_BREAKING_SPACE = ' ' 33 | 34 | COLORS = %w(brown goldenrod cadetblue chocolate cornflowerblue coral crimson 35 | forestgreen darkblue firebrick blue green grey hotpink indianred indigo 36 | blueviolet maroon mediumblue mediumpurple mediumseagreen navy fuchsia 37 | olive orchid purple red seagreen sienna orange slateblue peru salmon teal 38 | magenta steelblue rebeccapurple tomato violet darkcyan).freeze 39 | 40 | NUM_COLORS = COLORS.size.freeze 41 | 42 | def initialize(tag_name, text, tokens) 43 | super 44 | end 45 | 46 | def render(context) 47 | output = super 48 | 49 | # Reset color data for each post. Seed the index with part of the content. 50 | colors, color_index = {}, (output[-256..-250] || '').bytes.sum 51 | 52 | # Loop through each line of the meeting logs. 53 | output.gsub!(HH_MM).with_index(1) do |line, index| 54 | 55 | # Separate the log line into useful parts. 56 | lineno = "#{NON_BREAKING_SPACE * (LINE_DIGITS - index.to_s.size)}#{index}" 57 | time = line[0..TIME_SIZE] 58 | name = IRC_NICK.match(line[TIME_SIZE_PLUS_1..-1]).to_s 59 | nick = name.gsub(LT_GT, '').strip 60 | color = colors[nick] || (color_index = (color_index + 1) % NUM_COLORS ; 61 | colors[nick] = COLORS[color_index]) 62 | nick = "<#{nick}>" unless nick == '' 63 | message = CGI.escapeHTML(line[TIME_SIZE_PLUS_1 + name.size..-1]) 64 | 65 | # Extract URIs from the message and convert them to HTML links. 66 | URI.extract(message, schemes = URI_SCHEMES).each do |uri| 67 | link = uri.sub(TRAILING, '') # Strip unwanted trailing punctuation 68 | message.sub!(link, "#{link}") 69 | end 70 | 71 | # Return the log line as HTML markup. 72 | "" \ 73 | "" \ 74 | "" \ 75 | "" \ 76 | "" \ 80 | "" \ 81 | "
#{lineno}#{time}" \ 77 | "#{nick}" \ 78 | "#{message}" \ 79 | "
" 82 | end 83 | 84 | output 85 | end 86 | end 87 | end 88 | 89 | Liquid::Template.register_tag('irc', Jekyll::IRCBlock) 90 | -------------------------------------------------------------------------------- /_posts/2019-05-22-#15450.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | title: "Create wallet menu option" 4 | components: ["gui"] 5 | pr: 15450 6 | authors: [achow101] 7 | host: jnewbery 8 | status: past 9 | --- 10 | 11 | ## Notes 12 | 13 | - Bitcoin uses QT for its GUI. The minimum version is 5.5. [Online documentation](https://doc.qt.io/archives/qt-5.5/index.html). 14 | - This PR is one of the last in a series of multiwallet PRs. The first of those was [#8694](https://github.com/bitcoin/bitcoin/pull/8694) which added multiwallet support through the RPC interface and was merged in June 2017. 15 | - Adding the various multiwallet functions (create/open/close wallet) at runtime is tracked by [Issue 13059](https://github.com/bitcoin/bitcoin/issues/13059). 16 | - We already have UI support for opening and closing wallets. This PR adds UI support for creating wallets. 17 | - Creating wallets dynamically is relatively new functionality (merged in [#13058](https://github.com/bitcoin/bitcoin/pull/13058) in June 2018). There have been a couple of additional options added to the `createwallet` RPC since it was added: [Disable private keys](https://github.com/bitcoin/bitcoin/pull/9662), [Blank wallets](https://github.com/bitcoin/bitcoin/pull/15226) and [born-encrypted wallets](https://github.com/bitcoin/bitcoin/pull/15006). 18 | - This PR was opened before the born-encrypted wallets PR was merged, so potentially could be simplified now that the functionality exists within the wallet component. 19 | - For GUI PRs, I always like to build and manually test the PR to get a sense of what the new UI functionality feels like. If you're testing on the same machine that you run your mainnet node on, REMEMBER TO MOVE OR BACKUP YOUR WALLET/DATADIR BEFORE TESTING! 20 | - Feel free to leave feedback on UI PRs about usability as well as comments on the code. 21 | 22 | ## Meeting Log 23 | 24 | {% irc %} 25 | 13:02 < jnewbery> hi! 26 | 13:02 < dmkathayat_> Hi! 27 | 13:02 < davterra> Hi! 28 | 13:02 < ariard> hi 29 | 13:03 < peevsie> yo 30 | 13:03 < jnewbery> Today's PR is https://github.com/bitcoin/bitcoin/pull/15450 31 | 13:03 < pinheadmz> buenos dias 32 | 13:03 < emzy> Hi 33 | 13:03 < michaelfolkson> What up. Head spinning trying to work out how all these PRs overlap lol 34 | 13:03 < jnewbery> I wrote my review notes here: https://bitcoin-core-review-club.github.io/15450.html to save us some time at the start of the meeting 35 | 13:03 < jonatack> hi 36 | 13:04 < jnewbery> So rather than me talking for 5 minutes now, let's just get straight into questions 37 | 13:04 < jonatack> is no testing for qt a thing 38 | 13:05 < jnewbery> Most qt PRs don't include tests 39 | 13:05 < jnewbery> But there are some in src/qt/test 40 | 13:06 < MarcoFalke> Yeah, and those are more like gui unit tests, not actual gui tests 41 | 13:07 < MarcoFalke> Currently the only way to test the GUI is by running it by hand 42 | 13:08 < michaelfolkson> So to confirm I understand what is going on. You can currently create a new independent HD wallet using bitcoind but until now you couldn't using Qt. Qt can't leverage bitcoind RPC so the C++ code needs to be written afresh for Qt in addition to editing the GUI? 43 | 13:10 < jnewbery> michaelfolkson: we try to make the RPC layer as thin as possible so functionality can be shared between RPC and QT. Here's the createwallet RPC: https://github.com/bitcoin/bitcoin/blob/1c177c3a004f91eca743bb3a0dd9534a544026d5/src/wallet/rpcwallet.cpp#L2642 44 | 13:10 < jnewbery> You can see that it's mostly just parsing arguments and then calling CWallet::CreateWalletFromFile() which does the heavy lifting 45 | 13:11 < jnewbery> This PR adds a new method to the node interface called createWallet() which basically does the same stuff 46 | 13:11 < jnewbery> https://github.com/bitcoin/bitcoin/pull/15450/files#diff-7e7292143c1cc2b4125d85f1ae5cf046R261 47 | 13:12 < jonatack> thanks! i suppose then that units are added for any new non-qt code. seem might still be good to add e2e tests for the user flows. 48 | 13:12 < jonatack> unit tests 49 | 13:12 < jnewbery> jonatack: Yes, I think that would be valuable contribution 50 | 13:12 < jonatack> end to end functional ones? 51 | 13:12 < jnewbery> yes 52 | 13:12 < jonatack> ty 53 | 13:13 < jnewbery> I don't know anything about testing QT 54 | 13:13 < jnewbery> But I imagine there's documentation on the QT website 55 | 13:13 < MarcoFalke> Indeed, I'd welcome any progress in that direction 56 | 13:13 < jnewbery> michaelfolkson: to follow up on my comment in the review notes "This PR was opened before the born-encrypted wallets PR was merged, so potentially could be simplified now that the functionality exists within the wallet component. 57 | 13:13 < MarcoFalke> I don't know if there are existing framworks 58 | 13:14 < jnewbery> You can see here: https://github.com/bitcoin/bitcoin/pull/15450/files#diff-fef859e81d3321e85221891fd768efadR75 that there's some duplication of logic for creating an encrypted wallet 59 | 13:16 < jnewbery> that logic now exists in the wallet RPC: https://github.com/bitcoin/bitcoin/blob/master/src/wallet/rpcwallet.cpp#L2710 . Perhaps this could be factored out of there into wallet.cpp and then shared by the RPC and QT 60 | 13:16 < michaelfolkson> : Thanks, that's useful. I wasn't expecting to see any C++ code for this PR, I was expecting to just be looking at GUI design. But I forgot that Qt wasn't just a front end 61 | 13:16 < jnewbery> I'm not entirely sure of that though. I haven't checked whether there are subtle differences in what logic is required for QT and RPC 62 | 13:17 < jnewbery> Yep, it's all C++ 63 | 13:19 < jnewbery> Did everyone manage to build the PR and do some manual testing? 64 | 13:19 < jnewbery> Any questions about that? 65 | 13:20 < jnewbery> I guess that's it for today. Short meeting! 66 | 13:20 < jnewbery> Before we go, does anyone have requests for future PRs to cover? 67 | 13:21 < jonatack> i compiled but didn't run it yet because i didn't see it in root or source 68 | 13:21 < jonatack> any pointers ? 69 | 13:21 < jnewbery> jonatack: it should be at src/qt/bitcoin-qt 70 | 13:21 < jnewbery> if not, perhaps you're not configured to build the qt binary. Check the output from when you ran `configure` 71 | 13:22 < jnewbery> You should see: 'with gui / qt = yes' 72 | 13:22 < jonatack> all good 73 | 13:22 < emzy> I had no time to do it. Maybe I will check it later. 74 | 13:22 < michaelfolkson> For the creating blank empty wallets PR, what's the motivation for doing this? Importing a seed from elsewhere? 75 | 13:22 < jonatack> i never run qt, thanks for the tpi 76 | 13:22 < jonatack> tip 77 | 13:22 < michaelfolkson> #15226 78 | 13:23 < jnewbery> michaelfolkson: by default, a new wallet will generate an HD seed 79 | 13:23 < MarcoFalke> To follow up on the "How to test the GUI" question earlier: The only framework I am aware of is used by operating systems: OpenQA. I think it is a Open Suse in-house product. See https://openqa.opensuse.org/tests/940238#step/bootloader/3 80 | 13:23 < jnewbery> if you want to import your own seed, you can create a blank wallet and then import 81 | 13:24 < jnewbery> another motivation: when you encrypt the wallet, it'll create a new seed, so if you created a wallet that wasn't blank, you'd have a seed from before encryption and then a seed from after encryption, which perhaps you don't want 82 | 13:25 < jnewbery> #15226 also made #15006 (Add option to create an encrypted wallet) much simpler 83 | 13:25 < jonatack> thanks marco 84 | 13:25 < ariard> I had a a more general question which is on travis build process, I often get a timeout error "Error! Initial build successful, but not enough time..." What's the process to do after that ? Force-push new branch tip? 85 | 13:26 < MarcoFalke> Created an issue for that https://github.com/bitcoin/bitcoin/issues/16075 86 | 13:26 < MarcoFalke> jonatack: et al ^ 87 | 13:26 < ariard> Do this also mean things have been modified which make tests longer to run ? 88 | 13:26 < jonatack> MarcoFalke: nice 89 | 13:26 < jnewbery> ariard: Yes, I believe force-pushing the branch will trigger a rebuild on travis 90 | 13:27 < jnewbery> just run `git commit --amend` to update the timestamp and then `git force push` 91 | 13:27 < jonatack> today's pr has seen no activity since 3 months. 92 | 13:28 < ariard> jnewbery: thanks for tip! 93 | 13:28 < jonatack> does achow have too much on his plate, does he need more help 94 | 13:28 < jonatack> or is it not a priority 95 | 13:29 < jnewbery> It might just not be a priority for him. I know he has a PR for a descriptor-based wallet, which is large and more important 96 | 13:29 < jonatack> right 97 | 13:30 < jnewbery> In general, if you see PRs that haven't had attention from their author for a while, there's nothing wrong in offering to take over maintaining the PR 98 | 13:32 < jnewbery> any other questions? 99 | 13:32 < jonatack> MarcoFalke: 100 | 13:32 < jonatack> do you plan to resubmit a pr 101 | 13:32 < jonatack> for the f tests speedup 102 | 13:32 < jonatack> you had 2 103 | 13:32 < michaelfolkson> achow is overseeing the Bitcoin Core hardware wallet interface too isn't he? That is ongoing 104 | 13:33 < MarcoFalke> jonatack: Good question. Not sure if we are allowed to discuss other prs here 105 | 13:33 < MarcoFalke> jnewbery: ? ^ 106 | 13:33 < jonatack> related to ariard's q 107 | 13:33 < jnewbery> Is it directly related to this week's PR? If not, I think #bitcoin-core-dev is the better place to discuss it (so all interested parties can see it) 108 | 13:34 < jonatack> ok 109 | 13:35 < jonatack> qt is now running for me ty for the help jnewbery 110 | 13:36 < jnewbery> michaelfolkson: yes, achow maintains HWI 111 | 13:36 < jnewbery> jonatack: great! 112 | 13:36 < jnewbery> ok, unless there are any final questions, let's wrap it up. 113 | 13:37 < jnewbery> Thanks all! See you next week 114 | 13:37 < emzy> Tnx! 115 | 13:37 < jonatack> cheers! thanks everyone 116 | 13:38 < michaelfolkson> A quick final question? :) 117 | 13:38 < jnewbery> go for it! 118 | 13:39 < jnewbery> michaelfolkson: was 'A quick final question?' the final question or is there a question after that question? 119 | 13:40 < michaelfolkson> So what are next steps for advancing this? Someone who understands the code for the GUI needs to oversee all the merge conflicts between these different PRs? 120 | 13:40 < michaelfolkson> Sorry yes 121 | 13:40 < jnewbery> Which different PRs? This one doesn't currently conflict with anything 122 | 13:40 < michaelfolkson> And there needs to be more feedback on the design. I saw Sjors gave some suggestions for what the UI should be 123 | 13:41 < michaelfolkson> I was seeing a bunch of conflicts on one of the PRs you linked to 124 | 13:42 < jnewbery> Yeah, i think it's still appropriate to give design feedback at this stage 125 | 13:42 < jonatack> michael: perhaps adding a recent review can kick the pr back into action 126 | 13:42 < jnewbery> I agree. achow will probably be more motivated to work on it if he knows there are people keen to review 127 | 13:44 < michaelfolkson> Ok cool. It is just design considerations now right? 128 | 13:44 < jnewbery> No, the code needs review too 129 | 13:44 < jnewbery> all aspects of the PR 130 | 13:45 < michaelfolkson> Ok understood, thanks 131 | 13:45 < michaelfolkson> Ok I'll let you go, many thanks 132 | 13:46 < jnewbery> ok, thanks again. See you all next time! 133 | {% endirc %} 134 | -------------------------------------------------------------------------------- /_posts/2019-09-11-#16688.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | title: "Add validation interface logging" 4 | components: ["utils/log/libs"] 5 | pr: 16688 6 | authors: [jkczyz] 7 | host: jkczyz 8 | status: past 9 | --- 10 | 11 | ## Notes 12 | 13 | - The 14 | [validation layer](https://github.com/bitcoin/bitcoin/blob/0d20c42a014ff95aab1447a92605c3a194cfeecc/src/validation.cpp) 15 | enforces Bitcoin's consensus rules. 16 | - It processes blocks and transactions from the net processing layer and updates the validated 17 | chain state (`CChainState`) and mempool (`CTxMemPool`). 18 | - Clients can subscribe to updates from the validation layer using the [`CValidationInterface`](https://github.com/bitcoin/bitcoin/blob/0d20c42a014ff95aab1447a92605c3a194cfeecc/src/validationinterface.h#L56). 19 | - The validation layer notifies `CValidationInterface` subscribers whenever the mempool or chainstate is updated. Some interface methods are (see *validationinterface.cpp* for the full list of interface methods): 20 | - [`UpdatedBlockTip`](https://github.com/bitcoin/bitcoin/blob/0d20c42a014ff95aab1447a92605c3a194cfeecc/src/validationinterface.h#L87) (fired once when the block chain is extended with one or more new blocks) 21 | - [`BlockConnected`](https://github.com/bitcoin/bitcoin/blob/0d20c42a014ff95aab1447a92605c3a194cfeecc/src/validationinterface.h#L111) (fired once for every block added to the block chain. The notification includes the serialized block with transactions) 22 | - [`TransactionAddedToMempool`](https://github.com/bitcoin/bitcoin/blob/0d20c42a014ff95aab1447a92605c3a194cfeecc/src/validationinterface.h#L93) (fired whenever a new transaction is accepted into the mempool. The notification includes the serialized transaction) 23 | 24 | ## Questions 25 | 26 | - What's the reason for adding logging to event notification? 27 | - What mechanism is used to notify listeners of validation events? 28 | - What code implements `CValidationInterface`? What does it use event 29 | notifications for? 30 | - What is a `CBlockLocator`? How is it used in this PR? How else is it used? 31 | - What refactorings are included in this PR? 32 | - How can this PR be tested? Could any other tests have been added? 33 | 34 | ## Meeting Log 35 | 36 | {% irc %} 37 | 13:00 < jkczyz> hi 38 | 13:00 < sosthene> nah it certainly comes from my side, happens all the time 39 | 13:00 < lightlike> hi 40 | 13:00 < jnewbery> hi 41 | 13:00 < b10c> hi 42 | 13:00 < udiWertheimer> jnewbery: that’s dedication! 43 | 13:00 < emzy> Hi 44 | 13:01 < jkczyz> As jnewbery noted, I'm guest hosting today. He may be around to help with the finer points :) 45 | 13:01 < jnewbery> udiWertheimer: haha. I'm going to duck out in a few minutes. Just wanted to make sure jkczyz has everything he needs to get started 46 | 13:01 < jkczyz> Today we’re reviewing PR #16688, which adds logging to validation layer’s event notification 47 | 13:01 < jkczyz> The validation layer processes blocks and transactions from the net processing layer and updates the validated chain state and mempool 48 | 13:02 < jkczyz> Any initial thoughts on this PR? 49 | 13:03 < jnewbery> I think it's great, and definitely going to be helpful for debugging issues as we move towards a more modular architecture 50 | 13:04 < jkczyz> jnewbery: Glad I can help in even a small way! While this is a fairly simple change, there are some lessons we can learn about the code through it 51 | 13:05 < jkczyz> Alright, let's jump into the questions 52 | 13:05 < jkczyz> What’s the reason for adding logging to event notification? 53 | 13:06 < sosthene> I guess it helps debugging? 54 | 13:07 < jkczyz> sosthene: correct, what sort of issues can it help debug? 55 | 13:07 < jnewbery> specifically, since the CValidationInterface is asynchronous, it can help with debugging threading issues and race conditions 56 | 13:07 < lightlike> it helps with error analysis, especially in case of race conditions, which appear in functional tests sometimes. 57 | 13:07 < emzy> There was a race condition where it would had helpd to debug. 58 | 13:07 < sosthene> In fact I wonder why there wasn't any log to begin with, as it seems a pretty critical part of Bitcoin to me. 59 | 13:08 < jkczyz> jnewbery, emzy: correct! Specifically it could have helped with issue #12978 60 | 13:08 < jkczyz> https://github.com/bitcoin/bitcoin/issues/12978 61 | 13:08 < lightlike> ironically, there is a is a race condition in the TSAN Travis build of this PR (which seems unrelated though) 62 | 13:08 < jkczyz> Here there was a race condition resulting in UpdatedBlockTip() signals delivered out of order 63 | 13:08 < jnewbery> sosthene: I agree this is critical, but for historic context, the CValidationInterface was updated about a year ago by Matt. Before then, I think it wasn't asynchronous (I may be wrong) 64 | 13:09 < jnewbery> bitcoind is (mostly) single threaded on the Message Handler thread. As we try to make it more multi-threaded, better logging at the interfaces is going to be more important 65 | 13:10 < jkczyz> lightlike: Yes, appears to be so. I thought about force pushing to see if there was some flakiness to the test 66 | 13:10 < jnewbery> I've got to head out now. Bye! 67 | 13:11 < jkczyz> jnewbery: Bye! Thanks for stopping in 68 | 13:11 < jkczyz> ok, next question: What mechanism is used to notify listeners of validation events? 69 | 13:11 < lightlike> jkczyz: i looked at it a little. seems related to https://github.com/bitcoin/bitcoin/issues/16133 70 | 13:12 < jkczyz> lightlike: cool, thanks for investigating! I'll have to look at that issue 71 | 13:13 < jkczyz> Hint: it uses a third-party library 72 | 13:15 < lightlike> don't know about it in depth, but via callback functions 73 | 13:16 < sosthene> I'm not even sure to quite get the question 74 | 13:16 < jkczyz> lightlike: yes, it uses callbacks, specifically with the boost:signals2 library 75 | 13:16 < jkczyz> https://www.boost.org/doc/libs/1_71_0/doc/html/signals2.html 76 | 13:17 < jkczyz> sosthene: The code in question is a bit tricky to reason through. I had to draw out a diagram to be honest! 77 | 13:17 < jkczyz> https://github.com/bitcoin/bitcoin/blob/d0f81a96d9c158a9226dc946bdd61d48c4d42959/src/validationinterface.cpp 78 | 13:17 < jkczyz> Ok, let's move on to some more interesting questions 79 | 13:18 < jkczyz> What code implements CValidationInterface? What does it use event notifications for? 80 | 13:18 < jkczyz> There are many correct answers to this one 81 | 13:19 < lightlike> the wallet does, for tracking the status of wallet transactions 82 | 13:21 < jkczyz> lightlike: yes, though this interface is adapted by NotificationsHandlerImpl for use by the wallet 83 | 13:21 < jkczyz> https://github.com/bitcoin/bitcoin/blob/9ab9d6356938ffe069ffc005a371d5405976823e/src/interfaces/chain.cpp#L158 84 | 13:22 < sosthene> what about the networking part? I guess you need to know if a peer is feeding you invalid blocks or tx? 85 | 13:24 < jkczyz> sosthene: correct, PeerLogicValidation (net processing layer) makes use of notificaitons to send peers new data and to validate peer messages (I believe :) 86 | 13:25 < jkczyz> On the wallet-side, using event notification helps with separation betweeen node and wallet functionality 87 | 13:25 < jkczyz> anything else? 88 | 13:25 < sosthene> I see it implemented in the BaseIndex class too, but I'm not too sure about what it does 89 | 13:25 < sosthene> https://github.com/bitcoin/bitcoin/blob/e4beef611a423e9f836fa210a51634e94f14d830/src/index/base.h 90 | 13:26 < jkczyz> sosthene: Good find! It uses BlockConnected and ChainStateFlushed to write to on-disk indexes 91 | 13:27 < sosthene> I see 92 | 13:28 < jkczyz> The remaining uses are not as important as these, but they are still interesting to look at 93 | 13:28 < sosthene> I see it also mentioned in the transaction.h file 94 | 13:28 < sosthene> https://github.com/bitcoin/bitcoin/blob/be0e8b4bff88b421128239e7140fc6bfdb654806/src/node/transaction.h 95 | 13:28 < jkczyz> submitblock RPC, ZMQ notificaitons, withing tests. 96 | 13:29 < lightlike> sosthene: my understanding is that the validation routines are called from the networking part (net_processing.cpp), and if we are sent something invalid, validationinterface will never be involved. 97 | 13:30 < sosthene> lightlike: I don't quite understand sorry, how do we know we have been sent something invalid without involving validationinterface? 98 | 13:33 < jkczyz> I may have been mistaken earlier about validating peer messages. Net processing will call the validation layer. Then only if the validation succeeds do subscrivers get notified 99 | 13:33 < lightlike> sosthene: we have a network thread that receives the messages. net_processing deals with the logic around these, and if we get a new block or tx, calls procedures in validation. Only if these procedures pass, validation will create signals for validationinterface that are passed on to the wallet etc. 100 | 13:34 < jkczyz> lightlike: yes, put more eloquently :) 101 | 13:34 < sosthene> lightlike: ok, it makes more sense, thanks! 102 | 13:34 < jkczyz> Alright, let's move on 103 | 13:34 < jkczyz> What is a CBlockLocator? How is it used in this PR? How else is it used? 104 | 13:37 < lightlike> jkczyz: i have encountered it in networking/getblocks messages, where it is used to determine the point up to which the chains of two peers are identical (for example in IBD when one peer has only part of the chain). 105 | 13:38 < sosthene> I found this, it makes sense with what lightlike says https://github.com/bitcoin/bitcoin/blob/78dae8caccd82cfbfd76557f1fb7d7557c7b5edb/src/primitives/block.h 106 | 13:39 < jkczyz> lightlike: yes, also in getheaders 107 | 13:39 < lightlike> https://github.com/bitcoin/bitcoin/blob/78dae8caccd82cfbfd76557f1fb7d7557c7b5edb/src/chain.cpp#L23 shows the logic behind it, how the internal vector of block hashes is filled 108 | 13:39 < jkczyz> See details: https://en.bitcoin.it/wiki/Protocol_documentation#getblocks 109 | 13:40 < jkczyz> lightlike: great! I was just about to ask how it was constructed 110 | 13:40 < jkczyz> Any insight into why it is constructed in that manner? 111 | 13:42 < lightlike> i think it's quite elegant, with the exponential thinning out: most of the time, two peers are just a few blocks away, so all the recent blocks are there. in rarer cases, where the chains differ strongly, multiple locators need to be exchanged to get the highest common block. 112 | 13:43 < jkczyz> lightlike: good observation! This is a nice way to limit the amount of data exchanged between peers. 113 | 13:43 < lightlike> jkczyz: do you know if satoshi came up with it? 114 | 13:44 < jkczyz> The locators are also used when writing to the on-disk block index 115 | 13:45 < jkczyz> lightlike: I'm afraid that predates my involvement. :) Checking out Github's blame layer might help determine the origin, though you may have to do some code archeology as the code has probably been moved from other files 116 | 13:46 < jkczyz> Back to one of the original questions: How is CBlockLocator used in this PR? 117 | 13:47 < lightlike> just to get the first element (which is the tip) 118 | 13:48 < sosthene> I see it in ChainStateFlushed, but I don't understand what it does 119 | 13:48 < jkczyz> lightlike: yup, this is logged as part of ChainStateFlushed. 120 | 13:50 < sosthene> jkczyz: I got to go, I'll read the transcript to get the end of the story, thank you and see you! 121 | 13:50 < jkczyz> sosthene: My understanding is that this is written to the on-disk index. I may be mistaken so others may correct me, but I believe this will give a compact path of block back to the genessis block 122 | 13:50 < lightlike> looks like everyone is at Scaling Bitcoin today :-) 123 | 13:51 < jkczyz> sosthene: thanks for joining! 124 | 13:51 < jkczyz> lightlike: indeed :) 125 | 13:51 < jkczyz> Hopefully there are some lurkers following along, too 126 | 13:52 < jkczyz> ok, let's finish up the last couple questions 127 | 13:52 < jkczyz> What refactorings are included in this PR? 128 | 13:53 < jkczyz> Hint: see the commits from the PR 129 | 13:54 < lightlike> MempoolEntryRemoved is renamed to TransactionRemovedFromMempool, some String functions are changed to return a const ref 130 | 13:54 < jkczyz> yep, fairly trivial changes but good for code hygiene 131 | 13:55 < jkczyz> Lastly, as we are running out of time: How can this PR be tested? Could any other tests have been added? 132 | 13:56 < lightlike> not sure about that one. I think there is some mechanism to check for log messages in functional tests. 133 | 13:57 < jkczyz> lightlike: yeah, I remember seeing that in the PR that logged bitcoind's args 134 | 13:58 < jkczyz> Here, I manually verified the logging through the p2p_compactblocks.py functional test 135 | 13:59 < lightlike> though i am not sure if testing log messages is a bit overkill. 136 | 13:59 < jkczyz> This was the flaky test from issue 137 | 13:59 < jkczyz> issue #12978 138 | 13:59 < jkczyz> https://github.com/bitcoin/bitcoin/issues/12978 139 | 13:59 < jkczyz> lightlike: agreed 140 | 14:00 < jkczyz> Other testing may be unit tests for newly added code 141 | 14:00 < jkczyz> And that's the bell! 142 | 14:00 < jkczyz> Thanks lightlike and sosthene for participating today! 143 | 14:00 < lightlike> by the way you don't have to force push for a new travis run. you could ask in #bitcoin-core-dev, several people can restart it. 144 | 14:00 < lightlike> thanks jkczyz! 145 | 14:01 < jkczyz> As jnewbery would want, please added any interesting PR's to https://github.com/bitcoin-core-review-club/bitcoin-core-review-club.github.io/issues/14 146 | 14:01 < jkczyz> So they can be covered in future weeks 147 | 14:01 < jkczyz> lightlike: Thanks! This was fun :) 148 | 14:02 < lightlike> jkczyz: gonna review/ack on github in the next days. 149 | {% endirc %} 150 | -------------------------------------------------------------------------------- /_posts/2020-12-23-rc-testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2020-12-23 4 | title: "Testing Bitcoin Core 0.21 Release Candidates" 5 | components: ["tests"] 6 | host: jarolrod 7 | status: past 8 | --- 9 | 10 | ## Notes 11 | 12 | - Major versions of Bitcoin Core are released every 6-8 months. See the [Life 13 | Cycle documentation](https://bitcoincore.org/en/lifecycle/) for full details. 14 | 15 | - When all of the PRs for a release have been merged, _Release Candidate 1_ 16 | (rc1) is tagged. The rc is then tested. If any issues are found, fixes are 17 | merged into the branch and a new rc is tagged. This continues until no major 18 | issues are found in an rc, and that rc is then considered to be the final 19 | release version. 20 | 21 | - To ensure that users don't experience issues with the new software, it's 22 | essential that the rcs are thoroughly tested. This special review club 23 | meeting is for people who want to help with that vital review process. 24 | 25 | - This [Bitcoin Core Release Candidate Testing 26 | Guide](https://gist.github.com/jarolrod/6495932dc6b598ddef49e6374b348f4e) has 27 | a tutorial for testing the release candidate. 28 | 29 | ## Meeting Log 30 | 31 | {% irc %} 32 | 18:00 #startmeeting 33 | 18:00 It’s a Christmas Miracle! The Bitcoin Core PR Review Club has returned for a Special Edition on testing the upcoming 0.21 release 34 | 18:00 You have been enlisted to ensure the upcoming Bitcoin Core 0.21 Release is ready for production by going through some of its changes. 35 | 18:00 Here are your mission instructions: https://gist.github.com/jarolrod/6495932dc6b598ddef49e6374b348f4e 36 | 18:00 If you accept this mission, send a ‘hi’ in the chat. (Also so that we know who’s here) 37 | 18:00 hi 38 | 18:00 hi 39 | 18:00 hi 40 | 18:00 hi 41 | 18:01 Hi 42 | 18:01 hi 43 | 18:01 Is anyone here for the first time? 44 | 18:01 hi 45 | 18:01 hi 46 | 18:01 Yes 47 | 18:01 hello there anastasiia, welcome! 48 | 18:02 I have linked to the guide, does everyone have it open? 49 | 18:02 hi 50 | 18:02 Yes 51 | 18:03 Sure do 52 | 18:03 yes 53 | 18:03 Yes 54 | 18:03 yes 55 | 18:03 Great. For all who’ve enlisted, here is a a magnifying glass, notebook, and pen. Let’s start inspecting! 56 | 18:04 Those here for the first time: If any question pops up, just go right ahead and say it. You don’t need to ask in order to ask a question. 57 | 18:04 We will begin with the section titled ‘Preparation’ 58 | 18:04 You have the option of grabbing the release candidate binary or compiling from source code. 59 | 18:05 we'll wait for everyone to get there copy of the release candidate 60 | 18:05 hi 61 | 18:06 hi 62 | 18:06 Any preference on the side of the core devs? I'm guessing the preference from the tester should be compile from source code 63 | 18:08 hey there fodediop and sishir, we're just getting started. We're grabbing the rc candidate from the testing guide 64 | 18:08 I downloaded the binary and checked the SHA256 hash of the binary against the gitian build. 65 | 18:09 compiling is preferred, but compiling can take some time depending on the machine. Those who are not comfortable with compiling should grab the binary 66 | 18:10 hi 67 | 18:10 emzy: 🎉 68 | 18:11 welcome felixweis 69 | 18:11 emzy: did you use https://github.com/fanquake/core-review/tree/master/gitian-building to check that or the docs on bitcoin core? 70 | 18:13 ajonas: I have still an old setup for the gitian builds. It is this https://github.com/bitcoin-core/docs/blob/master/gitian-building.md 71 | 18:14 hi 72 | 18:14 By "old" you mean it shouldn't be followed anymore? 73 | 18:14 For the macOS binary, how do we specify using the /tmp/21-rc-test data directory on launch? 74 | 18:14 is the apple signing bug for rc3 tracked somewhere? 75 | 18:15 jonatack: welcome! 76 | 18:15 michaelfolkson: istm the goal is to test the binaries, as that is what most people will use...happy to be corrected on that 77 | 18:16 jarolrod: thanks ✨ 78 | 18:17 michaelfolkson: good question. I think the docker one from fanquake seems to be easier to set up. 79 | 18:17 nevermind 80 | 18:18 does everyone have a copy of the current release candidate? 81 | 18:18 murtyjones: you can specify the data directory by passing -datadir=PATH on the command line or datadir=PATH in the bitcoin.conf configuration filse 82 | 18:18 file 83 | 18:19 murtyjones: /Applications/Bitcoin-Qt.app/Contents/MacOS/Bitcoin-Qt -datadir=/tmp/21-rc-test 84 | 18:19 thanks! 85 | 18:22 The testing guide is divided into four missions: `Testing the Wallet`, `Testing Torv3`, `Signet`, and `Anchors` 86 | 18:22 As you go through each section, please bring up any questions or problems that arise 87 | 18:22 one thought, the guide says to test the GUI or the command line per your preference, but if you can it's good to test both, as there can be issues in one and not the other 88 | 18:25 To be inclusive, some people may not be too comfortable with the command line. If you are able to test both, then great! 89 | 18:26 In the .dmg for macOS is afaik only the GUI version included. So I only tested that. 90 | 18:29 emzy: AFAIK that is correct 91 | 18:30 the tor conf can be more minimal, e.g. no need to set onlynet=onion 92 | 18:31 jonatack: I think it is important so see that you can bootstrap from tor only. 93 | 18:31 nor proxy/bind either in some cases 94 | 18:32 I can still do the testing for 0.21 on testnet version right? 95 | 18:33 hmrawal: yep, the testnet chain is fine, and definitely try signet too 96 | 18:33 jonatack: sure 97 | 18:34 hmrawal: the tor part in the document adds some mainnet tor V3 onions. They will not work for testnet. 98 | 18:34 should it take a while to connect to peers using tor? my node has been stuck on "Connecting to peers" for a bit and nodes keep appearing and disappearing from the "Peers" window 99 | 18:34 emzy: that's true 100 | 18:34 signet does IBD much faster 101 | 18:34 signet starts up much faster too. my go-to for quick manual testing. 102 | 18:34 felixweis: because of smaller blocks ;) 103 | 18:35 murtyjones: yes connecting to tor can take some time, we've supplied some torv3 nodes in the bitcoin.conf to try to get around this 104 | 18:35 You can't see which connections are anchor in the GUI or CLI (getpeerinfo etc)? 105 | 18:35 (y) 106 | 18:36 btw. I'm running sxjbhmhob2xasx3vdsy5ke5j5jwecmh3ca4wbs7wf6sg4g2lm3mbszqd.onion 107 | 18:36 windows -> network traffic 108 | 18:36 michaelfolkson: the anchor connections will be the initial block-only peers. you can see them easily with ./src/bitcoin-cli -netinfo 4 109 | 18:37 not sure but how much size is required in signet 110 | 18:37 emzy: which net? 111 | 18:38 felixweis: mainnet 112 | 18:38 can you run a signet instance too please? 113 | 18:39 emzy: just connected to you 114 | 18:39 felixweis: hm. Maybe on another host. This box is busy with the mainnet :) 115 | 18:39 if anyone wants to connect to emzy, run this on the command line: 116 | 18:39 ./src/bitcoin-cli addnode sxjbhmhob2xasx3vdsy5ke5j5jwecmh3ca4wbs7wf6sg4g2lm3mbszqd.onion onetry 117 | 18:39 jonatack: I see one onion connection incomming. 118 | 18:40 emzy: the subversion should have @jon at the end 119 | 18:40 for those on the tor section, here's some extra-credit work 120 | 18:40 1. Running `bitcoind` with the `-debug=tor` configuration option lets you see useful info on the onion configuration 121 | 18:40 2. This release includes a dashboard that lets you see useful network information. Instead of `getpeerinfo`, one can run `-netinfo 4` 122 | 18:40 jonatack: yes: "70016/Satoshi:21.99.0(@jon)/" 123 | 18:40 thanks jonatack for the tips 124 | 18:41 yes, -debug=tor is handy for seeing in the debug log if your tor setup has any issues or is working ok 125 | 18:42 it's not too noisy logging-wise so i always use it 126 | 18:44 felixweis: signet: 4sk25djzsqqscnv4yfbbntiuo6xxbmddfweppmpc6p6wlt33p36iluyd.onion 127 | 18:45 Have to drop off but thanks jarolrod! 128 | 18:45 murtyjones: thanks for testing! 129 | 18:46 jarolrod: this idea and guide and the one by ajonas is great. taking action, testing PRs and releases, and reporting feedback are a valuable part of reviewing. 130 | 18:47 I have started signet, says connecting to peers . Is there some config that we should do beforehand ? 131 | 18:47 Presumably those are temporary Tor nodes you've put up emzy. Would be good to know of a persistent Signet Tor node when doing Tor testing 132 | 18:48 (outside of this session) 133 | 18:48 hmrawal: the main config is to enable signet in your bitcoin.conf, one note is that for many it takes some time to connect as it is a new network 134 | 18:48 emzy, thanks still trying to get tor working 135 | 18:48 i have 4 tor v3 onion peers in signet ATM 136 | 18:48 hmrawal: emzy put up a signet tor node in the chat, you can addnode it 137 | 18:49 michaelfolkson: I could move the onions to some server. If people are interested. 138 | 18:49 Persistent jonatack? Can I have one? :) 139 | 18:49 two testing 0.21.0 and two running master (0.21.99) 140 | 18:49 qlci54ryrj6ywxgki5vvf45fwtp3yhdxxftgnhczvo37qpc2abqcjoid.onion:38333 141 | 18:49 Thanks 142 | 18:49 v7ajjeirttkbnt32wpy3c6w3emwnfr3fkla7hpxcfokr3ysd3kqtzmqd.onion:38333 143 | 18:49 jonatack: thank you! ✨ 144 | 18:49 those two are 0.21 145 | 18:49 hx3x3dhdxd5jbz5popeydcehuj5bpekztoya5b7ymvidlvgj6ean6pid.onion:38333 146 | 18:49 lktswnpsh3b7ctsvnf7xrjfbesho5l7i3fds2kwvmzufjv7mzgrgoiid.onion:38333 147 | 18:50 They are running on VPS? 148 | 18:50 those two are 0.21.99 (master), i think most of them are persistent, maybe run by kalle or aj 149 | 18:52 With < 10 min left, are people close to being able to leave their comment on #20555? 150 | 18:52 Okay, I need a little help. I am running bitcoin qt and in another tab in terminal I entered jonatack's terminal command to add emzy's node but I get an error saying I need to start bitcoind server 151 | 18:53 hmrawal: iirc you cannot use bitcoin-cli to talk to bitcoin-qt 152 | 18:53 hmrawal: try entering it on the GUI (bitcoin qt) console 153 | 18:54 as jonatack said 154 | 18:54 jarolrod: you can, if bitcoin-qt was started with -server option 155 | 18:54 or you an add to your conf and restart 156 | 18:54 sipa: thanks, didn't know that! 157 | 18:54 hmrawal: on the GUI you have to use the console window (in bitcoin-qt) and type "addnode 4sk25djzsqqscnv4yfbbntiuo6xxbmddfweppmpc6p6wlt33p36iluyd.onion onetry" 158 | 18:55 ^^ for a signet node 159 | 18:55 We're getting close to time everyone, 5 minutes! 160 | 18:56 Thanks everyone for testing, but the mission is not done! 161 | 18:57 please report back your findings here: https://github.com/bitcoin/bitcoin/issues/20555 162 | 18:57 got tor working, was :9150 for some reason 163 | 18:57 are there any peers to connect for later testing ? 164 | 18:57 felixweis: are you on windows? 165 | 18:57 felixweis: that's the port tor-browser is using. 166 | 18:57 macos tor brwoser 167 | 18:58 afaik Port 9150 is the default one of tor browser 168 | 18:58 hmrawal2008: you have mainnet tor v3 peers in the guide, and signet ones here in the discussion 169 | 18:58 On making a comment on the issue page: list your hardware and operating system, the rc version you tested, what you were able to test, and what you found while testing 170 | 18:58 so will these peers be available for later use also right ? 171 | 18:59 If everything went well, that's great! let us know 172 | 18:59 I will have mine up for a few weeks. 173 | 18:59 (i don't see any tor v3 peers in testnet ATM) 174 | 18:59 testnet is just too large for IBD :( signet all the way! 175 | 19:00 That's time everyone!, thanks for participating, happy holidays! 176 | 19:00 hmrawal2008: yes, worth trying to connect to them, emzy's mainnet ones are stable and i think the signet ones are stable, too 177 | 19:00 thanks jarolrod for hosting :) 178 | 19:01 #endmeeting 179 | 19:01 thanks jarolrod, great initiative 🍰 180 | 19:01 thanks jarolrod! 181 | 19:01 thanks jarolrod 182 | 19:01 cool thanks, thanks jarolrod, thanks everyone and merry christmas 183 | 19:01 thank you everyone! happy holidays and happy new year! 184 | 19:01 thanks jarolrod! 185 | 19:01 Thanks jarolrod for hosting.... Happy Holidays and Merry Christmas everyone 186 | 19:02 🎄 187 | 19:03 Thanks jarolrod for hosting.... Happy Holidays and Merry Christmas everyone. See you 2021. 188 | {% endirc %} 189 | -------------------------------------------------------------------------------- /_posts/2021-09-15-#22677.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2021-09-15 4 | title: "Cut the validation <-> txmempool circular dependency" 5 | pr: 22677 6 | authors: [glozow] 7 | components: ["p2p", "validation", "mempool"] 8 | host: glozow 9 | status: past 10 | commit: ab3fef71e 11 | --- 12 | 13 | ## Notes 14 | 15 | * A [circular dependency](https://en.wikipedia.org/wiki/Circular_dependency) exists when two or more 16 | modules depend on each other. [PR#13695](https://github.com/bitcoin/bitcoin/pull/13695) added a 17 | linter which statically analyzes files to detect circular dependencies. At the time, a few already 18 | existed and were listed in 19 | [`EXPECTED_CIRCULAR_DEPENDENCIES`](https://github.com/bitcoin/bitcoin/blob/053a5fc7d912d597cd6dc7376b479420d1eae1c0/test/lint/lint-circular-dependencies.sh#L11). 20 | 21 | * One of the circular dependencies in the codebase is validation <-> txmempool. These two modules 22 | are each heavily depended on by other modules, so their interdependency creates a "domino effect" 23 | into the rest of the codebase. To experience this for yourself, compile (with ccache), make a small 24 | edit to protocol.h (where P2P protocol messages are defined), then run `make` again and watch it 25 | rebuild txmempool and everything mempool-related. 26 | 27 | * [PR#22677](https://github.com/bitcoin/bitcoin/pull/22677) removes this dependency by removing 28 | txmempool's dependency on validation. It creates a `GetFiltered()` function that allows 29 | validation and other clients to pass in an arbitrary predicate, iterates through all of its entries, 30 | applies the predicate function to each of them, and returns the set of filtered iterators to mempool 31 | entries. This allows validation to apply consensus rules to all of the mempool entries without 32 | access to the mempool's internals. 33 | 34 | ## Questions 35 | 36 | 1. Did you review the PR? [Concept ACK, approach ACK, tested ACK, or 37 | NACK](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#peer-review)? 38 | 39 | 2. What is a circular dependency? Why should we avoid circular dependencies? 40 | 41 | 3. What functionality lives in validation? What functionality lives in txmempool? 42 | 43 | 4. Why should/shouldn't validation depend on txmempool? Why should/shouldn't txmempool depend on 44 | validation? 45 | 46 | 5. One of the functions that causes txmempool to rely on validation is the `check()` function. What 47 | checks does it perform, and how does this PR split the checks into two categories? 48 | 49 | 6. Another function that causes txmempool to rely on validation is the `removeForReorg()` function, 50 | which calls `CheckSequenceLocks()` and `CheckFinalTx()`. Why do we need to re-check sequence 51 | locks in a reorg? How is it possible for a coinbase spend to become premature in a reorg? 52 | 53 | 7. [Clang Thread Safety Analysis 54 | annotations](https://github.com/bitcoin/bitcoin/blob/92aad5303b9b96c46015156b5dc96b48e9e7bc76/doc/developer-notes.md#threads-and-synchronization) 55 | give compile-time warnings about potential race conditions. How do we let the compiler know whether 56 | `cs_main` is held 57 | [here](https://github.com/bitcoin-core-review-club/bitcoin/blob/pr22677/src/validation.cpp#L387)? 58 | 59 | 8. Do you have any suggestions for alternative approaches to removing this circular dependency? 60 | 61 | ## Meeting Log 62 | 63 | {% irc %} 64 | 18:00 #startmeeting 65 | 18:00 Hello friends! Welcome to PR Review Club! Feel free to say hi to let us know you're here 66 | 18:00 hi! 67 | 18:01 We're looking at PR#22677 today: "Cut the validation <-> txmempool circular dependency" 68 | 18:01 hi 69 | 18:01 PR: https://github.com/bitcoin/bitcoin/pull/22677 70 | 18:01 Notes: https://bitcoincore.reviews/22677 71 | 18:01 hi 72 | 18:02 did anyone get a chance to look at the notes or review the PR? 73 | 18:02 n 74 | 18:03 n 75 | 18:03 0.5y 76 | 18:03 no problem. we'll start conceptual: What is a circular dependency, and why should we avoid circular dependencies? 77 | 18:04 Two or more modules depend on each other 78 | 18:04 hi 79 | 18:04 pg2: indeed! 80 | 18:04 testing is much easier 81 | 18:04 and why are circular dependencies bad? 82 | 18:04 we can't seperately use one module individually if another is linked with it (they might recursively call each other) 83 | 18:05 sandipndev: right, it's much harder to isolate and test our code if it's tangled up with a bunch of other stuff 84 | 18:06 What functionality lives in the validation module? What lives in txmempool? 85 | 18:06 with circular dependencies present, it's harder to get a clear mental model 86 | 18:06 valiation.{h.cpp} update local knowledge of the current best chain and corresponding UTXO set, and process new blocks 87 | 18:06 txmempool.{h.cpp} store the actual transaction in the pool (class `CTxMemPool`), and metadata about the transactions (class `CTxMemPoolEntry`) 88 | 18:07 larryruane: yeah, i agree with that too! 89 | 18:08 Removing circular dependencies is desirable, but are there any downside or risks for this kind of refactoring? (e.g. could this break any downstream systems built on top of Bitcoin Core?) 90 | 18:09 pg2: good answer. i might add (for the context of this PR) that txmempool is a "dumb" data structure that shouldn't know any details about consensus rules 91 | 18:09 (that's my opnion though of course) 92 | 18:10 i see there are a few expected circular dependencies, since circular deps are bad, why are they even present and expected? 93 | 18:11 pg2: good question, I suppose forks of bitcoin core could have some trouble incorporating our changes if our architectures diverge 94 | 18:11 because the codebase is old, and works, so we don't want to throw it out 95 | 18:12 for context, the circular dependencies linter was added in https://github.com/bitcoin/bitcoin/pull/13695 96 | 18:13 listing them explicitly probably helps us see when they're removed and be warned if someone adds a new one 97 | 18:14 having a list of expected circular dependencies allows us to use the linter without ripping everything out 98 | 18:14 sandipndev: does that answer your question? 99 | 18:15 yes, absolutely! 100 | 18:15 cool! :) 101 | 18:15 So, in case it wasn't clear, we currently have a circular dependency between txmempool and validation. 102 | 18:16 There would theoretically be 2 ways to remove this: make txmempool not depend on validation anymore, or make validation not depend on txmempool anymore 103 | 18:16 Why should/shouldn’t validation depend on txmempool? Why should/shouldn’t txmempool depend on validation? 104 | 18:17 Validation should depend on txmempool, because we need to know what is in the mempool to validate new transactions 105 | 18:17 pg2: very logical answer, I agree :D 106 | 18:17 Txmempool shouldn't depend on validation, because the transactions in mempool are already validated (and therefore donot need to depend on anything in validation.{h.cpp}). 107 | 18:18 i also think an argument could be made for neither depending on the other - you don't really need to know about the existence of a mempool in order to apply validation rules to a transaction 108 | 18:19 glozow: thanks for your answers. after this PR, is txmempool "complete dumb", or "dumb enough"? Or there are places where it still knows about consensus rules (unnecessarily)? 109 | 18:20 pg2: ooh good question 110 | 18:21 since i've already started saying possibly controversial things... another thing the mempool probably doesn't need to be responsible for is the fee estimator 111 | 18:21 <_aj_> glozow: "neither depending on the other" -- isn't validation the *action* of accepting a block (which means the txs in the block should no longer be in the mempool since they're no longer valid on top of the new tip) ; the consensus rules themselves are in consensus/ and script/ and the like? 112 | 18:22 <_aj_> (also the action of accepting a tx into the mempool) 113 | 18:23 _aj_: ah true, i completely agree. I guess in general I mean that consensus rules themselves (i.e. consensus/ and script/) and the mempool are not conceptually related 114 | 18:24 but yes, the action of validating transactions would depend on both 115 | 18:26 OK next question. One of the functions that causes txmempool to rely on validation is the `check()` function. What checks does it perform, and how does this PR split the checks into two categories? 116 | 18:27 For every transaction input in mempool, `check()` checks if the input refers to any other mempool transactions, otherwise it checks if the previous transaction output is unspent. 117 | 18:28 I don't find anywhere in `check()` checks the sender has enough balance to cover the sum of output amounts. Is there such a check somewhere? 118 | 18:29 pg2: see `CheckTxInputs` in src/consensus/tx_verify 119 | 18:29 glozow: thanks 120 | 18:29 https://github.com/bitcoin/bitcoin/blob/2161a058552ac938f2079b311a2d12f5d1772d01/src/consensus/tx_verify.cpp#L201-L206 121 | 18:30 pg2: yes, that's one thing that `check()` does. what else? 122 | 18:30 (oops - the link I sent has the wrong line numbers. it should be a few lines above, the `bad-txns-in-belowout` check) 123 | 18:33 glozow: that's the only part where I finished reading the code, that's why I can only give a partial answer 124 | 18:33 no worries. just seeing if anyone is willing to answer the rest :) 125 | 18:34 so I've (arbitrarily) split the `check()` assertions into 2 categories: contextual checks and internal consistency checks. Contextual is what pg2 already mentioned - we go through and make sure all the transactions' inputs refer to something available in our mempool or UTXO set. 126 | 18:36 Internal consistency checks are things like making sure the ancestor/descendant counts of each entry add up correctly, checking that our total fee accounting and dynamic memory usage are accurate, etc. 127 | 18:36 It may or may not make sense to split `check()` up this way; up to you as a reviewer 128 | 18:37 Moving on to next question: Another function that causes txmempool to rely on validation is the `removeForReorg()` function, which calls `CheckSequenceLocks()` and `CheckFinalTx()`. Why do we need to re-check sequence locks in a reorg? 129 | 18:38 Yes, I think this conceptual distinction between contextual and non-contextual checks appears also with respect to blocks 130 | 18:39 glozow: because time is "backing up" so a tx that used to be valid is no longer valid (yet) 131 | 18:40 larryruane: right! but... how is it possible for a coinbase spend in the mempool to become premature in a reorg? Don't we only reorg when we see a longer chain?! 132 | 18:41 a reorg could result in a shorter chain, because it may have more _work_ 133 | 18:41 larryruane: aha!!!! 134 | 18:43 <_aj_> the first block in a multi-block reorg will be lower than the last block before the reorg even if difficulty doesn't change? [A B C D] -> [A E F G H], E has lower height than D? 135 | 18:44 <_aj_> (or are we only readding txs after processing all the reorg blocks somewhere?) 136 | 18:45 _aj_: i believe so 137 | 18:46 _aj_: righto. i think in a multi-block reorg we fill up a disconnectpool and then call `removeForReorg` after 138 | 18:46 not 100% sure tho? 139 | 18:47 will check 140 | 18:51 next question is about lock annotations. what are we saying to the compiler when we annotate a callable with `EXCLUSIVE_LOCKS_REQUIRED`? 141 | 18:55 <_aj_> glozow: (hmmmm, i think i had a bug way back whenever when i was investigating something related to this then!) 142 | 18:56 _aj_: (i am... about 16% confident in that statement) 143 | 18:58 hok so the answer to my previous question about lock annotations, the answer is here: https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#requires-requires-shared 144 | 18:59 the rest of the questions are left as an exercise to the reader 145 | 18:59 thanks for coming! 146 | 18:59 #endmeeting 147 | {% endirc %} 148 | -------------------------------------------------------------------------------- /_posts/2023-04-12-#27255-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2023-04-12 4 | title: "MiniTapscript: port Miniscript to Tapscript (Part 2)" 5 | pr: 27255 6 | authors: [darosior] 7 | components: ["descriptors"] 8 | host: josibake 9 | status: past 10 | commit: 6e3b37b 11 | --- 12 | 13 | ## Notes 14 | 15 | See notes from the [first part of this review club](/27255). 16 | 17 | ## Questions 18 | 19 | 1. Did you review the PR? [Concept ACK, approach ACK, tested ACK, or NACK](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#peer-review)? 20 | What was your review approach? 21 | 22 | 1. In Miniscript, we have type modifiers, which guarantee additional properties for an expression. [866284d](https://github.com/bitcoin-core-review-club/bitcoin/commit/866284d007993551f681809d9e48175a3b0fe0c1) makes the wrapper "**d:**" have the "**u**" property under Tapscript. 23 | * What is the "**d:**" wrapper and the "**u**" type modifier? 24 | * Why is it that we can make **d:** have the **u** property here? Why not in non-Tapscript Miniscript? 25 | 26 | 1. This PR adds some logic for statically ensuring no spending path exceeds the stack size at execution time: 27 | * Why does this matter for Tapscript? 28 | * What's the approach taken by this PR? What are the pros/cons? (hint: [efdd154](https://github.com/bitcoin-core-review-club/bitcoin/commit/efdd1543597aff49c56a1abaa75b574be3b330db)) 29 | * Can you think of an alternative approach to ensure no spending path exceeds the stack size? 30 | 31 | 1. In [e81635c](https://github.com/bitcoin-core-review-club/bitcoin/commit/e81635c39d99a158629544fefd765b3994f3d7c4), the scripts are optionally padded during fuzzing. Why? 32 | 33 | 1. What is the most significant change to the descriptor logic in this PR (hint: [08db38a](https://github.com/bitcoin-core-review-club/bitcoin/commit/08db38aca2fe9169b39507d928c1094be2116ad4)). Why is it needed? 34 | 35 | 36 | ## Meeting Log 37 | 38 | {% irc %} 39 | 17:00 < josie> #startmeeting 40 | 17:00 < josie> hi! 41 | 17:02 < kevkevin> hi 42 | 17:02 < josie> planning to review https://bitcoincore.reviews/27255-2 , which is a follow up to last weeks PR review club: https://bitcoincore.reviews/27255 43 | 17:03 < josie> although, it's awfully quiet in here... 44 | 17:03 < abubakr> hi 45 | 17:03 < glozow> hi 46 | 17:05 < brunoerg> hi 47 | 17:05 < josie> i recognize most of the names from last time, but I'll ask any way: did everyone here get a chance to attend part 1? 48 | 17:05 < josie> and if so, have you had a chance to review the questions for part 2? 49 | 17:06 < abubakar> yes 50 | 17:06 < kevkevin> yup was in part 1 didnt get too much of a chance to look at part 2's questions 51 | 17:08 < LarryRuane> Hi 52 | 17:09 < josie> cool, let's start with question 2: In Miniscript, we have type modifiers, which guarantee additional properties for an expression. commit 866284d makes the wrapper “d:” have the “u” property under Tapscript 53 | 17:10 < josie> first off, what are the "d:" wrapper and "u" fragment? 54 | 17:11 < abubakar> from miniscript website "d" is a dissatisfiable: does not include a signature or a hash preimage cannot rely on timelocks for being satisfied 55 | 17:12 < stickies-v> hi 56 | 17:12 < abubakar> "u" when satisfied the expression will have 1 on the stack 57 | 17:13 < josie> also - I typed that incorrectly: that should be "what is the 'u' type modifier" 58 | 17:13 < stickies-v> abubakar: perhaps confusingly, there's a difference between `d` the property and `d:` the wrapper 59 | 17:13 < stickies-v> as in - they're entirely unrelated 60 | 17:14 < abubakar> stickies-v: ohthanks 61 | 17:15 < josie> abubakar: I made the same mistake when writing the questions! it is confusingly named 62 | 17:15 < stickies-v> properties/type modifiers describe attributes of fragments (expressions), e.g. the `z` property says that a fragment with that property always consumes exactly 0 stack elements 63 | 17:15 < stickies-v> wrappers however take a fragment and add some script before/after it 64 | 17:16 < josie> stickies-v: that's a great explanation on the difference between wrappers and type modifiers, thanks! 65 | 17:17 < stickies-v> the `d:X` wrapper takes fragment X, and adds `DUP IF` before and `ENDIF` after the fragment, so you end up with `DUP IF [X] ENDIF` 66 | 17:19 < abubakar> stickies-v: thanks 67 | 17:19 < josie> what about the type modifier, "u"? 68 | 17:20 < stickies-v> fragments with type modifier `u` always put `1` on the stack when satisfied 69 | 17:20 < abubakar> i think its the one I reffered to earlier 70 | 17:20 < stickies-v> ah yes exactly you did! 71 | 17:21 < josie> abubakar: sorry, i missed this, but yes! when satisfied, expressions with the u property leave exactly 1 on the stack 72 | 17:22 < josie> so leading into the second part: why is okay for us to say the d:X fragment has the u property under tapscript? 73 | 17:22 < abubakar> It is called unit because of the 1 it leaves right? 74 | 17:23 < josie> abubakar: that's how I understood it: unit as in exactly 1 75 | 17:25 < abubakar> josie: okay 76 | 17:26 < stickies-v> before taproot, OP_IF would evaluate to true for any value > 0, whereas in taproot we require the argument to be either 0/1. Which means that in case of true, the argument is definitely 1. Because the `d:` wrapper duplicates the argument (OP_DUP), we can state that in case of satisfaction this fragment will put 1 on the stack 77 | 17:27 < josie> stickies-v: "OP_IF would evaluate true for any value > 0" .. was this true for _any_ transaction? 78 | 17:29 < stickies-v> hmmmm, i thought so but it sounds like i'm missing something? 79 | 17:30 < josie> perhaps a better way to phrase my question: was there anything pre-tapscript that would have prevented "regular" users from constructing transactions that used this OP_IF behavior? 80 | 17:31 < instagibbs> MINIMALIF was a standardness check for p2wsh iirc 81 | 17:32 < josie> instagibbs: bingo! the main problem here is miners are not bound by standardness, only validity 82 | 17:33 < josie> I don't have a link to it, but darosier has shown some nasty examples where miners could exploit this to steal funds in scripts that use thresholds 83 | 17:34 < josie> so if people remember from last week, MINIMALIF was added as a consensus rule in tapscript, which means it is now safe to say that d:X fragments can have the u property 84 | 17:34 < josie> moving on to question 3: "This PR adds some logic for statically ensuring no spending path exceeds the stack size at execution time" 85 | 17:35 < josie> why does this matter for tapscript? 86 | 17:36 < kevkevin> didn't CHECKMULTISIG have a limit of 20, and CHECKSIGADD removed that limit so now we're bound by the stack size limit, not sure if I'm remembering correctly 87 | 17:37 < instagibbs> miniscript does more than 20 signatures fine I think. BIP342 introduces "It is extended to also apply to the size of initial stack" which means it can't exceed limits ever and succeed. Not sure that answers it 88 | 17:37 < instagibbs> see https://github.com/bitcoin/bips/blob/master/bip-0342.mediawiki#resource-limits 89 | 17:37 < abubakar> because someone might use a script that add elements that are larger than stack size, standarness were lifted 90 | 17:39 < stickies-v> miniscript also checks if a script is sane, which (amongst others) also means that it is consensus valid and standard - this helps a lot with analysis of scripts. for example, you may not care about the entire script, just that you have a certain spending path to which you control the keys. but if it then turns out that that spending path is actually not spendable (because of stack size limit), that's a problem 91 | 17:39 < josie> kevkevin: CHECKMULTISIG did have a limit, but I think its more correct to say CHECKMULTISIG was disabled in tapscript and CHECKSIGADD was added, and CHECKSIGADD doesn't have a limit (aside from the stack size limit) 92 | 17:41 < kevkevin> josie: ok ya that makes more sense, thanks 93 | 17:41 < josie> stickies-v: great point re: miniscript. I think tapscript's decision to remove some of the "arbitrary" limits from before makes being able to reason about sanity much more straightforward 94 | 17:43 < josie> moving on the the second part of the question: "What’s the approach taken by this PR? What are the pros/cons?" 95 | 17:44 < josie> by approach, we are referring to how this PR ensures no spending path exceeds the stack size limit at execution time 96 | 17:50 < josie> for this one, the commit message is pretty helpful 97 | 17:53 < josie> haha the silence is pretty deafening on this one (which admittedly is a pretty in the weeds question), so lets finish with the last question about descriptors 98 | 17:53 < josie> What is the most significant change to the descriptor logic in this PR? 99 | 17:54 < stickies-v> sorry josie I didn't review this far ahead so just looking at the commit now - if you wouldn't mind summarizing your answer i'd appreciate that? 100 | 17:54 < stickies-v> on the approach and pros/cons 101 | 17:58 < josie> sure! basically, it tracks how the stack will be affected after the script executes, and also how many items will be pushed on the stack during execution. the second part is the part I don't fully understand, but it also checks the maximum witness size for a fragment and takes the lesser. regarding pros and cons, it mentions this being a conservative approach because the max 102 | 17:58 < josie> witness might not always happen along with the max stack size 103 | 17:59 < stickies-v> i think we also distinguish between satisfactions and dissatisfactions, right? 104 | 17:59 < josie> as a con, you could say since this is a conservative approximation, which might not let you do a script that you would otherwise be able to do with more precise accounting 105 | 18:00 < josie> stickies-v: I believe so, but this where my knowledge of script execution gets fuzzy 106 | 18:01 < josie> we'll stop here. thanks everyone for attending part 2! this is a really dense topic so I appreciate everyone muscling through 107 | 18:01 < josie> #endmeeting 108 | 20:58 @josie kevkevin Arguably, CHECKMULTISIG has no more or no less a limit (20) than CHECKSIGADD has a limit (1). 109 | 20:59 The point is that multi maps to just one CHECKMULTISIG, and thus inherits the 20 limit. 110 | 20:59 While multi_a maps to many CHECKSIGADD opcodes, so it is not bound to its 1 limit. 111 | 21:00 We could arguably define a multi() fragment that intelligently maps to multiple CHECKMULTISIG opcodes, and that wouldn't be bound by the 20 limit either, but that's just hiding a lot of complexity that can equally well be captured at a higher level (forcing the miniscript to combine multiple multi() fragments explicitly). 112 | {% endirc %} 113 | -------------------------------------------------------------------------------- /_posts/2023-05-24-v25-rc-testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2023-05-24 4 | title: "Testing Bitcoin Core 25.0 Release Candidates" 5 | components: ["tests"] 6 | host: ismaelsadeeq 7 | status: past 8 | commit: 9 | --- 10 | 11 | ## Notes 12 | 13 | - Major versions of Bitcoin Core are released every 6-8 months. See the [Life 14 | Cycle documentation](https://bitcoincore.org/en/lifecycle/) for full details. 15 | - When all of the PRs for a release have been merged, _Release Candidate 1_ 16 | (rc1) is tagged. The rc is then tested. If any issues are found, fixes are 17 | merged into the branch and a new rc is tagged. This continues until no major 18 | issues are found in an rc, and that rc is then considered to be the final 19 | release version. 20 | - To ensure that users don't experience issues with the new software, it's 21 | essential that the rcs are thoroughly tested. This special review club 22 | meeting is for people who want to help with that vital review process. 23 | 24 | - This [Bitcoin Core Release Candidate Testing 25 | Guide](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/25.0-Release-Candidate-Testing-Guide) provides guidance for testing the release candidate. 26 | 27 | - It is recommended to go through the "Preparation" steps ahead of the meeting, especially if you want to compile from source. Verify and confirm the successful installation of v25rc2. 28 | 29 | - The testing guide relies on the tools `jq` which are not installed by default on each platform. For example on macOS, you can install these ahead of time using `brew install`. Alternatively, you can also modify the instructions to avoid using these tools as they are not strictly necessary and/or can be replaced by other tools. 30 | 31 | - For some of the tests, you might want to have the [signet](https://en.bitcoin.it/wiki/Signet) chain fully synced beforehand, so that you can just copy the signet directory into `/tmp/25-rc-test/` every time you run a test in a fresh environment. 32 | 33 | - The guide is just to get you started on testing, so feel free to read the [Release Notes](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/25.0-Release-Notes-Draft) 34 | and bring ideas of other things you'd like to test! 35 | 36 | ## Meeting Log 37 | 38 | {% irc %} 39 | 16:59 #startmeeting 40 | 16:59 hi 41 | 16:59 hello 42 | 16:59 Hello everyone welcome to this special edition of bitcoin core pr review club 43 | 16:59 yaay 44 | 17:00 Hi every1 45 | 17:00 hi all ! 46 | 17:00 Feel free to say hello 47 | 17:00 Anyone joining in for the first time? 48 | 17:02 We will be testing the changes and new features in the upcoming release of bitcoin core version 25.0 49 | 17:03 Find the relevant notes and the link to the testing guide here https://bitcoincore.reviews/v25-rc-testing 50 | 17:05 The purpose of this is to ensure all the changes in this release are working as expected, the guide covers most but not all the changes, so go ahead and try to break things :). 51 | 17:06 ieay ! 52 | 17:06 hi 53 | 17:07 Welcome ! 54 | 17:08 Which os are you all using / and are you compiling from source or using pre-built binaries 55 | 17:08 pop os / compiling from source 56 | 17:09 macOS 13.0 / compiling from source 57 | 17:10 macos 13.3.1, compiled from source 58 | 17:10 Linux 6.0.10 #1 SMP PREEMPT_DYNAMIC Wed Nov 30 15:00:02 -03 2022 x86_64 x86_64 x86_64 GNU/Linux 59 | 17:10 compiling from source 60 | 17:11 Great let's get started with the preparation step https://github.com/bitcoin-core/bitcoin-devwiki/wiki/25.0-Release-Candidate-Testing-Guide#preparation 61 | 17:11 Ubuntu, compiled from source 62 | 17:12 Lets spare a few minutes for that step, you can go ahead and start testing if you are done with this step 🚀 63 | 17:14 Compiling from source Ubuntu 20.04 64 | 17:15 There are majorly 4 test in the guide with some bonus tests 65 | 17:16 There is a major tests in the release notes that are not covered in the guide, the guide is a wip for feedback on it please drop comment here (https://github.com/bitcoin/bitcoin/issues/27736) 66 | 17:18 There are some major* 67 | 17:19 The first one is to test -maxconnections=0 will now disable -dnsseed and -listen 68 | 17:19 https://github.com/bitcoin-core/bitcoin-devwiki/wiki/25.0-Release-Candidate-Testing-Guide#test--maxconnections0-will-now-disable--dnsseed-and--listen 69 | 17:23 Run smoothly , everything as expected 70 | 17:23 hernanmarino: great 71 | 17:25 -maxconnections=0 ran w/o issues 72 | 17:26 Anyone having unexpected results can drop questions here on the issue 73 | 17:26 https://github.com/bitcoin/bitcoin/issues/27621 74 | 17:27 Alright the next test is Test non-witness transaction that are greater than 65 bytes are allowed in the mempool and relayed #26265 75 | 17:27 https://github.com/bitcoin-core/bitcoin-devwiki/wiki/25.0-Release-Candidate-Testing-Guide#test-non-witness-transactions-that-are-greater-than-65-bytes-are-allowed-in-the-mempool 76 | 17:33 Tips for the last step, add 0 after the transactionhex to set the maxfeerate to 0 77 | 17:37 when running bcli -regtest sendrawtransaction ... getting error code: -25 error message: 78 | 17:37 bad-txns-inputs-missingorspent 79 | 17:38 did you replace your own txid when creating the raw transaction ? 80 | 17:38 ah nope 81 | 17:38 Yes use the raw trxhex from your regtest node 82 | 17:38 you cannot simply copy and paste from the guide in this step, i believe. You should replace the txid with the one you got in the previous step 83 | 17:39 ah ok got it 84 | 17:39 +1 hernanmarino 85 | 17:40 mine passed the tx was accepted in my mempool 🚀 86 | 17:40 aslo when you sign and send the rawtransaction you should use is the output you got when you created it 87 | 17:41 and also when decoding and verifying it s size 88 | 17:44 The third test is an interesting one, it tests Finalizing a PSBT with inputs spending Miniscript-compatible P2WSH scripts introduced in PR #24149 89 | 17:44 https://github.com/bitcoin-core/bitcoin-devwiki/wiki/25.0-Release-Candidate-Testing-Guide#test-finalizing-a-psbt-with-inputs-spending-miniscript-compatible-p2wsh-scripts-and-test-spending-the-coin 90 | 17:51 ok it worked 91 | 17:52 Great same here :) 92 | 17:52 worked here as well 93 | 17:52 We have some minutes to test one or two bonus tests 94 | 17:53 worked ok 95 | 17:54 This is a good one if you have signet chain https://github.com/bitcoin-core/bitcoin-devwiki/wiki/25.0-Release-Candidate-Testing-Guide#ensure-verifychain-returns-false-if-the-check-cant-be-completed 96 | 17:54 You can copy the signet directory to /tmp/25-rc-test for this 97 | 17:59 Please remember to add a comment on v25.0-rc2 testing issue detailing 98 | 17:59 Please remember to add a comment on v25.0-rc2 testing issue detailing: 99 | 17:59 #endmeeting 100 | {% endirc %} 101 | -------------------------------------------------------------------------------- /_posts/2023-06-07-#27711.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2023-06-07 4 | title: "Remove shutdown from kernel library" 5 | pr: 27711 6 | authors: [TheCharlatan] 7 | components: ["validation"] 8 | host: stickies-v 9 | status: past 10 | commit: a6a3c3245303d05917c04460e71790e33241f3b5 11 | --- 12 | 13 | ## Notes 14 | 15 | - The [libbitcoinkernel project](https://github.com/bitcoin/bitcoin/issues/27587) is an effort to decouple Bitcoin Core’s consensus engine from other non-consensus modules (such as the various indices) in the codebase. We have previously covered libbitcoinkernel-related PRs [#25527](/25527), [#24410](/24410) and [#20158](/20158). 16 | 17 | - [#27636](https://github.com/bitcoin/bitcoin/pull/27636) introduced a [`kernel::Notifications` interface](https://github.com/bitcoin/bitcoin/blob/b22408df162a224d94ac54e8443b57ef3fd2ca72/src/kernel/notifications_interface.h#L21), which can then be implemented by node implementations (e.g. [`KernelNotifications`](https://github.com/bitcoin/bitcoin/blob/b22408df162a224d94ac54e8443b57ef3fd2ca72/src/node/kernel_notifications.h#L18)) to trigger the desired behaviour for an event. 18 | 19 | - One such type of event is the consensus engine requiring a shutdown, [expectedly](https://github.com/bitcoin/bitcoin/blob/b22408df162a224d94ac54e8443b57ef3fd2ca72/src/node/blockstorage.cpp#L939) or [unexpectedly](https://github.com/bitcoin/bitcoin/blob/b22408df162a224d94ac54e8443b57ef3fd2ca72/src/node/chainstate.cpp#L210). 20 | 21 | - This PR [#27711](https://github.com/bitcoin/bitcoin/pull/27711) adds two new notification methods `kernel::Notifications::startShutdown`[](https://github.com/TheCharlatan/bitcoin/commit/a6a3c3245303d05917c04460e71790e33241f3b5#diff-6f5e5a92ba752d079eddefda2bb7a4432c853712d10878369ffd36f45fca204dR45) and [`kernel::Notifications::fatalError`](https://github.com/TheCharlatan/bitcoin/commit/2db5ddf52b4b8100b03c1235d3e94a00d66a16cb#diff-6f5e5a92ba752d079eddefda2bb7a4432c853712d10878369ffd36f45fca204dR36) to allow the node to implement the necessary behaviour. 22 | 23 | - Moreover, this PR moves the shutdown files as well as the remaining usages of `uiInterface` out of the kernel code, as started in [#27636](https://github.com/bitcoin/bitcoin/pull/27636). 24 | 25 | ## Questions 26 | 27 | 1. Did you review the PR? [Concept ACK, approach ACK, tested ACK, or NACK](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#peer-review)? What was your review approach? 28 | 29 | 1. Why do we have `startShutdown` both in `kernel/notifications_interface.h` as well as in `node/kernel_notifications.h`? 30 | 31 | 1. How does [`fRequestShutdown`](https://github.com/bitcoin/bitcoin/blob/b22408df162a224d94ac54e8443b57ef3fd2ca72/src/shutdown.cpp#L35) relate to this PR, and can you elaborate on its role in terminating long-running kernel functions? 32 | 33 | 1. How does the notification interface contribute to the decoupling of most non-consensus code from libbitcoinkernel? 34 | 35 | 1. Can you describe the flow of `startShutdown` and `fatalError` notifications in this new setup? Who are the producers and consumers of these notifications? 36 | 37 | 1. Are there any potential race conditions or synchronization issues that might arise with the use of the notification interface in this context? 38 | 39 | 1. Why is [`KernelNotifications::m_shutdown_requested`](https://github.com/bitcoin-core-review-club/bitcoin/commit/2db5ddf52b4b8100b03c1235d3e94a00d66a16cb#diff-04e685224f1ac5bfd91d47d8d7528a2e44f94fab5535d4b6b5af79b5a13aeb93R94) a reference value? Do you have any ideas for alternative approaches to triggering a shutdown? 40 | 41 | 42 | ## Meeting Log 43 | 44 | {% irc %} 45 | 17:00 #startmeeting 46 | 17:00 hi 47 | 17:01 welcome everyone! Today we're looking at #27711, authored by TheCharlatan. The notes and questions are available on https://bitcoincore.reviews/27711 48 | 17:01 hello 49 | 17:01 Hi every1 50 | 17:02 note: we'll be focusing on the previous PR HEAD (https://github.com/bitcoin-core-review-club/bitcoin/commit/a6a3c3245303d05917c04460e71790e33241f3b5), which is _not_ the current HEAD anymore (but we don't want to overhaul the notes and questions last minute) 51 | 17:02 anyone joining us for the first time today? even if you're just lurking, feel free to say hi! 52 | 17:03 silly question, but is there a way to see the commits before that one? 53 | 17:03 (on GitHub) 54 | 17:03 hi :) 55 | 17:04 LarryRuane: GitHub allows you to browse a repo at a certain commit (like checkout), and if you do that and then click the commit history button, you can see the history indeed 56 | 17:05 https://github.com/bitcoin-core-review-club/bitcoin/commits/a6a3c3245303d05917c04460e71790e33241f3b5 would be the link 57 | 17:05 (an extra `s` after `commit` in the url) 58 | 17:05 that's it, perfect, thanks 59 | 17:05 who got the chance to review the PR or read the notes? (y/n) 60 | 17:05 hi TheCharlatan, thanks for joining us today! 61 | 17:06 do others do a lot of URL hacking on github? I do, but always wondered if it's only because I don't know of better ways 62 | 17:06 when in doubt I revert to cli :-D 63 | 17:07 I have not much at all, sorry, I got stuck on a question that didn't make sense with the most recent head 64 | 17:07 mutex: is that the `gh` command? I haven't used it but maybe should learn how to 65 | 17:07 this is my first PR review, not well versed in C++ so i'm at a bit of a disadvantage 66 | 17:07 LarryRuane, url's are made to be hacked :D 67 | 17:08 LarryRuane: git command, I haven't used the 'gh' tool 68 | 17:08 I read the notes and was reading about the kernel project :) 69 | 17:08 :) .. yeah i actually don't mind it! but just was wondering.. sorry for the sidetrack 70 | 17:08 hey mutex, glad to have you here! there's a bit of a learning curve but hang in there :-) 71 | 17:09 the PR turned out to be a bit more complex than I imagined when I first selected it hah, as also evidenced by the recent discussions and today's force-push 72 | 17:09 mutex: yes i of course use `git` constantly, but to interact with github, there's a `gh` command you can install, which i did, but i haven't used it yet 73 | 17:09 I see there's not been too much review, so perhaps we can start if anyone has any questions about the purpose of this PR? does the approach make sense? 74 | 17:10 stickies-v: yes, i started reading the comments on the PR was like, wow, this is way over my head! 75 | 17:10 LarryRuane: I've not had any use case where `git` and shell alias/functions couldn't help me out tbh 76 | 17:12 concept ACK 77 | 17:12 is this a step toward getting rid of the fRequestShutdown flag? 78 | 17:12 (but I'm unclear on how exactly that flag interacts with the consensus kernel) 79 | 17:13 LarryRuane: oh, good question. I don't think that's quite in the scope of the libbitcoinkernel project, since `fRequestShutdown` is owned by the node 80 | 17:14 I think the version of the PR that we're reviewing doesn't really make any progress towards that goal either, since we're still very much relying on a global boolean value 81 | 17:15 the new, current version, however, seems to be moving in that direction with the `interrupt()` function 82 | 17:15 is there more than one PR we should be looking at? 83 | 17:16 mutex: the most relevant prior PR to this one is https://github.com/bitcoin/bitcoin/pull/27636, that introduced the notification interface 84 | 17:17 but I'd say the PR is pretty self contained 85 | 17:17 gonna start with the first question: 86 | 17:17 Why do we have `startShutdown` both in `kernel/notifications_interface.h` as well as in `node/kernel_notifications.h`? 87 | 17:19 (that's the question i got stumped on, since it's not in both of those places) 88 | 17:19 yeah I'm not seeing it 89 | 17:19 (in the latest PR head) 90 | 17:21 yeah, it's in commit a6a3c3245303d05917c04460e71790e33241f3b5 91 | 17:23 but, I think it probably doesn't make sense to keep discussing questions that no one's seen the code for 92 | 17:23 so I suggest we stop covering the prepared questions and instead just move to general Q&A on the PR, if there are any? 93 | 17:25 is this an issue of the questions being prepared for code that has already been superceded? 94 | 17:26 Here's something I wondered while reviewing this PR (but the latest on github), but just a c++ question, https://github.com/bitcoin/bitcoin/pull/27711/files#diff-d6d633592a40f5f3d8b03863e41547de8751b874c1d20f129a616b9dd719b999R26 there are empty braces at the end of that declaration, do those need to be there? what do they do? 95 | 17:27 mutex: yeah, there was quite a big code overhaul this morning. we do include the HEAD that we look at on the bitcoincore.reviews website, but I now see that it only is mentioned for reviews in the past, not for current/upcoming ones 96 | 17:27 I have a quesiton about this comment: https://github.com/bitcoin/bitcoin/pull/27711/files#diff-04c8e84ee77f6085c064940c211aedb95c781be20927aec64553d8448253af97R44 No signals on windows? I thought windows was POSIX compliant? 97 | 17:27 (modern windows) 98 | 17:28 mutex: +1 good question, what happens when you hit control-c on windows? Does that even work there? How does it work without signals? 99 | 17:29 afaik windows has its own event thing that you can use to emulate posix signals. 100 | 17:30 (I'm not a windows dev though) 101 | 17:30 https://stackoverflow.com/questions/51476296/what-signals-should-i-use-to-terminate-kill-applications-on-windows 102 | 17:30 my knowledge here is from 20 years ago, where WindowsNT had a POSIX subsystem, i'm sure things have changed since then ;-) 103 | 17:30 LarryRuane: I think `KernelNotifications notifications` and `KernelNotifications notifications{}` are equivalent, since `KernelNotifications` is a class with a default constructor 104 | 17:31 `As a standalone library the libbitcoinkernel should not have to rely on code that accesses shutdown state through a global.`  was `static std::atomic fRequestShutdown(false);` the original global?  the state being just true/false? 105 | 17:31 thanks 106 | 17:31 but with the braces we ensure that it's always initialized, so probably better practice to do it like this? 107 | 17:31 i see, so even if the class does have a default constructor, probably no harm in specifying those braces 108 | 17:32 evansmj: that's my understanding, yes! 109 | 17:38 in case this is also helpful to others... here's a list of the files that are considered part of libbitcoinkernel: https://github.com/bitcoin/bitcoin/blob/2026301405f83c925ca68db6a3cd5134ed619ca7/src/Makefile.am#L911 110 | 17:39 (well, not "considered" ... actually are!) 111 | 17:39 it's more than I thought 112 | 17:39 with the "#TODO" line above it quite important: 113 | 17:39 "...as more and more modules are decoupled from the consensus engine, this list will shrink to only those which are absolutely necessary." 114 | 17:40 yes, great point, i had missed that! 115 | 17:41 So the PR changes the signaling method, does the behavior change at all? I see a few exceptions being thrown, does that change the behavior other than to stop hashing? 116 | 17:42 I don't think i know enough about the surrounding code to understand 117 | 17:42 so the first two commits (in the review club version, not the latest PR tip) are removing calls to the global `ShutdownRequested()` function from those files (that make up libbitcoinkernel), IIUC 118 | 17:43 mutex: I've not looked at the current version too much yet, but I think behaviour is not meant to change, no 119 | 17:44 so now, classes interested in the shutdown state need to look at the kernel Context notifications for the signal interrupt flag.  what kinds of things/classes are interested in this?  i see bitcoind checks it immediately in AppInit(), is that somehow the main looping check? 120 | 17:45 behaviour should not change except for the two subtle changes/bugfixes in the latest PR tip. 121 | 17:45 LarryRuane: I think just the first commit? but otherwise, yeah 122 | 17:45 yes, you're right 123 | 17:51 evansmj: I think long-running operations, mostly? In `master`, I'd look at callsites of `ShutdownRequested()`, e.g. here when we're loading the blockindex: https://github.com/bitcoin/bitcoin/blob/2026301405f83c925ca68db6a3cd5134ed619ca7/src/node/blockstorage.cpp#L264 124 | 17:54 I assume one of the goals of a PR like this is making consensus code more testable? So that last commit, "kernel: Remove shutdown from kernel library" changes all the calls (in libbitcoinkernel) to the global `StartShutdown()`, to instead call a notification callback, for example `chainman.GetNotifications().startShutdown(ShutdownReason::StopAfterBlockImport)` 125 | 17:55 so with that change, test code won't *really* get shutdown (the test process) when this condition occurs 126 | 17:56 test code wouldn't really get shut down, it might check that this callback did happen (like presumably it's supposed to), and fail the test if not .. something like that 127 | 17:58 LarryRuane: yeah I think that's definitely true, and probably holds for pretty much all decoupling? the less intertwined everything is, the more straightforward your tests can be 128 | 17:58 I didn't think of that though, nice 129 | 17:59 alright, looks like we're out of time 130 | 18:00 thanks 131 | 18:00 thanks for your work on this PR TheCharlatan, and thanks everyone else for attending! 132 | 18:00 #endmeeting 133 | {% endirc %} 134 | -------------------------------------------------------------------------------- /_posts/2023-06-14-#27625.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2023-06-14 4 | title: "Stop relaying non-mempool txs" 5 | pr: 27625 6 | authors: [MarcoFalke] 7 | components: ["p2p"] 8 | host: mzumsande 9 | status: past 10 | commit: faa2976a56ea7cdfd77ce2580a89ce493b57b5d4 11 | --- 12 | 13 | ## Notes 14 | 15 | - [`mapRelay`](https://github.com/bitcoin/bitcoin/blob/153a6882f42fff3fdc63bf770d4c86a62c46c448/src/net_processing.cpp#L924) is a map containing all transactions that we've relayed to any peer recently. 16 | It is accompanied by [`g_relay_expiration`](https://github.com/bitcoin/bitcoin/blob/153a6882f42fff3fdc63bf770d4c86a62c46c448/src/net_processing.cpp#L926), a sorted list of expiration times for `mapRelay` entries. 17 | Entries stay in `mapRelay` and `g_relay_expiration` [for 15 minutes](https://github.com/bitcoin/bitcoin/blob/153a6882f42fff3fdc63bf770d4c86a62c46c448/src/net_processing.cpp#L5801). 18 | 19 | - When a peer asks for a transaction by sending a `getdata` message but the 20 | transaction is no longer in the mempool, it can be served from `mapRelay`. 21 | 22 | - `mapRelay` has been around for a long time, it was already present in the 23 | [first github commit](https://github.com/bitcoin/bitcoin/commit/4405b78d6059e536c36974088a8ed4d9f0f29898). 24 | While it was essential back then, its scope has been reduced over time: 25 | For example, Bitcoin Core now first tries to fetch transactions directly from the mempool. 26 | There are other reasons why `mapRelay` wasn't removed earlier 27 | (see [this comment](https://github.com/bitcoin/bitcoin/pull/27625#issuecomment-1552435967) 28 | for an overview), but most of these have been made obsolete by other improvements. 29 | 30 | - This PR removes `mapRelay` and instead introduces 31 | [`m_most_recent_block_txs`](https://github.com/bitcoin-core-review-club/bitcoin/commit/fccecd75fed50a59ec4d54d6dc9bd9a406ea6b30#diff-6875de769e90cec84d2e8a9c1b962cdbcda44d870d42e4215827e599e11e90e3R854) to keep track of only the transactions from the most recent block. 32 | 33 | ## Questions 34 | 1. Did you review the PR? [Concept ACK, approach ACK, tested ACK, or NACK](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#peer-review)? What was your review approach? 35 | 36 | 1. What are the reasons to remove `mapRelay`? 37 | 38 | 1. Why is the memory usage of `mapRelay` hard to determine? (Hint: see 39 | [this comment](https://github.com/bitcoin/bitcoin/pull/27625#issuecomment-1544947585)) 40 | 41 | 1. What problem is solved by introducing `m_most_recent_block_txs`? 42 | Do you think it is necessary to introduce it (as opposed to just removing `mapRelay` 43 | without any replacement)? 44 | 45 | 1. What are the memory requirements for `m_most_recent_block_txs` compared to `mapRelay`? 46 | 47 | 1. Are there scenarios in which transactions would be made available for a shorter or longer time 48 | than before as a result of this change? 49 | 50 | 1. Can you think of any other possible downsides of removing `mapRelay`? 51 | 52 | 53 | ## Meeting Log 54 | 55 | {% irc %} 56 | 17:00 #startmeeting 57 | 17:00 hi! 58 | 17:00 hi 59 | 17:01 hello 60 | 17:01 Hi every1 61 | 17:01 welcome to this week's review club! 62 | 17:01 hi 63 | 17:01 hi 64 | 17:01 Today's PR is https://github.com/bitcoin/bitcoin/pull/27625 (Stop relaying non-mempool txs). Notes are at https://bitcoincore.reviews/27625 65 | 17:02 the PR already got merged earlier this week! 66 | 17:02 Did you review the PR? Concept ACK, approach ACK, tested ACK, or NACK? 67 | 17:02 Concept ACK 68 | 17:03 n 69 | 17:03 woot! 70 | 17:03 Concept ACK 71 | 17:03 tested ACK 72 | 17:03 i'm hoping to get to Concept ACK after this meeting - looked at the code (and notes) but haven't fully wrapped my head around it yet 73 | 17:04 great! then let's jump into the questions. 74 | 17:04 What are the reasons to remove mapRelay? 75 | 17:05 hi 76 | 17:05 memory consumption? 77 | 17:06 unpredictable memory consumption (since we don't know which % of mapRelay is also in mempool)? 78 | 17:06 hi 79 | 17:06 because their is no utility for the transactions in mapRelay, all transaction dropped from mempool except for BLOCK reason does not need to be relayed anymore? 80 | 17:07 also, side question: this PR should affect GETDATA behaviour, but not INV behaviour, right? 81 | 17:07 emzy, stickies-v: yes, exactly. I'd say it just gives an uneasy feeling having an unbounded structure, even if the actual memory consumption may not be that high. 82 | 17:08 abubakarsadiq and REPLACED 83 | 17:08 (nice table in the PR) 84 | 17:08 abubakarsadiq: yes, that too. I think it's kind of a relic from the past when it was the main mechanism for tx transaction and we woldn't look up txns from the mempool. 85 | 17:10 stickies-v: yes, i agree, INV shouldn't be affected 86 | 17:11 instagibs:I thought REPLACED also is not needed https://github.com/bitcoin/bitcoin/pull/27625#issuecomment-1548505174 , why would we want to relay REPLACED transactions? 87 | 17:11 thanks, makes sense, we're just not keeping data for transactions that we believe our peers shouldn't care about anymore either 88 | 17:12 next question: Why is the memory usage of mapRelay hard to determine? 89 | 17:12 it depends on the number/rate of incoming transactions? 90 | 17:13 there is no maximum memory? 91 | 17:13 mutex: that's one aspect, but not all there is to it. 92 | 17:15 do we need the same amount of memory for all entries of mapRelay (given the txns are the same size), or does it depend on other factors? 93 | 17:16 mapRelay and mempool share the same `std::shared_ptr` pointers, so the memory overhead of having an extra transaction in mapRelay depends on whether or not the transaction is still in mempool 94 | 17:16 ah I see the detailed comment now! Looks like mapRelay <-> Mempool eviction relationship is not tracked 95 | 17:18 stickies-v: exactly! Due to the use of a shared_ptr, if we have the tx stored in the mempool, the overhead of adding it also to mapRelay is small. If mapRelay is the only place the tx is stored, the additional size is much larger. 96 | 17:19 so the size doesn't only depend on the number of transactions, but also on how many of its txns are no longer in the mempool (which is hard to predict) 97 | 17:21 come to think about it, I feel a bit weird about calling that unpredictability a downside 98 | 17:21 it's obviously much preferable over storing the entire tx in mapRelay, regardless of whether or not it already exists in mempool 99 | 17:23 stickies-v: yes, that's true,, it would be much worse if we did that. But what is not nice is that if for some reason there is a situation with a lot of mempool turnover, mapRelay could become very large in memory consumption. 100 | 17:24 next q: What problem is solved by introducing m_most_recent_block_txs? 101 | 17:24 but then I think the real problem is that mapRelay was unbounded in size? 102 | 17:25 that's what I read from the comments, having an unbounded datastructure is a concern 103 | 17:25 (regardless: it highlights the limitations that mapRelay had, e.g. it could easily be abused with high RBF turnover, so perhaps I'm just arguing semantics) 104 | 17:26 stickies-v: yes, just bounding it in size (e.g. by evicting earlier when it gets too large) would've been an alternative possibility, but in my opionion that would only make sense if mapRelay had an important use case in the first place (which doesn't seem to be the case anymore) 105 | 17:27 lightlike: yup, fully agreed 106 | 17:28 I think to be able to relay transactions that was mined in the most recent block, because it will be dropped from the mempool, hence m_most_recent_block_txs will help 107 | 17:28 lightlike: when a new block comes in and we validate it, we remove those transactions from our mempool, but we still want to be able to relay those recent txs to our peers, because they're very relevant 108 | 17:29 abubakarsadiq, stickies-v: correct! 109 | 17:29 Follow-up q: Do you think it is necessary to introduce it (as opposed to just removing mapRelay without any replacement)? 110 | 17:29 (I added this because im not completely convinced) 111 | 17:31 isn't that helpful for block propagation speed? if you receive a block but don't yet have all txs, you'd want to have as many peers as possible that can relay you that tx? 112 | 17:31 I wonder about the timing here. When we have received and connected a new block, wouldn't we immediately announce it to our peers, so they'd get the transactions from us anyway during compact block download? 113 | 17:31 so they wouldn't need to request them via GETDATA anyway? 114 | 17:32 what about peers that don't use compact blocks? 115 | 17:33 stickies-v: those peers would ask us for the entire BLOCK msg, it doesn't help them at all if we sent them the txns via GETDATA. 116 | 17:33 oh right 117 | 17:35 hmmm. would this be helpful during a chain split? a peer on a different tip would still benefit from being able to get the tx, and potentially won't have received it as part of a block? 118 | 17:37 stickies-v: yes, that might be the reason. 119 | 17:37 I think I'll try to add some extra logging on my node to see how often we'd actually answer getdata requests from m_most_recent_block_txs. 120 | 17:38 next question: What are the memory requirements for m_most_recent_block_txs compared to mapRelay? 121 | 17:41 i don't have the numbers, but it's bounded to the (in-memory) size of the `CTransaction`s in the previous block, plus a bit of overhead for the index etc? 122 | 17:43 stickies-v +1: unlike mapRelay which is unpredicatable 123 | 17:44 I think it's even less. We save the last block anyway in m_most_recent_block, which includes CTransactionRef (the shared pointer) to all its txns. So even after the txns are removed from the mempool, I think there won't be extra storage requirement for the actual transaction data. 124 | 17:46 ooohh I didn't see that, that's neat, yeah I think you're right 125 | 17:46 next q: Are there scenarios in which transactions would be made available for a shorter or longer time than before as a result of this change? 126 | 17:47 depends on the mining speed? 127 | 17:49 with `RELAY_TX_CACHE_TIME = 15min`, it looks like txs were expired from mapRelay after 15 mins, so I suppose they're available longer whenever there is more than 15 mins since the last block? 128 | 17:49 if mapRelay stored 15 minutes of blocks, then it could store more than a single block at certain times 129 | 17:51 yes - if blocks take longer, we'd keep some txns around for longer now. 130 | 17:51 and I think shorter whenever last block time <15 mins? 131 | 17:51 which makes perfect sense to me. 132 | 17:52 yes - if there are e.g. two blocks in <15 mins, the txns from the earlier wouldn't be kept around anymore 133 | 17:52 this seems ok, after all the 15 minute limit was rather arbitrary 134 | 17:53 block height is the only true time <3 135 | 17:54 and the peers should rather catch up with the chain instead of asking for old transactions, so I don't really see a downside. 136 | 17:55 but it might decrease availability of txns in case of chainsplits >1 maybe (which are extremely rare) 137 | 17:55 last question: Can you think of any other possible downsides of removing mapRelay? 138 | 17:56 I couldn't think of any, so I don't really expect any answers here :) 139 | 17:56 I think in case of reorg, having the `CONFLICT` transactions still in your mapRelay gives you a slight speed advantage? 140 | 17:57 only I think in the case of a reorg race? if you've marked it conflicted, you're now on a heavier chaintip, and you want peers to get stuff on that heavier chaintip 141 | 17:57 if there's a back and forth reorg, maybe 142 | 17:57 but that's no bueno 143 | 17:59 instagibbs: I don't actually mean from a relay pov, just for yourself to more quickly be able to validate the new chaintip? since you still have the tx you don't need to fetch it from a peer? 144 | 17:59 you're right that you wouldn't want to relay it to your peers 145 | 17:59 stickies-v: but would you actually try to fetch it from mapRelay in that scenario? 146 | 18:00 as in - does if the code currently does that? or if it's desirable? the former no idea, the latter I think so? 147 | 18:00 I meant the former. 148 | 18:01 yeah sorry no idea :-D also this is quite edge case and probably (definitely?) not worth optimizing for, just the only thing i could come up with 149 | 18:01 in any case, time's up. 150 | 18:01 Thanks everyone! 151 | 18:01 thanks for hosting lightlike 152 | 18:01 thank you lightlike! and MacroFake for authoring 153 | 18:01 Thanks lightlike and everyone else! 154 | 18:01 spending time avoiding reorgs through faster prop seems better value than handling them slightly faster... gut feeling :) thanks lightlike 155 | 18:02 yeah i agree 156 | 18:03 #endmeeting 157 | {% endirc %} 158 | -------------------------------------------------------------------------------- /_posts/2023-06-28-#27307.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2023-06-28 4 | title: "Track mempool conflicts with wallet transactions" 5 | pr: 27307 6 | authors: [ishaanam] 7 | components: ["wallet"] 8 | host: ishaanam 9 | status: past 10 | commit: 0538ad7 11 | --- 12 | 13 | ## Notes 14 | - In Bitcoin Core, every [wallet transaction](https://github.com/bitcoin/bitcoin/blob/7f0b79ea132d22ad5212c1d3ff4325715ca5ac12/src/wallet/transaction.h#L160) 15 | has a [transaction state](https://github.com/bitcoin/bitcoin/blob/7f0b79ea132d22ad5212c1d3ff4325715ca5ac12/src/wallet/transaction.h#L68) (detailed [here](https://gist.github.com/ishaanam/846adf3b453c3a85fe6e15c882c57ae0#types-of-tx-states)). 16 | These transaction states are part of how the wallet decides which 17 | transactions to allow the user to spend, and which transactions to 18 | count towards a user's balance. 19 | 20 | - Wallet transaction states and conflicts were previously discussed in 21 | review club [#27145](/27145) 22 | 23 | - When a transaction is `TxStateInactive`: 24 | - its inputs are considered spent, and 25 | - its outputs are not available to spend and don't count towards a 26 | user's balance 27 | 28 | - When a transaction is `TxStateConflicted`: 29 | - its inputs are _not_ considered spent, and 30 | - its outputs are not available to spend and don't count towards a 31 | user's balance 32 | 33 | - On master, wallet txs are only considered conflicted when the conflicting tx 34 | gets mined into a block. This means that if a transaction is only conflicted 35 | by a mempool tx, it is considered `TxStateInactive` instead. This can lead to 36 | [confusion](https://bitcoin-irc.chaincode.com/bitcoin-core-dev/2023-05-09#1683605157-1683612219;) 37 | amongst users, because the funds seem to briefly "disappear". 38 | 39 | - This PR treats transactions with conflicts in the mempool as conflicted 40 | as well, by adding another [transaction state for mempool-conflicted 41 | transactions](https://github.com/bitcoin/bitcoin/pull/27307/files#diff-d41d68c5a65d67956c91b33ca86da7df1981d84a0b15b4a186deea566563fed5R46-R49) 42 | and keeping track of the conflicting transactions in 43 | [`MempoolConflicts`](https://github.com/bitcoin/bitcoin/pull/27307/files#diff-9ce137cd784ea308778842120aa2af6d2bb8369485b71f25e72b2a32cf0a5b21R316-R318), 44 | a map of wallet tx hashes to a set of their mempool conflicts' tx 45 | hashes. 46 | 47 | - This idea and a previous attempt to implement it is described 48 | [here](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking#idea-mempool-conflicted) 49 | 50 | ## Questions 51 | 1. Did you review the PR? [Concept ACK, approach ACK, tested ACK, or 52 | NACK](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#peer-review)? 53 | What was your review approach? 54 | 55 | 1. Is this PR fixing a bug or adding a feature? What is that 56 | bug/feature? 57 | 58 | 1. What are the trade-offs with considering a mempool-conflicted 59 | transaction as conflicted instead of inactive? 60 | 61 | 1. Is the first commit necessary for this PR? Does it change any 62 | existing behavior? 63 | 64 | 1. What is the point of adding a `MempoolConflicts` map? Why can't the 65 | wallet just check for conflicts in `mapTxSpends`? 66 | 67 | 1. What is the benefit of adding another transaction state 68 | (`TxStateMempoolConflicted`) instead of just using `TxStateConflicted`? 69 | 70 | 1. Should a user be able to abandon a transaction with a mempool 71 | conflict? With this PR is a user able to do so? 72 | 73 | 1. After a wallet is reloaded, what will be the transaction state of a 74 | previously mempool-conflicted transaction? 75 | 76 | 1. Do the tests added to [`wallet_conflicts.py`](https://github.com/bitcoin-core-review-club/bitcoin/commit/0538ad7d4cfddb5a377f879cbf221b2b028c264a) fail on master for you? 77 | 78 | 1. This PR doesn't modify any of the balance calculation code directly, 79 | so how do the changes made in this PR affect the balance calculation of 80 | the wallet?xf 81 | 82 | 1. Are `TxStateConflicted` and `TxStateMempoolConflicted` transactions 83 | treated the same in memory? 84 | 85 | 1. Are there any additional test cases you would like to see 86 | implemented? 87 | 88 | 1. Why does `wallet_abandonconflict.py` need to be 89 | modified in the [second commit](https://github.com/bitcoin-core-review-club/bitcoin/commit/285d00523198ce352835d8360f8d79554b03bcd1)? 90 | 91 | ## Meeting Log 92 | 93 | {% irc %} 94 | 17:00 #startmeeting 95 | 17:00 Hey everyone, welcome to PR review club! 96 | 17:00 hi 97 | 17:00 hi 98 | 17:00 Today we will be reviewing #27307: "Track mempool conflicts with wallet transactions" 99 | 17:00 The notes and questions can be found here: https://bitcoincore.reviews/27307 100 | 17:01 hi 101 | 17:01 hi 102 | 17:01 Feel free to ask any questions! 103 | 17:01 Has anyone gotten a chance to review the PR or look at the notes? 104 | 17:01 hey do scripted diffs normally come in an independent pr?  i think yes right? 105 | 17:02 hello 106 | 17:02 One really basic question, is there a `CWalletTx` instance in memory for every tx that is either paying *to* this wallet or paying *from* this wallet? And both mined and unmined transactions? 107 | 17:03 Yes, and yes. 108 | 17:03 ishaanam[m] I did 109 | 17:03 evansmj: no, scripted diff is generally *one* commit within a larger PR 110 | 17:04 Great, can someone give a short summary of what this PR is doing? 111 | 17:05 ishaanam[m]: I was confused by the description of `TxStateConflicted` in the notes... its inputs are not spent (by another tx? and its outputs are not available to spend, for example immature coinbase? To me, that doesn't sounds "conflicted" ... so I must be missing something 112 | 17:05 creating a new tx state to the mempool conflicted tx 113 | 17:07 LarryRuane: To clarify, that was not about what makes a transaction TxStateConflicted, it was about how a wallet treats a TxStateConflicted transaction 114 | 17:08 oh i see, thanks, that helps a lot 115 | 17:08 Solving an intermittent issue where mempool droped transaction are marked as TxStateConflicted, by creating a new state for mempool dropped transaction 116 | 17:08 i thought it was defining those states 117 | 17:10 LarryRuane: yes, I think there was some confusion about that earlier as well, I think I'll go back and clarify the notes 118 | 17:10 I still didn't understand (sorry, you can go on) exactly which event(s) causes funds (by which I think you mean balance) to briefly disappear? And which event(s) cause them to come back? 119 | 17:11 But as I said, you can go on if everyone else gets it :) 120 | 17:11 abubakarasdiq: while a new transaction state is created for mempool conflicted transactions, I don't think that mempool dropped transactions were ever marked as TxStateConflicted? 121 | 17:12 Also, I want to clarify that this new transaction state is only applied to transactions which are conflicted by another transaction in the mempool, not transactions which have been dropped without conflicts 122 | 17:13 thanks 123 | 17:14 I think the PR tries to solve the issue of mempool conflicted transactions being treated as TxStateInactive by adding TxStateMempoolConflicted state 124 | 17:15 LarryRuane: Because the funds are marked as TxStateInactive when they are conflicted out of the mempool, the wallet will not show the outputs (the funds which disappear), but it will still consider the inputs as spent 125 | 17:15 BrandonOdiwuor: yes! 126 | 17:15 ishaanam[m]: +1 thanks 127 | 17:16 That being said, what are the trade-offs with considering a mempool-conflicted transaction as TxStateMempoolConflicted instead of TxStateInactive? 128 | 17:18 Meaning, is it more or less "safe", from a user's perspective 129 | 17:20 mempool-conflicted transaction inputs will no longer be considered as spent 130 | 17:20 Is it better to err on the side of caution and consider something as "spent" even if it technically is not, or consider something as "unspent" even though it's funds could potentially be spent (though not likely)? 131 | 17:21 considering something as spent that may not be seems like the more conservative view 132 | 17:21 +1 133 | 17:22 and in bitcoin we like to be conservative 😄 134 | 17:22 ;D 135 | 17:22 yes, that's true 136 | 17:23 What is the benefit of adding another transaction state (TxStateMempoolConflicted) instead of just using TxStateConflicted? 137 | 17:25 other wallets can differentiate between either mempool or block conflicts more clearly with the new state in transaction.h, and display it different or inform the user whats going on? 138 | 17:25 To distinguish between block conflicted and mempool conflicted transactions 139 | 17:25 Diferentiate the kind of conflict 140 | 17:26 evansmj: BrandonOdiwuor: Pins: Yes, to make the distinction more clear. 141 | 17:27 There was a previous attempt at this PR where TxStateConflicted was used 142 | 17:27 does marking a tx as a mempool-conflict consider it "spent" or "unspent"? 143 | 17:27 vs inactive 144 | 17:27 evansmj spent 145 | 17:29 I'm not very sure 146 | 17:29 Also, because previously mempool-conflicted states were serialized differently, a new tx state was introduced to maintain this behavior 147 | 17:29 evansmj: Pins: Marking a tx as mempool-conflicted means that it's inputs are "unspent" 148 | 17:30 ishaanam[m] Yes, sure ... thanks 149 | 17:30 The code for this is here: https://github.com/bitcoin/bitcoin/pull/27307/commits/2be57fea174b7079b86d3954413c7be1fd993db2#diff-69473389a98be9232528ccdef04f9fa51ce8c5558e64994e15589be924eebae3L259-R260 150 | 17:31 One thing that I found was pretty interesting, and I wasn't aware of, is `std::get_if` https://github.com/bitcoin/bitcoin/blob/d6ee03507f39223889a5f039c4db7204ddfb91d5/src/wallet/transaction.h#L314 ... that's some pretty advanced c++ 151 | 17:31 whats the difference between mempool conficted and mempool dropped transactions? 152 | 17:32 After a wallet is reloaded, what will be the transaction state of a previously mempool-conflicted transaction? 153 | 17:32 ishaanam[m] TxStateInactive 154 | 17:34 abubakarsadiq: the way I see it is that mempool conflicted transactions are a subset of mempool dropped transactions. 155 | 17:34 in master TxStateInactive, with this pr TxStateMempoolConflicted 156 | 17:34 mempool dropped transactions could have been dropped for some reason other than being conflicted 157 | 17:35 after a wallet reload will it go through WalletBatch::LoadWallet() which will start everything over again, or will it do the mapWallet check when a wallet is 'reloaded'? 158 | 17:35 For example, they could have been dropped from the mempool because of size-limiting 159 | 17:36 Pins: yes 160 | 17:37 abubakarsadiq: Because this PR doesn't change how mempool-conflicted transactions are serialized, and previously they would be considered TxStateInactive, it is still TxStateInactive 161 | 17:39 evansmj: it won't go through the mapTxSpends check that it does during `transactionAddedToMempool` and `transactionRemovedFromMempool`, if that's what you mean 162 | 17:40 Come to think of it, there should be a test for reloading a wallet with a mempool-conflicted transaction 163 | 17:40 Speaking of tests, has anyone tried running the added tests on master? 164 | 17:41 so just copy paste the new tests to master and make sure they fail? 165 | 17:42 evansmj: You could do that, or you could run git cherry-pick 0538ad7d4cfddb5a377f879cbf221b2b028c264a(the test commit hash) so that only the commit with the tests gets added to your master branch 166 | 17:43 evansmj: or can just run the test without compiling the pr 167 | 17:43 thanks ishaanam 168 | 17:45 Are there any additional test cases that you would like to see implemented? 169 | 17:49 What about the first commit of this PR, does it change any existing behavior? 170 | 17:50 This is the commit that I'm referring to: https://github.com/bitcoin/bitcoin/pull/27307/commits/2be57fea174b7079b86d3954413c7be1fd993db2 171 | 17:54 makes CachedTxIsTrusted() use the new tx state instead of checking tx depth 172 | 17:55 same for IsTxInMainChain() 173 | 17:55 I don't think that commit changed behavior. You could run the existing tests on just that commit and see if any fail. If none fail, this *may* be a behavior non-change. (I guess you still can't be sure.) 174 | 17:57 evansmj: yes, there were multiple places that used the depth instead of just checking the state 175 | 17:58 LarryRuane: Yes, this commit is interesting because it is technically just a refactor, but this PR won't work without it. This is because it changed the balance calculation by modifying IsSpent. 176 | 17:58 If depth was still used, then mempool-conflicted transactions would have a depth of 0, so their inputs would be considered as spent. 177 | 18:59 +1 makes sense 178 | 18:00 It looks like an hour is up 179 | 18:00 thanks everyone for coming! 180 | 18:00 #endmeeting 181 | {% endirc %} 182 | -------------------------------------------------------------------------------- /_posts/2023-11-15-v26-rc-testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2023-11-15 4 | title: "Testing Bitcoin Core 26.0 Release Candidates" 5 | components: ["tests"] 6 | host: m3dwards 7 | status: past 8 | commit: 9 | --- 10 | 11 | ## Notes 12 | 13 | - Major versions of Bitcoin Core are released every 6-8 months. See the [Life 14 | Cycle documentation](https://bitcoincore.org/en/lifecycle/) for full details. 15 | - When all of the PRs for a release have been merged, _Release Candidate 1_ 16 | (rc1) is tagged. The rc is then tested. If any issues are found, fixes are 17 | merged into the branch and a new rc is tagged. This continues until no major 18 | issues are found in an rc, and that rc is then considered to be the final 19 | release version. 20 | - To ensure that users don't experience issues with the new software, it's 21 | essential that the rcs are thoroughly tested. This special review club 22 | meeting is for people who want to help with that vital review process. 23 | 24 | - This [Bitcoin Core Release Candidate Testing 25 | Guide](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/26.0-Release-Candidate-Testing-Guide) provides guidance for testing the release candidate. 26 | 27 | - It is recommended to go through the "Preparation" steps ahead of the meeting, especially if you want to compile from source. Verify and confirm the successful installation of v26rc2. 28 | 29 | - For some of the tests, you might want to have the [signet](https://en.bitcoin.it/wiki/Signet) chain fully synced beforehand, so that you can just copy the signet directory into `/tmp/26-rc-test/` every time you run a test in a fresh environment. 30 | 31 | - The guide is just to get you started on testing, so feel free to read the [Release Notes](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/26.0-Release-Notes-Draft) 32 | and bring ideas of other things you'd like to test! 33 | 34 | ## Meeting Log 35 | {% irc %} 36 | 17:00 #startmeeting 37 | 17:00 hi everyone! 38 | 17:00 hi 39 | 17:01 hi 40 | 17:02 anyone here for the first time? even if you're just lurking, feel free to say hi! 41 | 17:04 not a massive turn out, it seems 42 | 17:05 hi, lurking 43 | 17:05 hello 44 | 17:05 ah, more people, yay! 45 | 17:06 we've got a special edition of review club planned for this week, ahead of the (hopefully soon) final release of Bitcoin Core v26 46 | 17:07 maxedw has prepared a fantastic guide to help test (some of) the new features of this new release: https://bitcoincore.reviews/v26-rc-testing 47 | 17:07 the purpose of this meeting really is just to go through it together 48 | 17:08 given that we're a bit of a smaller group, just polling if everyone's still keen to do that in this meeting, or if people would prefer to just go through it on their own pace? 49 | 17:08 thank you stickies-v 50 | 17:08 hello everyone, thanks for joining us for today's review club 51 | 17:08 we will be taking a look and a run through the Bitcoin Core 26.0 testing guide 52 | 17:08 link to the guide: https://github.com/bitcoin-core/bitcoin-devwiki/wiki/26.0-Release-Candidate-Testing-Guide 53 | 17:09 what operating systems are people running? 54 | 17:09 WSL Ubuntu 22.04 55 | 17:09 I will do some testing later this week at my own pace, so I'd be just lurking. 56 | 17:09 no problem lightlike 57 | 17:10 d33r_gee: great stuff 58 | 17:10 i'm on macos 13.4, m1 chip 59 | 17:10 great stickies-v, there is a macos only test that you will be able to help out on 60 | 17:10 today we will cover: getprioritisedtransactions rpc, mportmempool rpc, V2 Transport - BIP 324, TapMiniscript and Ancestor Aware Funding 61 | 17:11 I will leave the last test, Outbound connection management for you to do in your own time after this meeting 62 | 17:11 Did anyone manage to run through the preparation steps? No problem if not. 63 | 17:11 yep 64 | 17:12 fantastic, we won't need to spend much time getting prepped then 65 | 17:13 same here! 66 | 17:13 running compiled binaries 67 | 17:13 let's start the getprioritisedtransactions rpc test together 68 | 17:13 well, self compiled 69 | 17:13 this should be a relatively easy test to start us off 70 | 17:15 test works fine for me! 71 | 17:16 test went through no problems 72 | 17:16 well i did find something interesting 73 | 17:16 if i run the prioritisetransaction rpc twice on the same tx, the feerates compound 74 | 17:17 right, okay, that is in line with the documentation of the rpc: "The fee value (in satoshis) to add (or subtract, if negative)" 75 | 17:18 great to hear, it also worked on my machine 76 | 17:18 interesting stickies-v 77 | 17:18 https://github.com/bitcoin/bitcoin/blob/0aa014d5a34ed6b020b687ec924f8a17351f5aeb/src/rpc/mining.cpp#L455 78 | 17:18 if everyone is ready, let's move onto the second test 79 | 17:18 ready 80 | 17:19 importmempool 81 | 17:19 for this test, we can do it on mainnet (preferred) or on regtest. 82 | 17:19 does anyone have a mainnet node synced that they can test this RPC with? 83 | 17:21 yup 84 | 17:21 great 85 | 17:22 yup got one that was synced using an utxo snapshot 86 | 17:22 that's excellent 87 | 17:22 nice to see mainnet being used where possible 88 | 17:22 let's have a go at this one 89 | 17:24 you may need to pay attention to the environment variables $DATA_DIR to make sure you have it pointing to a bitcoind data directory that's synced 90 | 17:25 when I first ran  importmempool got this error: 91 | 17:25 error code: -10 92 | 17:25 error message: 93 | 17:25 Can only import the mempool after the block download and sync is done. 94 | 17:25 However waited a bit then reran and it worked 95 | 17:27 hmm, d33r_gee. I might have expected with `connect=0` it never to sync if it thought it was out of sync 96 | 17:27 but I think that's still a successful test 97 | 17:29 maxedw ah great I test it some more, do you think it may be because the chainstate came from a snapshot? 98 | 17:29 I'm not sure tbh 99 | 17:29 wouldn't have thought so 100 | 17:29 maxedw np 101 | 17:30 d33r_gee: what do you get when you run `bcli getblockcount`? 102 | 17:31 I think I might add a check into the test to make sure we are fully synced before we stop bitcoind 103 | 17:32 maxedw great idea 104 | 17:32 oh wait you're saying it worked eventually 105 | 17:32 at the moment mine says 816730 106 | 17:33 stickies-v yet waiting like 2min then reran and it worke 107 | 17:33 my importmempool is still running, seems to take quite a while for a big mempool 108 | 17:33 but mine is stuck from my previous test with connect=0 109 | 17:34 stickies-v: for me it didn't take long 110 | 17:34 did it take a while for you d33r_gee ? 111 | 17:35 maxedw yep took longer than the regtest one for sure 112 | 17:35 how big was yours maxedw? I've got ("bytes": 1716322) and I'm on a pretty old machine 113 | 17:35 "bytes": 8098791 114 | 17:37 interesting, looks like it's not really working for me then 115 | 17:39 let's pick this up after the call stickies-v 116 | 17:39 I just ran mine again and it completed in about 10 seconds 117 | 17:40 according to `top` it seems to be doing something, running with -debug=rpc and -debug=mempool but it doesn't really give me much, there's no intermediate logging 118 | 17:40 i'll just let it run and see what happens 119 | 17:40 great idea 120 | 17:40 this is exactly why we run these tests! 121 | 17:41 let's move on to the next test 122 | 17:41 oh wait 123 | 17:41 i have an interesting idea to test 124 | 17:41 on mainnet 125 | 17:41 go ahead stickies-v 126 | 17:42 what happens when you run importmempool, abort, run again, in very short sequence? 127 | 17:42 fyi, after my node synced my mempool size was similar to yours 128 | 17:42 (abort the cli request w ctr+c, not kill the daemon) 129 | 17:42 great question 130 | 17:43 I can give it a go. d33r_gee are you still in a position to try? 131 | 17:43 maxedw yep 132 | 17:43 my import finally succeeded: "Imported mempool transactions from disk: 40705 succeeded, 0 failed, 0 expired, 0 already there, 0 waiting for initial broadcast" 133 | 17:46 running importmempool right now 134 | 17:46 I reran the test with ctrl+c and then imported again and it worked for me 135 | 17:46 appears to anyway 136 | 17:46 it worked 137 | 17:46 "size": 48876 138 | 17:47 Imported mempool transactions from disk: 0 succeeded, 0 failed, 0 expired, 2959 already there, 0 waiting for initial broadcast 139 | 17:47 that is my second log message 140 | 17:47 so ctrl+c didn't appear to stop the import for me 141 | 17:47 I was quite quick at hitting it but maybe still too slow 142 | 17:47 or perhaps the command is running in another thread that doesn't exit 143 | 17:48 no ctrl+c on the cli doesn't affect the daemon, and we don't recognize remote client disconnects 144 | 17:48 so bitcoind keeps processing all requests even if the client's no longer listening 145 | 17:48 but i was wondering if running simultaneous importmempool tasks would cause issues 146 | 17:48 great, looks like it doesn't 147 | 17:49 I was perhaps not quick enough for it to be simultaneous 148 | 17:49 I will have another go after this meeting 149 | 17:49 shall we move onto the next test? 150 | 17:49 V2 transport 151 | 17:50 sounds good 152 | 17:50 which again could be done on different networks but for this guide we are using signet 153 | 17:51 I believe bitcoin.achow101.com should support v2 protocol on both signet and mainnet so please feel free to use whichever network you prefer 154 | 17:52 I just tried bitcoin.achow101.com on mainnet and got: Error: v2transport requested but not enabled (see -v2transport) 155 | 17:53 so I think if you plan to use that node, it's signet only at the moment 156 | 17:53 mmm i think that's an error on your side maxedw 157 | 17:53 you are right 158 | 17:54 I skipped a step 159 | 17:54 (didn't enable it for myself) 160 | 17:58 I now have: New manual v2 peer connected: version: 70016, blocks=816906, peer=18 161 | 17:59 hmmm i wasn't able to connect to achow but i think he just wasn't accepting new inbounds 162 | 17:59 will investigate more 163 | 17:59 the peer isn't listed in my peerinfo either 164 | 17:59 but I had that message in the logs 165 | 17:59 looks like we are out of time to run through the last couple of tests 166 | 18:00 #endmeeting 167 | {% endirc %} -------------------------------------------------------------------------------- /_posts/2025-03-19-v29-rc-testing.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: pr 3 | date: 2025-03-19 4 | title: "Testing Bitcoin Core 29.0 Release Candidates" 5 | authors: [janb84, arejula27, musaHaruna, Prabhat1308] 6 | components: ["tests"] 7 | host: janb84 8 | status: past 9 | commit: 10 | --- 11 | 12 | ## Notes 13 | 14 | - Major versions of Bitcoin Core are released every 6-8 months. See the [Life 15 | Cycle documentation](https://bitcoincore.org/en/lifecycle/) for full details. 16 | 17 | - When all of the PRs for a release have been merged, _Release Candidate 1_ 18 | (rc1) is tagged. The rc is then tested. If any issues are found, fixes are 19 | merged into the branch and a new rc is tagged. This continues until no major 20 | issues are found in an rc, and that rc is then considered to be the final 21 | release version. 22 | 23 | - To ensure that users don't experience issues with the new software, it's 24 | essential that the rcs are thoroughly tested. This special review club 25 | meeting is for people who want to help with that vital review process. 26 | 27 | - This [Bitcoin Core Release Candidate Testing 28 | Guide](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/29.0-Release-Candidate-Testing-Guide) provides guidance for testing the release candidate. 29 | 30 | - The guide is just to get you started on testing, so feel free to read the [Release Notes](https://github.com/bitcoin-core/bitcoin-devwiki/wiki/29.0-Release-Notes-Draft) 31 | and bring ideas of other things you'd like to test! 32 | 33 | ## Meeting Log 34 | {% irc %} 35 | 17:00 #startmeeting 36 | 17:00 hi 37 | 17:00 hi :D 38 | 17:00 hi 39 | 17:00 hi 40 | 17:00 hi 41 | 17:00 Hello everyone, 42 | 17:00 Welcome to the Bitcoin Review Club meeting! Today, we will be discussing the Release Testing Guide for the upcoming 29.0 release. These guides are essential for assisting people in testing the release candidates across various systems and environments. This time, we, the students of the 2025 Chaincode Labs Boss program, have had the privilege of writing it. 43 | 17:00 Typically, the Review Club focuses on discussing a pull request (PR), but this time we will be reviewing the Release Testing Guide. 44 | 17:00 You can find it here: 45 | 17:00 https://github.com/bitcoin-core/bitcoin-devwiki/wiki/29.0-Release-Candidate-Testing-Guide 46 | 17:01 Just a reminder to please be mindful of the review club meeting conventions: 47 | 17:01 Do not ask to ask a question, just ask! 48 | 17:01 The host moderates, not lead, just jump in :) 49 | 17:01 With that out of the way, let’s start ! 50 | 17:01 Did everyone get a chance already to test v29 (and use our guide)? How about a quick y/n from everyone! 51 | 17:01 n 52 | 17:01 n 53 | 17:02 I just did the build. 54 | 17:02 That is a good start :) 55 | 17:02 Any trouble doing that ? was it clear how to do it from the guide ? 56 | 17:04 it seems like there is a small issue with setting the v29 bin when building from source (https://github.com/bitcoin-core/bitcoin-devwiki/wiki/29.0-Release-Candidate-Testing-Guide#v29-from-source) 57 | 17:04 I actualy did not use the guide. Not the first time I'm doing it. 58 | 17:04 ah cool cool 59 | 17:04 should be "export BINARY_PATH_29=$RC_TEST_DIR/bitcoin/build/bin" after a recent change 60 | 17:05 yeah that is a good point @dzxzg 61 | 17:05 otherwise built and checked the versions and everything looks good (y) 62 | 17:06 I have made a note of this issue, but if you come across any other issues please make a comment to the issue list :) 63 | 17:07 https://github.com/bitcoin/bitcoin/issues/32026 64 | 17:07 Libnatpmp was replaced with a custom implementation of PCP and NAT-PMP. This supports automatic IPv4 port forwarding as well as IPv6 pinholing. We are interested in all test outcome, Please describe how to test this. 65 | 17:11 I ran the following command: bitcoind29 -signet -natpmp=1 -debug=net and looked for logging output about pcp in my terminal, as described in the testing guide 66 | 17:12 haha yeah thats it @dzxzg , kinda stupid question from me but it is a starter 67 | 17:12 I ran this command: cat $DATA_DIR_29/signet/debug.log | grep "pcp"  to grep for lines about pcp 68 | 17:12 But once you have started the node like that how can one check if the node is reachable 69 | 17:14 I think I have the feature off on my router. Getting this: pcp: Mapping failed with result NOT_AUTHORIZED (code 2) 70 | 17:15 I see this after my node requests port mapping "[net:warning] pcp: Could not send request: Operation not permitted (1)"  looks like it doesn't work on my network! 71 | 17:16 @emzy correct ! looks like pnp is not enabled 72 | 17:16 or pcp 73 | 17:16 These testcases are also very valuable ! the developers would love to know if you could setup a connection and if PNP is enabled by default. 74 | 17:16 Please if you are able to do so create a comment here: https://github.com/bitcoin/bitcoin/issues/31663 75 | 17:17 They would also like the know the route brand/model 76 | 17:18 Does anyone has IpV6 enabled on their network ? 77 | 17:21 Yes 78 | 17:22 In the RPC updated methods, **mainnet** and **regtest** are used. Is it okay, or would it be better to test all methods only on **regtest**? 79 | 17:22 I have a FRITZ!Box 7530 AX. But I changed a lot of settinge :) 80 | 17:23 @emzy do you get any feedback on ipv6 pinholing being succesful ? 81 | 17:26 @dzxzg is the connection issues related to PCP test? or just a coincedence ? 82 | 17:27 ipv4 pcp seems to work now, that I allowed it: "[net:info] portmap: Added mapping pcp:87.x.x.x:38333 -> 192.168.99.114:38333 (for 120s)" 83 | 17:28 I think it's just a coincidence, firefox garbage collecting my web.libera.chat tab :) 84 | 17:28 looks like the "pcp: Mapping failed with result NOT_AUTHORIZED (code 2)" is from ipv6 85 | 17:28 @emzy even if you have changed a lot of settings, i think it's valueble to create a comment to share these findings 86 | 17:28 ok, will do. 87 | 17:29 I'll share my router and settings in that issue as well 88 | 17:30 is there a way to see the active mappings? It could be that just one of my ipv6 are NOT_AUTHORIZED 89 | 17:31 that's a good question @emzy i do not know. 90 | 17:32 from the log, it seems only the ipv4 pcp was working. 91 | 17:32 emzy: not sure if there's any rpc command for that, but you can see the mappings that get set using: `cat $DATA_DIR_29/regtest/debug.log | grep -i "pcp"` 92 | 17:33 @emzy the ai tells me you would be able to see that in your Fritzbox, Network settings -> View active connections 93 | 17:37 Looks more it is at: Internet > Permit Access > Port Sharing. I can see the ipv4 pcp there. 94 | 17:37 I'm a networking guy. But the Fritzbox is made for normal people. Hard to use for me :) 95 | 17:37 @emzy AI.. so yeah :') But glad you found it 96 | 17:38 I will look into it. And make a comment about it. 97 | 17:38 @emzy thanks 98 | 17:39 The issue also mentions that one can test if the mapping is successful by using nn 99 | 17:39 nc -v -n -z 8444 100 | 17:40 ofc replace redacted with external ip and port with the correct port 101 | 17:42 Does anyone of you have a question about the guide ? or some remarks or missing something. We did not know how to create a test for the Ephemeral dust feature, if one of you would have a clue please create a comment in the feedback issue 102 | 17:43 just tested to connect my local node. It works from a public node! 103 | 17:43 in ipv4 nbwl2 2 24 24 0 34 1 1 15 70016/Satoshi:27.1.0(@emzy)/ 104 | 17:44 @emzy nice ! thats a great result ! 105 | 17:44 in ipv4 nbwl2 2 22 22 13 1 1 2 15 178.63.87.163:44900 106 | 17:45 nice 107 | 17:47 @dzxzg thank you for also creating a comment about your PCP findings ! 108 | 17:48 Any questions ? if not I will wrap up this meeting in 5 minutes. 109 | 17:53 Thank you all for joining and actively participating! If you have any feedback, please leave a comment here: 110 | 17:53 https://github.com/bitcoin/bitcoin/issues/32026 111 | 17:53 None from me, I have to drop but thanks to all who wrote the testing guide and thank you janb84 for hosting! 112 | 17:53 Thanks once again! 113 | 17:53 #endmeeting 114 | {% endirc %} 115 | -------------------------------------------------------------------------------- /assets/css/1-tools/_-tools-dir.sass: -------------------------------------------------------------------------------- 1 | @import 'normalize/import-now' 2 | @import 'social-media-icons' 3 | @import 'code' 4 | @import 'syntax' 5 | -------------------------------------------------------------------------------- /assets/css/1-tools/_code.scss: -------------------------------------------------------------------------------- 1 | pre, 2 | code { 3 | border-radius: 3px; 4 | background-color: var(--code-bg-color); 5 | font-family: monospace; 6 | margin-top: 1rem; 7 | margin-bottom: 1rem; 8 | line-height: 1.5; 9 | } 10 | code { 11 | padding: 1px 5px; 12 | } 13 | pre { 14 | padding: 8px 12px; 15 | overflow-x: auto; 16 | > code { 17 | border: 0; 18 | padding-right: 0; 19 | padding-left: 0; 20 | } 21 | } 22 | .highlight .lineno { 23 | color: #aaa; 24 | display:inline-block; 25 | padding: 0 5px; 26 | border-right:1px solid #ccc; 27 | } 28 | .highlight pre code { 29 | display: block; 30 | white-space: pre-wrap; 31 | overflow-x: auto; 32 | word-wrap: normal; 33 | } 34 | -------------------------------------------------------------------------------- /assets/css/1-tools/_normalize.scss: -------------------------------------------------------------------------------- 1 | @import 'normalize/variables'; 2 | @import 'normalize/vertical-rhythm'; 3 | @import 'normalize/normalize-mixin'; 4 | -------------------------------------------------------------------------------- /assets/css/1-tools/_social-media-icons.sass: -------------------------------------------------------------------------------- 1 | $icon-transition-time: 0s 2 | $envelope-color: #f39c12 3 | $twitter-color: #00aced 4 | $instagram-color: #375989 5 | $github-color: #343434 6 | $linkedin-color: #0073a4 7 | $facebook-color: #3d5b99 8 | $google-color: #e64a41 9 | $pinterest-color: #bd081c 10 | $medium-color: #00AB6C 11 | $codepen-color: black 12 | $rss-color: #ff6600 13 | 14 | @mixin social-media-icon($color, $transition) 15 | -webkit-transition: $transition 16 | -o-transition: $transition 17 | -ms-transition: $transition 18 | -moz-transition: $transition 19 | transition: $transition 20 | &:hover 21 | color: $color 22 | 23 | .fa-envelope 24 | @include social-media-icon($envelope-color, $icon-transition-time) 25 | 26 | .fa-twitter 27 | @include social-media-icon($twitter-color, $icon-transition-time) 28 | 29 | .fa-instagram 30 | @include social-media-icon($instagram-color, $icon-transition-time) 31 | 32 | .fa-github 33 | @include social-media-icon($github-color, $icon-transition-time) 34 | 35 | .fa-linkedin 36 | @include social-media-icon($linkedin-color, $icon-transition-time) 37 | 38 | .fa-facebook 39 | @include social-media-icon($facebook-color, $icon-transition-time) 40 | 41 | .fa-google-plus 42 | @include social-media-icon($google-color, $icon-transition-time) 43 | 44 | .fa-pinterest 45 | @include social-media-icon($pinterest-color, $icon-transition-time) 46 | 47 | .fa-medium 48 | @include social-media-icon($medium-color, $icon-transition-time) 49 | 50 | .fa-codepen 51 | @include social-media-icon($codepen-color, $icon-transition-time) 52 | 53 | .fa-rss-square 54 | @include social-media-icon($rss-color, $icon-transition-time) 55 | -------------------------------------------------------------------------------- /assets/css/1-tools/_syntax.scss: -------------------------------------------------------------------------------- 1 | .highlight .hll { background-color: #ffc; } 2 | .highlight .c { color: #999; } /* Comment */ 3 | .highlight .err { color: #a00; background-color: #faa } /* Error */ 4 | .highlight .k { color: #069; } /* Keyword */ 5 | .highlight .o { color: #555 } /* Operator */ 6 | .highlight .cm { color: #09f; font-style: italic } /* Comment.Multiline */ 7 | .highlight .cp { color: #099 } /* Comment.Preproc */ 8 | .highlight .c1 { color: #999; } /* Comment.Single */ 9 | .highlight .cs { color: #999; } /* Comment.Special */ 10 | .highlight .gd { background-color: #fcc; border: 1px solid #c00 } /* Generic.Deleted */ 11 | .highlight .ge { font-style: italic } /* Generic.Emph */ 12 | .highlight .gr { color: #f00 } /* Generic.Error */ 13 | .highlight .gh { color: #030; } /* Generic.Heading */ 14 | .highlight .gi { background-color: #cfc; border: 1px solid #0c0 } /* Generic.Inserted */ 15 | .highlight .go { color: #aaa } /* Generic.Output */ 16 | .highlight .gp { color: #009; } /* Generic.Prompt */ 17 | .highlight .gs { } /* Generic.Strong */ 18 | .highlight .gu { color: #030; } /* Generic.Subheading */ 19 | .highlight .gt { color: #9c6 } /* Generic.Traceback */ 20 | .highlight .kc { color: #069; } /* Keyword.Constant */ 21 | .highlight .kd { color: #069; } /* Keyword.Declaration */ 22 | .highlight .kn { color: #069; } /* Keyword.Namespace */ 23 | .highlight .kp { color: #069 } /* Keyword.Pseudo */ 24 | .highlight .kr { color: #069; } /* Keyword.Reserved */ 25 | .highlight .kt { color: #078; } /* Keyword.Type */ 26 | .highlight .m { color: #f60 } /* Literal.Number */ 27 | .highlight .s { color: #d44950 } /* Literal.String */ 28 | .highlight .na { color: #4f9fcf } /* Name.Attribute */ 29 | .highlight .nb { color: #366 } /* Name.Builtin */ 30 | .highlight .nc { color: #0a8; } /* Name.Class */ 31 | .highlight .no { color: #360 } /* Name.Constant */ 32 | .highlight .nd { color: #99f } /* Name.Decorator */ 33 | .highlight .ni { color: #999; } /* Name.Entity */ 34 | .highlight .ne { color: #c00; } /* Name.Exception */ 35 | .highlight .nf { color: #c0f } /* Name.Function */ 36 | .highlight .nl { color: #99f } /* Name.Label */ 37 | .highlight .nn { color: #0cf; } /* Name.Namespace */ 38 | .highlight .nt { color: #2f6f9f; } /* Name.Tag */ 39 | .highlight .nv { color: #033 } /* Name.Variable */ 40 | .highlight .ow { color: #000; } /* Operator.Word */ 41 | .highlight .w { color: #bbb } /* Text.Whitespace */ 42 | .highlight .mf { color: #f60 } /* Literal.Number.Float */ 43 | .highlight .mh { color: #f60 } /* Literal.Number.Hex */ 44 | .highlight .mi { color: #f60 } /* Literal.Number.Integer */ 45 | .highlight .mo { color: #f60 } /* Literal.Number.Oct */ 46 | .highlight .sb { color: #c30 } /* Literal.String.Backtick */ 47 | .highlight .sc { color: #c30 } /* Literal.String.Char */ 48 | .highlight .sd { color: #c30; font-style: italic } /* Literal.String.Doc */ 49 | .highlight .s2 { color: #c30 } /* Literal.String.Double */ 50 | .highlight .se { color: #c30; } /* Literal.String.Escape */ 51 | .highlight .sh { color: #c30 } /* Literal.String.Heredoc */ 52 | .highlight .si { color: #a00 } /* Literal.String.Interpol */ 53 | .highlight .sx { color: #c30 } /* Literal.String.Other */ 54 | .highlight .sr { color: #3aa } /* Literal.String.Regex */ 55 | .highlight .s1 { color: #c30 } /* Literal.String.Single */ 56 | .highlight .ss { color: #fc3 } /* Literal.String.Symbol */ 57 | .highlight .bp { color: #366 } /* Name.Builtin.Pseudo */ 58 | .highlight .vc { color: #033 } /* Name.Variable.Class */ 59 | .highlight .vg { color: #033 } /* Name.Variable.Global */ 60 | .highlight .vi { color: #033 } /* Name.Variable.Instance */ 61 | .highlight .il { color: #f60 } /* Literal.Number.Integer.Long */ 62 | 63 | .css .o, 64 | .css .o + .nt, 65 | .css .nt + .nt { color: #999; } 66 | 67 | @media (prefers-color-scheme: dark) { 68 | .highlight .gd { color: black } 69 | .highlight .gi { color: black } 70 | } 71 | -------------------------------------------------------------------------------- /assets/css/1-tools/normalize/_import-now.scss: -------------------------------------------------------------------------------- 1 | // Import Now 2 | // 3 | // If you import this module directly, it will immediately output all the CSS 4 | // needed to normalize default HTML elements across all browsers. 5 | // 6 | // ``` 7 | // @import "normalize/import-now"; 8 | // ``` 9 | 10 | @import '../normalize'; 11 | @include normalize(); 12 | -------------------------------------------------------------------------------- /assets/css/1-tools/normalize/_variables.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Variables 3 | // 4 | // You can override the default values by setting the variables in your Sass 5 | // before importing the normalize-scss library. 6 | 7 | // The font size set on the root html element. 8 | $base-font-size: 16px !default; 9 | 10 | // The base line height determines the basic unit of vertical rhythm. 11 | $base-line-height: 24px !default; 12 | 13 | // The length unit in which to output vertical rhythm values. 14 | // Supported values: px, em, rem. 15 | $base-unit: 'em' !default; 16 | 17 | // The default font family. 18 | $base-font-family: null !default; 19 | 20 | // The font sizes for h1-h6. 21 | $h1-font-size: 2 * $base-font-size !default; 22 | $h2-font-size: 1.5 * $base-font-size !default; 23 | $h3-font-size: 1.17 * $base-font-size !default; 24 | $h4-font-size: 1 * $base-font-size !default; 25 | $h5-font-size: 0.83 * $base-font-size !default; 26 | $h6-font-size: 0.67 * $base-font-size !default; 27 | 28 | // The amount lists and blockquotes are indented. 29 | $indent-amount: 40px !default; 30 | 31 | // The following variable controls whether normalize-scss will output 32 | // font-sizes, line-heights and block-level top/bottom margins that form a basic 33 | // vertical rhythm on the page, which differs from the original Normalize.css. 34 | // However, changing any of the variables above will cause 35 | // $normalize-vertical-rhythm to be automatically set to true. 36 | $normalize-vertical-rhythm: false !default; 37 | -------------------------------------------------------------------------------- /assets/css/1-tools/normalize/_vertical-rhythm.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Vertical Rhythm 3 | // 4 | // This is the minimal amount of code needed to create vertical rhythm in our 5 | // CSS. If you are looking for a robust solution, look at the excellent Typey 6 | // library. @see https://github.com/jptaranto/typey 7 | 8 | @function normalize-rhythm($value, $relative-to: $base-font-size, $unit: $base-unit) { 9 | @if unit($value) != px { 10 | @error "The normalize vertical-rhythm module only supports px inputs. The typey library is better."; 11 | } 12 | @if $unit == rem { 13 | @return ($value / $base-font-size) * 1rem; 14 | } 15 | @else if $unit == em { 16 | @return ($value / $relative-to) * 1em; 17 | } 18 | @else { // $unit == px 19 | @return $value; 20 | } 21 | } 22 | 23 | @mixin normalize-font-size($value, $relative-to: $base-font-size) { 24 | @if unit($value) != 'px' { 25 | @error "normalize-font-size() only supports px inputs. The typey library is better."; 26 | } 27 | font-size: normalize-rhythm($value, $relative-to); 28 | } 29 | 30 | @mixin normalize-rhythm($property, $values, $relative-to: $base-font-size) { 31 | $value-list: $values; 32 | $sep: space; 33 | @if type-of($values) == 'list' { 34 | $sep: list-separator($values); 35 | } 36 | @else { 37 | $value-list: append((), $values); 38 | } 39 | 40 | $normalized-values: (); 41 | @each $value in $value-list { 42 | @if unitless($value) and $value != 0 { 43 | $value: $value * normalize-rhythm($base-line-height, $relative-to); 44 | } 45 | $normalized-values: append($normalized-values, $value, $sep); 46 | } 47 | #{$property}: $normalized-values; 48 | } 49 | 50 | @mixin normalize-margin($values, $relative-to: $base-font-size) { 51 | @include normalize-rhythm(margin, $values, $relative-to); 52 | } 53 | 54 | @mixin normalize-line-height($font-size, $min-line-padding: 2px) { 55 | $lines: ceil($font-size / $base-line-height); 56 | // If lines are cramped include some extra leading. 57 | @if ($lines * $base-line-height - $font-size) < ($min-line-padding * 2) { 58 | $lines: $lines + 1; 59 | } 60 | @include normalize-rhythm(line-height, $lines, $font-size); 61 | } 62 | -------------------------------------------------------------------------------- /assets/css/2-base/_-base-dir.sass: -------------------------------------------------------------------------------- 1 | @import 'base' 2 | -------------------------------------------------------------------------------- /assets/css/2-base/_base.sass: -------------------------------------------------------------------------------- 1 | /* Basic Styles */ 2 | 3 | body 4 | font-family: $body-font 5 | line-height: 1.5 6 | 7 | blockquote 8 | margin: 10px 20px 10px 9 | padding: 0.5em 15px 10 | border-left: 0.25rem solid #ccc 11 | color: #999 12 | line-height: 1.5 13 | -------------------------------------------------------------------------------- /assets/css/3-sections/_-sections-dir.sass: -------------------------------------------------------------------------------- 1 | @import 'default' 2 | -------------------------------------------------------------------------------- /assets/css/3-sections/_default.sass: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/css/3-sections/_default.sass -------------------------------------------------------------------------------- /assets/css/Source+Code+Pro.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Source Code Pro'; 3 | font-style: normal; 4 | font-weight: 400; 5 | src: local('Source Code Pro Regular'), local('SourceCodePro-Regular'), url(/assets/fonts/Source+Code+Pro.ttf) format('truetype'); 6 | } 7 | -------------------------------------------------------------------------------- /assets/css/all.sass: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | //Typography 5 | $body-font: 'Helvetica', sans-serif 6 | $code-font: monospace 7 | 8 | //Colour Palette 9 | $sunc-yellow: #FEE04E 10 | $light-blue: #55ACEE 11 | $hungry-mind-blue: #268BD2 12 | 13 | $primary-color: #000000 14 | $secondary-color: #FEE04E 15 | 16 | //Screen size for responsiveness 17 | $small-screen: 320px 18 | $mid-screen: 768px 19 | $large-screen: 1024px 20 | 21 | @import '1-tools/-tools-dir' 22 | @import '2-base/-base-dir' 23 | @import '3-sections/-sections-dir' 24 | 25 | /* This is an example style sheet that comes default - just delete everything after this comment this to start from a blank slate */ 26 | 27 | html 28 | height: 100% 29 | 30 | body 31 | height: 100% 32 | min-height: 100% 33 | 34 | // Light (default) 35 | .site-container 36 | --bg-color: white 37 | --text-color: black 38 | --link-color: #0000f0 39 | --link-visited-color: #551b8c 40 | --code-bg-color: #f5f5f5 41 | --log-bg-color: #f0f0f0 42 | --log-color: #808080 43 | --target-color: #dddddd 44 | --meeting-index-color: #606060 45 | --icon-color: black 46 | 47 | // Dark mode using media query 48 | @media (prefers-color-scheme: dark) 49 | html, body 50 | background-color: #1D1E20 51 | 52 | .site-container 53 | --bg-color: #1D1E20 54 | --text-color: #C4C4C5 55 | --link-color: #58a6ff 56 | --link-visited-color: #824bb7 57 | --code-bg-color: #37383E 58 | --log-bg-color: #37383E 59 | --log-color: #080808 60 | --target-color: #3a3939 61 | --meeting-index-color: #8c5e5e 62 | --icon-color: white 63 | 64 | a 65 | color: var(--link-color) 66 | 67 | a 68 | &:visited 69 | color: var(--link-visited-color) 70 | 71 | a 72 | &:hover 73 | color: $secondary-color 74 | 75 | .site-container 76 | margin: 0 77 | padding: 1rem 2rem 0 2rem 78 | background-color: var(--bg-color) 79 | color: var(--text-color) 80 | min-height: 100% 81 | overflow: auto 82 | 83 | .page-content 84 | max-width: 1200px 85 | margin: 0 auto 86 | 87 | .logo 88 | text-decoration: none 89 | color: var(--text-color) 90 | font: 91 | size: 48px 92 | a 93 | color: var(--text-color) 94 | 95 | .dt-published 96 | color: #828282 97 | font-size: 0.95em 98 | 99 | .host 100 | color: #828282 101 | font-size: 0.95em 102 | 103 | .author 104 | color: #828282 105 | font-size: 0.95em 106 | 107 | \:target 108 | background: var(--target-color) 109 | 110 | .question 111 | font-size: 1.2em 112 | font-weight: bold 113 | 114 | .meetings-index-section 115 | margin-top: 0.4em 116 | margin-bottom: 0.4em 117 | color: var(--meeting-index-color) 118 | 119 | .Home-posts-post-date 120 | min-width: 94px 121 | vertical-align: text-top 122 | 123 | .Home-posts-post-arrow 124 | padding-right: 4px 125 | vertical-align: text-top 126 | 127 | .Home-posts-post-pr 128 | font-weight: bold 129 | 130 | .padded 131 | padding: 1rem 1rem 0 0 132 | 133 | .log-line 134 | margin-block-start: 0px 135 | margin-block-end: 0px 136 | font-family: monospace 137 | border-spacing: 0px 138 | 139 | .log-row 140 | vertical-align: top 141 | 142 | .log-lineno 143 | background-color: var(--log-bg-color) 144 | \:target 145 | background-color: var(--target-color) 146 | a 147 | color: (--log-color) 148 | text-decoration: none 149 | user-select: none 150 | 151 | .log-time 152 | color: var(--link-color) 153 | padding-left: 6px 154 | padding-right: 6px 155 | 156 | .log-nick 157 | font-weight: bold 158 | color: green 159 | 160 | .log-msg 161 | padding-left: 0px 162 | white-space: pre-wrap 163 | 164 | .social-media-links 165 | font-size: 50% 166 | display: flex 167 | align-items: flex-end 168 | 169 | .fa 170 | color: var(--icon-color) 171 | -------------------------------------------------------------------------------- /assets/fonts/Source+Code+Pro.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/fonts/Source+Code+Pro.ttf -------------------------------------------------------------------------------- /assets/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /assets/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /assets/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /assets/img/18113-coins-table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/18113-coins-table.png -------------------------------------------------------------------------------- /assets/img/18267-signet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/18267-signet.png -------------------------------------------------------------------------------- /assets/img/19953-taproot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/19953-taproot.png -------------------------------------------------------------------------------- /assets/img/20827-pruning.drawio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/20827-pruning.drawio.png -------------------------------------------------------------------------------- /assets/img/22950-full.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/22950-full.jpg -------------------------------------------------------------------------------- /assets/img/22950-pimpl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/22950-pimpl.png -------------------------------------------------------------------------------- /assets/img/22950-pure-abstract.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/22950-pure-abstract.png -------------------------------------------------------------------------------- /assets/img/cluster219.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/cluster219.jpg -------------------------------------------------------------------------------- /assets/img/cluster881.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/cluster881.jpg -------------------------------------------------------------------------------- /assets/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/favicon.ico -------------------------------------------------------------------------------- /assets/img/minisketch-26-math-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/minisketch-26-math-1.jpg -------------------------------------------------------------------------------- /assets/img/minisketch-26-math-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/minisketch-26-math-2.jpg -------------------------------------------------------------------------------- /assets/img/minisketch-26-math-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/minisketch-26-math-3.jpg -------------------------------------------------------------------------------- /assets/img/minisketch-26-math-4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/minisketch-26-math-4.jpg -------------------------------------------------------------------------------- /assets/img/package_cpfp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/package_cpfp.png -------------------------------------------------------------------------------- /assets/img/package_low_and_modified.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/package_low_and_modified.png -------------------------------------------------------------------------------- /assets/img/package_mempool_examples.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/package_mempool_examples.jpg -------------------------------------------------------------------------------- /assets/img/package_mixed_feerate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/package_mixed_feerate.png -------------------------------------------------------------------------------- /assets/img/package_rich_parent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/package_rich_parent.png -------------------------------------------------------------------------------- /assets/img/script_output_types_blank.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/script_output_types_blank.png -------------------------------------------------------------------------------- /assets/img/script_output_types_sols.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/script_output_types_sols.png -------------------------------------------------------------------------------- /assets/img/twitter_card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bitcoin-core-review-club/website/ba5754b5b51de719e74835dd42c6ad15e48d6276/assets/img/twitter_card.png -------------------------------------------------------------------------------- /assets/txt/22950-abstract-class.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pimpl2.h" 3 | 4 | 5 | class PeerManagerImpl final : public PeerManager { 6 | int m_best_height; 7 | 8 | public: 9 | PeerManagerImpl(int ctor_int); 10 | 11 | void SetBestHeight(int height) override { 12 | m_best_height = height; 13 | std::cout << "setting m_best_height to " << height << std::endl; 14 | }; 15 | 16 | int GetMax(int a, int b) const override { 17 | return GetMax(a, b); 18 | } 19 | 20 | long GetMax(long a, long b) const override { 21 | return GetMax(a, b); 22 | } 23 | 24 | template 25 | T GetMax(T a, T b) const; 26 | }; 27 | 28 | 29 | template 30 | T PeerManagerImpl::GetMax(T a, T b) const 31 | { 32 | T result; 33 | result = (a > b) ? a : b; 34 | return result; 35 | } 36 | 37 | std::unique_ptr PeerManager::make(int caller_int) 38 | { 39 | return std::make_unique(caller_int); 40 | } 41 | 42 | PeerManagerImpl::PeerManagerImpl(int ctor_int) 43 | : m_best_height(ctor_int) 44 | { 45 | std::cout << "impl ctor, m_best_height: " << ctor_int << std::endl; 46 | } 47 | 48 | int main() { 49 | auto peerman = PeerManager::make(3); 50 | peerman->SetBestHeight(4); 51 | peerman->SetBestHeight(11); 52 | 53 | std::cout << peerman->GetMax(4, 11) << std::endl; 54 | std::cout << peerman->GetMax((long)6, (long)11) << std::endl; 55 | 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /assets/txt/22950-abstract-class.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class PeerManager 4 | { 5 | public: 6 | static std::unique_ptr make(int ctor_int); 7 | virtual ~PeerManager() {} 8 | 9 | virtual void SetBestHeight(int height) = 0; 10 | 11 | virtual int GetMax(int a, int b) const = 0; 12 | virtual long GetMax(long a, long b) const = 0; 13 | }; 14 | -------------------------------------------------------------------------------- /assets/txt/22950-pimpl.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "pimpl.h" 3 | 4 | class TxRequestTracker::Impl { 5 | int my_i; 6 | 7 | public: 8 | Impl(int i) : my_i(i) {} 9 | ~Impl() {} 10 | 11 | void Count(int peer_id) const { 12 | auto val = (peer_id == my_i) ? "yup" : "nope"; 13 | std::cout << val << std::endl; 14 | } 15 | 16 | template 17 | T GetMax(T a, T b); 18 | 19 | }; 20 | 21 | template 22 | T TxRequestTracker::Impl::GetMax(T a, T b) { 23 | T result; 24 | result = (a > b) ? a : b; 25 | return result; 26 | } 27 | 28 | TxRequestTracker::TxRequestTracker(int i) 29 | : m_impl(std::make_unique(i)) {} 30 | 31 | TxRequestTracker::~TxRequestTracker() = default; 32 | 33 | void TxRequestTracker::Count(int peer_id) const { return m_impl->Count(peer_id); } 34 | 35 | template 36 | T TxRequestTracker::GetMax(T a, T b) { 37 | return m_impl->GetMax(a, b); 38 | } 39 | 40 | int main() { 41 | TxRequestTracker m_txrequest{3}; 42 | m_txrequest.Count(8); 43 | m_txrequest.Count(3); 44 | 45 | std::cout << m_txrequest.GetMax(4, 6) << std::endl; 46 | std::cout << m_txrequest.GetMax(4, 6) << std::endl; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /assets/txt/22950-pimpl.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | class TxRequestTracker { 4 | class Impl; 5 | const std::unique_ptr m_impl; 6 | 7 | public: 8 | explicit TxRequestTracker(int i); 9 | ~TxRequestTracker(); 10 | 11 | void Count(int peer_id) const; 12 | 13 | template 14 | T GetMax(T a, T b); 15 | }; 16 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Code of Conduct 4 | --- 5 | 6 | # Code of Conduct 7 | 8 | The PR Review Club is designed to be a safe, respectful, and productive 9 | environment for everyone. We are dedicated to providing a harassment-free 10 | experience for all participants regardless of race, gender, age, sexual 11 | orientation, disability, physical appearance, national origin, ethnicity, or 12 | religion. This code of conduct is a guide for the behavior we support and don't 13 | support at our club meetings. 14 | 15 | #### Conduct 16 | 17 | Examples of behavior that contribute to a positive environment include: 18 | 19 | - Using welcoming and inclusive language 20 | - Being respectful of differing viewpoints and experiences 21 | - Gracefully accepting constructive criticism 22 | - Focusing on what is best for the community 23 | - Showing empathy towards other community members 24 | 25 | Examples of unacceptable behavior by participants include: 26 | 27 | - [Harassment](#harassment) 28 | - Public promotional activities 29 | - Questioning or challenging someone’s stated self-identity or chosen labels 30 | - Making general statements about groups you do not belong to 31 | - Incitement of violence towards any individual 32 | - Unauthorized publication of private information or communication 33 | - Unwelcome comments regarding a person’s lifestyle choices and practices, 34 | including those related to food, health, parenting, relationships, drugs, and 35 | employment 36 | - Gratuitous or off-topic sexual images or behaviour 37 | 38 | #### Harassment 39 | 40 | Harrassment can take many forms. Examples include, but are not limited to: 41 | 42 | - Threats of violence 43 | - Deliberate intimidation 44 | - Stalking or following 45 | - Unwanted recording, including logging online activity for harassment purposes 46 | - Sustained disruption of discussion 47 | - Unwelcome sexual attention 48 | - Pattern of inappropriate social contact, such as requesting/assuming 49 | inappropriate levels of intimacy with others 50 | - Continued one-on-one communication after requests to cease 51 | - Offensive comments or personal questions relating to gender, gender identity 52 | and expression, sexual orientation, disability, mental illness, 53 | neuro(a)typicality, physical appearance, body size, age, race, national origin, 54 | ethnic origin, nationality, immigration status, language, religion or lack 55 | thereof, or other identity marker 56 | 57 | #### If you see a violation 58 | 59 | 1. Notify the participant they are in violation of the code of conduct and ask 60 | them to stop their behavior. That participant should comply immediately. 61 | 62 | 2. If the participant does not correct the issue or if you’re uncomfortable 63 | speaking up, contact the administrator. When reporting, please include any 64 | relevant details, links, screenshots, context that may be used to better 65 | understand and resolve the situation. 66 | 67 | 3. As soon as available, an administrator will join, identify themselves, and 68 | take further action. These actions could include: 69 | 70 | - A warning 71 | - Removal from the club’s channel for the duration of the ongoing meeting 72 | - Being banned from all future club meetings 73 | 74 | We reserve the right to reject any report we believe to have been made in bad 75 | faith. Reports intended to silence legitimate criticism may be deleted without 76 | response. 77 | 78 | We will respect confidentiality requests for the purpose of protecting victims 79 | of abuse. At our discretion, we may publicly name a person about whom we’ve 80 | received harassment complaints, or privately warn third parties about them, if 81 | we believe that doing so will increase the safety of The PR Review Club or the 82 | general public. We will not name harassment victims without their affirmative 83 | consent. 84 | 85 | Thank you for your help in keeping our club welcoming, respectful, and friendly 86 | to all participants. 87 | -------------------------------------------------------------------------------- /contrib/new_post.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Create a new post.""" 3 | import argparse 4 | from dataclasses import dataclass 5 | import datetime 6 | import glob 7 | import json 8 | import os 9 | import subprocess 10 | import sys 11 | from urllib.request import Request, urlopen 12 | 13 | MIN_PYTHON = (3, 9) 14 | 15 | # These correspond to the GitHub labels used by Bitcoin Core. 16 | DESIRED_COMPONENTS = [ 17 | 'Block storage', 18 | 'Build system', 19 | 'Consensus', 20 | 'Data corruption', 21 | 'Descriptors', 22 | 'Docs', 23 | 'GUI', 24 | 'Interfaces', 25 | 'Mempool', 26 | 'Mining', 27 | 'P2P', 28 | 'Privacy', 29 | 'PSBT', 30 | 'Refactoring', 31 | 'Resource usage', 32 | 'RPC/REST/ZMQ', 33 | 'Scripts and tools', 34 | 'Settings', 35 | 'Tests', 36 | 'TX fees and policy', 37 | 'Utils/log/libs', 38 | 'UTXO Db and Indexes', 39 | 'Validation', 40 | 'Wallet', 41 | ] 42 | COMPONENTS = list(map(lambda x: x.lower(), DESIRED_COMPONENTS)) 43 | 44 | # Some PRs contain undesired words (here, single characters) immediately after 45 | # the prefix. Add the characters or words here to strip them from the title. 46 | UNDESIRED_PR_TITLE_WORDS = ['-', '_'] 47 | 48 | GITHUB_API_URL = 'https://api.github.com/repos/bitcoin/bitcoin/pulls' 49 | 50 | @dataclass 51 | class PullRequest(): 52 | number: int 53 | title: str 54 | labels: list[str] 55 | user: str 56 | 57 | def git_config_get(option, default=None): 58 | ''' 59 | Get named configuration option from git repository. 60 | ''' 61 | try: 62 | return subprocess.check_output(['git','config','--get',option], encoding='utf-8').rstrip() 63 | except subprocess.CalledProcessError: 64 | return default 65 | 66 | def validate_date(date_in: str) -> str: 67 | """Normalizes data from any recognised iso format into YYYY-MM-DD""" 68 | date = datetime.date.fromisoformat(date_in) 69 | return date.isoformat() 70 | 71 | def clean_title(title: str) -> str: 72 | """Normalizes the title formatting""" 73 | words = title.split() 74 | 75 | # Remove prefixes and unwanted characters from the beginning of the title 76 | for word in words: 77 | if (word in UNDESIRED_PR_TITLE_WORDS 78 | or word.endswith(':') # usually a component prefix 79 | or (word.startswith('[') and word.endswith(']'))): # usually a component prefix 80 | words.pop(0) 81 | else: 82 | # Continue as soon as we've found an allowed word 83 | break 84 | 85 | # Capitalize the first word 86 | words[0] = words[0].capitalize() 87 | 88 | # Return enclosed in double quotes after joining words and removing any double quotes. 89 | title = " ".join(words).replace("\"", "") 90 | return f"\"{title}\"" 91 | 92 | def valid_components(labels: list[str]) -> list[str]: 93 | return [l for l in labels if l in COMPONENTS] 94 | 95 | def invalid_components(labels: list[str]) -> list[str]: 96 | return [l for l in labels if l not in COMPONENTS] 97 | 98 | def get_nonempty_components(labels: list[str]) -> list[str]: 99 | # Parses the GitHub labels, and requires user input if no valid components were found 100 | components = valid_components(labels) 101 | if components: 102 | return components 103 | 104 | print(f"No label assigned to the PR yet; you will need to add one or more (comma-separated) manually from {COMPONENTS}") 105 | while True: 106 | components_input = input().replace("\'\"", '').split(',') 107 | components_input = [c.strip().lower() for c in components_input] 108 | 109 | if (invalid := invalid_components(components_input)): 110 | print(f"Components {invalid} are invalid, please try again") 111 | continue 112 | 113 | return components_input 114 | 115 | def create_post_file(fname: str, pr: PullRequest, date: str, host: str) -> None: 116 | title = clean_title(pr.title) 117 | labels = [l.lower() for l in pr.labels] 118 | components = get_nonempty_components(labels) 119 | 120 | print(f"GitHub PR title: \"{pr.title}\"") 121 | print(f"Parsed PR title: {title}") 122 | print(f"GitHub PR labels: \"{labels}\"") 123 | print(f"Parsed PR labels: \"{components}\"") 124 | 125 | with open(fname, 'w') as f: 126 | f.write('---\n') 127 | f.write('layout: pr\n') 128 | f.write(f"date: {date}\n") 129 | f.write(f"title: {title}\n") 130 | f.write(f"pr: {pr.number}\n") 131 | f.write(f"authors: [{pr.user}]\n") 132 | f.write(f"components: {json.dumps(components)}\n") # Use json.dumps() for double quotes 133 | f.write(f"host: {host}\n") 134 | f.write("status: upcoming\n") 135 | f.write("commit:\n") 136 | f.write("---\n\n") 137 | f.write("_Notes and questions to follow soon!_\n\n") 138 | f.write("\n\n\n") 143 | f.write("\n") 148 | f.write("\n") 151 | f.write("{% endirc %}\n") 152 | 153 | def load_pr_from_gh(n: int) -> PullRequest: 154 | req = Request(f"{GITHUB_API_URL}/{n}") 155 | 156 | ghtoken = git_config_get('user.ghtoken') 157 | 158 | if ghtoken is not None: 159 | req.add_header('Authorization', 'token' + ghtoken) 160 | response = urlopen(req) 161 | data = json.loads(response.read()) 162 | try: 163 | return PullRequest(number=data['number'], 164 | title=data['title'], 165 | labels=[l['name'] for l in data['labels']], 166 | user=data['user']['login']) 167 | except KeyError: 168 | raise KeyError(f"Could not deserialize GitHub response into PullRequest ({data}") 169 | 170 | def main() -> None: 171 | 172 | if sys.version_info < MIN_PYTHON: 173 | print(f"Error: This script requires Python {'.'.join(map(str, MIN_PYTHON))} or higher.", file=sys.stderr) 174 | sys.exit(1) 175 | 176 | parser = argparse.ArgumentParser() 177 | 178 | parser.add_argument("pr", type=int, help="PR number") 179 | parser.add_argument("host", help="Host's github username") 180 | parser.add_argument("date", help="Meeting date in YYYY-DD-MM format", type=validate_date) 181 | 182 | args = parser.parse_args() 183 | 184 | # Check file doesn't already exist 185 | fname = f"_posts/{args.date}-#{args.pr}.md" 186 | if os.path.isfile(fname): 187 | sys.exit(f"file {fname} already exists!") 188 | 189 | # Warn if PR has already been covered 190 | if(previous_meetings := glob.glob(f'_posts/*#{args.pr}.md*')): 191 | print(f"WARNING: PR already covered in {previous_meetings[0]}") 192 | 193 | # Query github api for PR information 194 | try: 195 | pr = load_pr_from_gh(args.pr) 196 | except Exception as e: 197 | sys.exit(f"Github returned error {e}") 198 | 199 | # Create a new post file if none exists, otherwise exit. 200 | create_post_file(fname, pr, args.date, args.host) 201 | 202 | if __name__ == "__main__": 203 | main() 204 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | preview: 3 | build: . 4 | ports: 5 | - "4000:4000" 6 | volumes: 7 | - .:/app 8 | command: make preview 9 | -------------------------------------------------------------------------------- /hosting.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Hosting a Review Club Meeting 4 | --- 5 | 6 | # Hosting a Bitcoin Core Review Club Meeting 7 | 8 | ## How to Choose a PR 9 | 10 | - The purpose of PR Review Club is to help new contributors learn about the 11 | Bitcoin Core codebase and the process of contributing to the project. Select a PR 12 | that is likely to be instructive or interesting. Don't select a PR just because 13 | you want it to be merged soon! You may even select a PR that is already merged. 14 | 15 | - The PR can be complex, but keep in mind that attendees may be at a variety of 16 | different experience levels. Some attendees have only just cloned the Bitcoin 17 | Core repo for the first time, and some have been contributing for months or 18 | years. If you choose a complex PR, try to provide notes that would help a 19 | beginner get up to speed. 20 | 21 | - It's fine to discuss a PR that you opened yourself. After all, you probably 22 | know more about it than anyone else! 23 | 24 | - The appropriate amount of code change to discuss depends on the complexity of 25 | the code. It might be fine to discuss 10-20 lines of code if the change is 26 | very subtle or has complex interactions. If the change is more straightforward, 27 | then it might be fine to discuss 100+ lines of code change. If the PR seems too 28 | large, consider only discussing a subset of the commits. 29 | 30 | - In the past, we have broken up discussion on a PR into multiple meetings, and 31 | run additional meetings during the week to accommodate higher interest on more 32 | complex PRs. If you feel additional time is appropriate, don't hesitate to 33 | propose something! 34 | 35 | ## Before the Meeting 36 | 37 | - Consider contacting the PR author to let them know that you're going to 38 | talk about their PR in the review club. They'll probably be happy that you're 39 | interested in their PR and may be prepared to answer questions and give 40 | you more context. They may even want to join the meeting themselves. 41 | 42 | - Post an announcement for your PR as soon as you can - at least 2 weeks before 43 | the meeting. See the [Making a New Post](#making-a-new-post) section below 44 | for how to make an announcement post. 45 | 46 | - Post notes and questions 1-2 weeks before the meeting. Again, the earlier, the better! 47 | That gives attendees time to review the PR and prepare for the meeting; we typically see much 48 | higher attendance and more lively discussions when attendees have more time to prepare. 49 | 50 | - Prepare a range of questions from basic to advanced. The review club is a way 51 | to help new developers learn. There should be something for everyone. 52 | 53 | - In the notes and meeting, don't just talk about the mechanical code changes. 54 | Other important aspects to consider are: 55 | 56 | - The motivation for the PR. 57 | - The historical context of the PR (why things in the code are the way they 58 | are currently, and what PRs have touched that part of the code base in the past). 59 | - How to review and test the changes. 60 | - Advantages and disadvantages of this approach compared to alternative approaches. 61 | - Potential bugs reviewers might want to look out for. 62 | - Fun C++ things. 63 | 64 | - You may want to think about how you want to split the discussion across two 65 | meetings. Here are some ideas: 66 | 67 | - Conceptual and approach, then implementation. 68 | - The first n commits of the PR, then the last n commits. 69 | 70 | - If you refer to yourself in the notes, use third person narrative 71 | (e.g. your name or GitHub profile) rather than first person ("I"). 72 | 73 | - Don't spoon-feed the attendees. Give them pointers for 74 | where to look in the codebase/GitHub/documentation, and let them do their 75 | own research from there. 76 | 77 | - When linking to code, use stable links that won't break later: 78 | 79 | - for links to code in the master branch, link to a recent commit hash in 80 | the master branch of bitcoin/bitcoin, e.g. 81 | [https://github.com/bitcoin/bitcoin/blob/23d3ae7a/src/addrman.cpp#L44](https://github.com/bitcoin/bitcoin/blob/23d3ae7a/src/addrman.cpp#L44). 82 | You can use a short (8 character) commit id. 83 | 84 | **REASON**: linking directly to master 85 | isn't stable because line numbers/files change over time. 86 | 87 | - for links to code in the PR branch, ask one of the 88 | review club maintainers to add a tag of the current PR branch 89 | to [bitcoin-core-review-club/bitcoin](https://github.com/bitcoin-core-review-club/bitcoin), 90 | and link to that branch or a commit on that branch, e.g. 91 | [https://github.com/bitcoin-core-review-club/bitcoin/commit/a6ca5080#diff-be2905e2f5218ecdbe4e55637dac75f3R1751-R1754](https://github.com/bitcoin-core-review-club/bitcoin/commit/a6ca5080#diff-be2905e2f5218ecdbe4e55637dac75f3R1751-R1754). 92 | You can use a short (8 character) commit id. 93 | 94 | **REASON**: if the PR author modifies 95 | their branch, links to the PR branch will become invalidated. If they 96 | force-push and the commits are detached, those commits will eventually be 97 | removed by GitHub. 98 | 99 | - Thorough preparation will really pay off. Taking the time to deeply 100 | understand the PR will make you feel more relaxed during the meeting. 101 | 102 | - If you find yourself struggling with writing the notes and questions, having 103 | them ready in time, or choosing what areas to focus on, ask the review club 104 | maintainers for help. 105 | 106 | - It can be useful to write out some anticipated answers/links/references 107 | before the meeting so you don't have to type them in the moment. 108 | 109 | #### Making a New Post 110 | 111 | [Fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks) the website repository [located on GitHub](https://github.com/bitcoin-core-review-club/website). 112 | 113 | To make a new post, run the following command from the website directory: 114 | 115 | ```shell 116 | ./contrib/new_post.py 117 | ``` 118 | 119 | This command will create a new markdown file for the post, with metadata and 120 | initial Notes and Questions headers. 121 | 122 | For full help on the command, run 123 | 124 | ```shell 125 | ./contrib/new_post.py -h 126 | ``` 127 | 128 | ## In the Meeting 129 | 130 | - Come with the mindset that the attendees are people who are as smart as you, 131 | but don't have the context that you do in Bitcoin protocol development or 132 | the Bitcoin Core codebase. 133 | 134 | - Start the meeting with `#startmeeting` and "hi" from everyone so you know 135 | who's at their keyboard and paying attention. 136 | 137 | - It's nice to remind people of some of our meeting conventions at the start: 138 | 139 | - Attendees don't have to ask to ask a question (e.g. "I have a question 140 | about x but I don't know if it's on-topic?"). They should just go ahead and 141 | ask. If it's off-topic, the host will say so. 142 | 143 | - The host is there to help moderate, not to lead. Attendees don't need to wait 144 | for the host to ask a specific question — they can just jump in at any point. 145 | 146 | - A quick poll at the start ("Did everyone get a chance to review the PR? How 147 | about a quick y/n from everyone") establishes who will probably be 148 | asking/answering the more interesting questions. 149 | 150 | - Move quickly at the start of the meeting to get to the interesting parts of 151 | the PR as soon as possible — preferably within 2 or 3 minutes. 152 | 153 | - Don't worry if people haven't had a chance to review the PR yet. This 154 | is a voluntary meeting and most people have a lot of other commitments. 155 | 156 | - Very open questions to the group (e.g. "Does everyone know how tx gossip works 157 | in Bitcoin?") don't get a good response because all the attendees are waiting for 158 | someone else to answer. Instead try to make the questions focused on the 159 | PR or change set that is being reviewed (e.g. "how does commit X change the 160 | way bitcoind gossips transactions?"). Try to phrase questions positively 161 | ("please describe how X works") rather than negatively ("Does anyone not know 162 | how X works?"). 163 | 164 | - Once the meeting has reached the challenging questions, 165 | it sometimes feels like there are long stretches of silence and no one 166 | is out there. Be patient. It takes people a bit of time to formulate their 167 | thoughts and type them out. 168 | 169 | - Be encouraging! For many people, asking questions or volunteering an answer 170 | can be intimidating, even in the pseudonymous comfort of IRC. People are 171 | there to learn. Try to create an environment where they feel safe to ask any 172 | questions and where they can attempt to answer without fear. 173 | 174 | - Keep an eye on the clock, and try to wrap up the session with `#endmeeting` at the end of the 175 | hour. Even if you're happy to continue beyond the hour, some of the attendees 176 | might have hard stops. 177 | 178 | - Have fun, and pat yourself on the back for making Bitcoin protocol development 179 | stronger and more decentralized 🚀 180 | 181 | ## After a Meeting 182 | 183 | Let one of the review club maintainers know that the meeting is over. They'll 184 | take care of updating the website. 185 | 186 | #### Adding logs to the review club website 187 | 188 | _This process is done by the review club maintainers_ 189 | 190 | - Uncomment the `## Meeting Log` markup in the meeting post and copy-paste the 191 | meeting log into it. Meeting logs should be copied exactly, but an `## 192 | Erratum` section can be added to correct factual errors. 193 | 194 | - To sanitize logs exported from IRCCloud (ensure UTC timezone is selected 195 | during export), use the following command on the unzipped .txt file: 196 | ```sh 197 | cat \#bitcoin-core-pr-reviews.txt \ 198 | | sed -n '/#startmeeting/h;//!H;$!d;x;//p' \ 199 | | sed '/#endmeeting/q' \ 200 | | sed '/[⇐→]/d' \ 201 | | LC_ALL=C tr -dc '\011\012\015\040-\176\200-\377' \ 202 | | cut -c 13-17,22- \ 203 | > sanitized_log.txt 204 | ``` 205 | 206 | - If there won't be any more meetings, change the `status` of the post from `upcoming` to `past`. 207 | ```diff 208 | -status: upcoming 209 | +status: past 210 | ``` 211 | 212 | - Add the first 7 characters of the PR commit hash at HEAD to the meeting post. 213 | This adds a link to the tagged branch on the review club bitcoin core repo. 214 | ```diff 215 | -commit: 216 | +commit: eebaca7 217 | ``` 218 | 219 | - Push a tag of the branch at the time of the meeting to the [PR Review Club 220 | Bitcoin repo](https://github.com/bitcoin-core-review-club/bitcoin). This is so 221 | if the PR branch changes after the review club meeting, people reading the 222 | notes and log later can see the branch as it was at the time of the meeting: 223 | 224 | - Run these steps from the root of your local bitcoin repo. 225 | 226 | ```shell 227 | cd bitcoin 228 | ``` 229 | 230 | - The first time you do this, you'll need to add the review club bitcoin 231 | repo to your git remotes: 232 | 233 | ```shell 234 | git remote add review-club git@github.com:bitcoin-core-review-club/bitcoin.git 235 | ``` 236 | 237 | - Push a tag to the review-club remote 238 | ```shell 239 | git push review-club :refs/tags/pr # e.g. git push review-club eebaca7:refs/tags/pr17487 240 | ``` 241 | -------------------------------------------------------------------------------- /index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: home 4 | --- 5 | ### A monthly review club for Bitcoin Core PRs 6 | 7 | What is this?  A monthly club for reviewing 8 | Bitcoin Core PRs in {{ site.meeting_location }}. Meetings take place on the **first 9 | {{ site.meeting_day }} of the month, at {{ site.meeting_time }}**. 10 | 11 | What's it for?  To help newer contributors 12 | learn about the Bitcoin Core codebase and review process. The review club is *not* primarily 13 | intended to help open PRs get merged. 14 | 15 | Who should take part?  Anyone who wants to 16 | learn about contributing to Bitcoin Core. All are welcome to come and ask 17 | questions! 18 | 19 | What's the benefit for participants? 20 |  Reviewing and testing PRs is the best way to start contributing to Bitcoin 21 | Core, but it's difficult to know where to start. There are hundreds of open PRs, 22 | many require a lot of contextual knowledge, and contributors and reviewers often 23 | use unfamiliar terminology. The review club will give you the tools and 24 | knowledge you need in order to take part in the [Bitcoin Core review 25 | process](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#peer-review) 26 | on GitHub. 27 | 28 | How do I take part? Just show up on IRC! See 29 | [Attending your first PR Review Club](/your-first-meeting/) for more tips 30 | on how to participate. To stay up to date on newly announced review clubs, 31 | you can follow us on Twitter or via the Atom feed. 32 | 33 | Who runs this?  Upcoming meetings are 34 | scheduled by {{ site.coordinator }}. 35 | The meetings are hosted by a variety of Bitcoin Core contributors. See 36 | some of our [previous hosts](/meetings-hosts/). 37 | 38 | ## Upcoming Meetings 39 | 40 | 41 | {% for post in site.posts reversed %} 42 | {% capture components %} 43 | {%- for comp in post.components -%} 44 | {{comp}}{% unless forloop.last %}, {% endunless %} 45 | {%- endfor -%} 46 | {% endcapture %} 47 | {% if post.status == "upcoming" %} 48 | 49 |
50 |
51 | 52 | 57 | 58 | 59 | {%- endif -%} 60 | {% endfor %} 61 |
»{% if post.pr %}#{{ post.pr }} {% endif %} {{ post.title }} 53 | ({{components}}) 54 | hosted by 55 | {{ post.host }} 56 |
62 | 63 | We're always looking for interesting PRs to discuss in the review club and for 64 | volunteer hosts to lead the discussion: 65 | 66 | - If there's a PR that you'd like to discuss in a future meeting, feel free to suggest it in the IRC channel. 67 | - If you'd like to host a meeting, look at the [information for meeting 68 | hosts](/hosting) and contact {{ site.coordinator_irc }} on IRC. 69 | 70 | ## Recent Meetings 71 | 72 | 73 | {% assign count = 0 %} 74 | {% for post in site.posts %} 75 | {% capture components %} 76 | {%- for comp in post.components -%} 77 | {{comp}}{% unless forloop.last %}, {% endunless %} 78 | {%- endfor -%} 79 | {% endcapture %} 80 | {% if post.status == "past" %} 81 | {% assign count = count | plus: 1 %} 82 | 83 |
84 |
85 | 86 | 89 | 90 | 91 | {%- endif -%} 92 | {% if count == 4 %} 93 | {% break %} 94 | {% endif %} 95 | {% endfor %} 96 |
»{% if post.pr %}#{{ post.pr }}{% endif %} {{ post.title }} 87 | ({{components}}) 88 | hosted by {{ post.host }}
97 | 98 | See all [meetings](/meetings/). 99 | 100 | ## Other Resources for New Contributors 101 | 102 | - Read the [Contributing to Bitcoin Core 103 | Guide](https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md). This 104 | will help you understand the process and some of the terminology we use in 105 | Bitcoin Core. 106 | - Look at the [Good First 107 | Issues](https://github.com/bitcoin/bitcoin/issues?q=is%3aissue+is%3aopen+label%3a%22good+first+issue%22) 108 | and [Up For 109 | Grabs](https://github.com/bitcoin/bitcoin/issues?utf8=%e2%9c%93&q=label%3a%22up+for+grabs%22) 110 | list. 111 | - Read the Bitcoin Core [Developer 112 | Notes](https://github.com/bitcoin/bitcoin/blob/master/doc/developer-notes.md) 113 | and [Productivity 114 | Tips](https://github.com/bitcoin/bitcoin/blob/master/doc/productivity.md). 115 | - Brush up on your C++. There are [many primers and reference manuals 116 | available](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). 117 | - There are some excellent blog posts on how to start contributing to Bitcoin Core: 118 | - [A Gentle Introduction to Bitcoin Core Development (Jimmy Song)](https://medium.com/bitcoin-tech-talk/a-gentle-introduction-to-bitcoin-core-development-fdc95eaee6b8) 119 | - [Contributing to Bitcoin Core - a Personal Account (John Newbery)](https://johnnewbery.com/contributing-to-bitcoin-core-a-personal-account/) 120 | - [Onboarding to Bitcoin Core (Amiti Uttarwar)](https://medium.com/@amitiu/onboarding-to-bitcoin-core-7c1a83b20365) 121 | - [How to Review Pull Requests in Bitcoin Core (Jon Atack)](https://jonatack.github.io/articles/how-to-review-pull-requests-in-bitcoin-core) 122 | -------------------------------------------------------------------------------- /meetings-authors.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Meetings by Author 4 | permalink: /meetings-authors/ 5 | --- 6 | 7 | {% capture raw_authors %} 8 | {%- for meeting in site.posts -%} 9 | {%- if meeting.layout == 'pr' -%} 10 | {%- if meeting.authors == empty -%} 11 | {% include ERROR_92_MISSING_TOPIC_CATEGORY %} 12 | {%- endif -%} 13 | {%- for author in meeting.authors -%} 14 | {{author}}| 15 | {%- endfor -%} 16 | {%- endif -%} 17 | {%- endfor -%} 18 | {% endcapture %} 19 | 20 | {% assign authors = raw_authors | split: "|" | sort_natural | uniq %} 21 | 22 |
23 |

Meetings

24 |

{% include linkers/meetings-pages.md %}

25 | 26 | {% for author in authors %} 27 |
28 |

29 | {{author}} 30 | 31 |

32 | 33 | {% for post in site.posts %} 34 | {% capture components %} 35 | {%- for comp in post.components -%} 36 | {{comp}}{% unless forloop.last %}, {% endunless %} 37 | {%- endfor -%} 38 | {% endcapture %} 39 | {% if post.authors contains author %} 40 | 41 | 44 | 47 | 51 | 52 | {%- endif -%} 53 | {% endfor %} 54 |
45 | » 46 | 48 | {% if post.pr %}#{{ post.pr }} {% endif %}{{ post.title }} 49 | ({{components}}) 50 |
55 |
56 | {% endfor %} 57 |
58 |
59 | -------------------------------------------------------------------------------- /meetings-components.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Meetings by Component 4 | permalink: /meetings-components/ 5 | --- 6 | 7 | {% capture raw_components %} 8 | {%- for meeting in site.posts -%} 9 | {%- if meeting.layout == 'pr' -%} 10 | {%- if meeting.components == empty -%} 11 | {% include ERROR_92_MISSING_TOPIC_CATEGORY %} 12 | {%- endif -%} 13 | {%- for component in meeting.components -%} 14 | {{component}}| 15 | {%- endfor -%} 16 | {%- endif -%} 17 | {%- endfor -%} 18 | {% endcapture %} 19 | 20 | {% assign components = raw_components | split: "|" | sort_natural | uniq %} 21 | 22 |
23 |

Meetings

24 |

{% include linkers/meetings-pages.md %}

25 | 26 | {% for component in components %} 27 |
28 |

{{component}}

29 | 30 | {% for post in site.posts %} 31 | {% if post.components contains component %} 32 |
33 |
34 | 37 | 40 | 47 | 48 | 49 | {%- endif -%} 50 | {% endfor %} 51 |
38 | » 39 | 41 | {% if post.pr %}#{{ post.pr }} {% endif %}{{ post.title }} 42 | 43 | hosted by 44 | {{ post.host }} 45 | 46 |
52 |
53 | {% endfor %} 54 |
55 |
56 | -------------------------------------------------------------------------------- /meetings-hosts.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Meetings by Host 4 | permalink: /meetings-hosts/ 5 | --- 6 | 7 | {% capture raw_hosts %} 8 | {%- for meeting in site.posts -%} 9 | {%- if meeting.layout == 'pr' -%} 10 | {%- if meeting.host == empty -%} 11 | {% include ERROR_92_MISSING_TOPIC_CATEGORY %} 12 | {%- endif -%} 13 | {{meeting.host}}| 14 | {%- endif -%} 15 | {%- endfor -%} 16 | {% endcapture %} 17 | 18 | {% assign hosts = raw_hosts | split: "|" | sort_natural | uniq %} 19 | 20 |
21 |

Meetings

22 |

{% include linkers/meetings-pages.md %}

23 | 24 | {% for host in hosts %} 25 |
26 |

27 | {{host}} 28 | 29 |

30 | 31 | {% for post in site.posts %} 32 | {% capture components %} 33 | {%- for comp in post.components -%} 34 | {{comp}}{% unless forloop.last %}, {% endunless %} 35 | {%- endfor -%} 36 | {% endcapture %} 37 | {% if post.host == host %} 38 | 39 | 42 | 45 | 49 | 50 | {%- endif -%} 51 | {% endfor %} 52 |
43 | » 44 | 46 | {% if post.pr %}#{{ post.pr }} {% endif %}{{ post.title }} 47 | ({{components}}) 48 |
53 |
54 | {% endfor %} 55 |
56 |
57 | -------------------------------------------------------------------------------- /meetings-prs.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Meetings by PR Number 4 | permalink: /meetings-prs/ 5 | --- 6 | 7 | {% assign posts_by_pr_number = site.posts | sort: 'pr' | reverse %} 8 | 9 |
10 |

Meetings

11 |

{% include linkers/meetings-pages.md %}

12 |
13 | 14 | {% for post in posts_by_pr_number %} 15 | 16 | {% if post.pr %} 17 | {% capture components %} 18 | {%- for comp in post.components -%} 19 | {{comp}}{% unless forloop.last %}, {% endunless %} 20 | {%- endfor -%} 21 | {% endcapture %} 22 | 23 | {% capture authors %} 24 | {%- for author in post.authors -%} 25 | {{author}} 26 | 27 | {% unless forloop.last %}, {% endunless %} 28 | {%- endfor -%} 29 | {% endcapture %} 30 | 31 | {% capture this_pr_group %}{{ post.pr | divided_by: 1000 }}{% endcapture %} 32 | {% if this_pr_group != last_pr_group and last_pr_group %} 33 |
34 | 35 | {% endif %} 36 | {% assign last_pr_group = this_pr_group %} 37 | 38 | 39 | 42 | 45 | 46 | {% endif %} 47 | {% endfor %} 48 |
40 | » 41 | 43 | #{{ post.pr }} {{ post.title }} by {{ authors }} ({{components}}) 44 |
49 |
50 |
51 |
52 | -------------------------------------------------------------------------------- /meetings.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Meetings by Date 4 | permalink: /meetings/ 5 | --- 6 | 7 |
8 |

Meetings

9 |

{% include linkers/meetings-pages.md %}

10 | 11 | {% for post in site.posts %} 12 | {% if post.layout != "pr" %} 13 | {% continue %} 14 | {% endif %} 15 | {% capture components %} 16 | {%- for comp in post.components -%} 17 | {{comp}}{% unless forloop.last %}, {% endunless %} 18 | {%- endfor -%} 19 | {% endcapture %} 20 | 21 | {% capture month_year %}{{ post.date | date: "%b %Y" }}{% endcapture %} 22 | 23 | {% if month_year != lastmy %} 24 | {% if lastmy != nil %}
{% endif %} 25 |
26 |

{{ month_year }}

27 | 28 | {% endif %} 29 | 30 | {% assign lastmy = month_year %} 31 | 32 | 33 | 36 | 39 | 47 | 48 | {% endfor %} 49 |
37 | » 38 | 40 | {% if post.pr %}#{{ post.pr }} {% endif %}{{ post.title }} 41 | ({{components}}) 42 | 43 | hosted by 44 | {{ post.host }} 45 | 46 |
50 |
51 |
52 |
53 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # test/test_helper.rb - This test setup helper is required by each test file. 4 | 5 | # Load test runner. 6 | require 'minitest/autorun' 7 | 8 | # Load test reporter. 9 | require 'color_pound_spec_reporter' 10 | Minitest::Reporters.use! [ColorPoundSpecReporter.new] 11 | -------------------------------------------------------------------------------- /test/test_site_content.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require_relative 'test_helper' 4 | require 'curb' 5 | require 'uri' 6 | 7 | class TestSiteContent < Minitest::Test 8 | # Load content from site XML feed, either in production, or locally after 9 | # running `make preview`, and run tests on the content. 10 | # 11 | # To run only this test file: rake TEST=test/test_site_content 12 | 13 | # Uncomment the desired website url: 14 | # SITE = 'https://bitcoincore.reviews' 15 | SITE = 'localhost:4000' 16 | URI_SCHEMES = %w(http https).freeze 17 | HTTP_SUCCESS = 200 18 | HTTP_ERROR = 400 19 | # Regex to select all trailing punctuation except "/". 20 | TRAILING_PUNCTUATION = /[^\/[:^punct:]]+$/ 21 | 22 | def setup 23 | http = Curl.get("#{SITE}/feed.xml") 24 | assert_equal HTTP_SUCCESS, http.response_code 25 | @body = http.body 26 | end 27 | 28 | def test_site_displays_no_empty_nicks 29 | # Check that no empty nicks are displayed, e.g. "<> * luke-jr wonders..." 30 | # To run only this test: 31 | # rake TEST=test/test_site_content TESTOPTS=--name=test_site_displays_no_empty_nicks 32 | # 33 | refute @body.include? "&lt;&gt;" 34 | end 35 | 36 | def test_all_links 37 | # Check the HTTP status of all URLs in the site-wide XML feed. 38 | # To run only this test: 39 | # rake TEST=test/test_site_content TESTOPTS=--name=test_all_links 40 | 41 | # Scrape potential links. 42 | urls = URI.extract(@body, schemes = URI_SCHEMES).uniq 43 | 44 | # Strip any trailing wierdness. 45 | urls.each_with_index do |url, index| 46 | str = url.sub(TRAILING_PUNCTUATION, '') 47 | parts = str.split('&') 48 | str = parts.first if parts.size > 1 49 | urls[index] = str 50 | end 51 | 52 | urls.uniq! 53 | total, errors = urls.count, 0 54 | 55 | # Test the links... 56 | puts "#{total} unique links found, now testing..." 57 | puts ' count | status | url' 58 | 59 | urls.each.with_index(1) do |url, index| 60 | count = "#{' ' * (total.to_s.size - index.to_s.size)}#{index}" 61 | status = Curl.get(url).response_code 62 | 63 | if status == HTTP_SUCCESS 64 | puts "#{count}/#{total} | #{status} | #{url}" 65 | else 66 | puts "#{count}/#{total} | **#{status}** | #{url}" 67 | errors += 1 if status >= HTTP_ERROR 68 | end 69 | end 70 | assert_equal 0, errors 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /your-first-meeting.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Attending your first PR Review Club 4 | --- 5 | 6 | ## Attending your first PR Review Club 7 | 8 | If you’re thinking about attending PR Review Club, welcome! We love new 9 | participants. Below is information to help you get started as a first-timer. 10 | 11 | The club meets on {{ site.meeting_day }}s at {{ site.meeting_time }} in 12 | {{ site.meeting_location }}. Every month, a Bitcoin protocol 13 | developer will host two 60-minute discussion on a Bitcoin Core pull request. [The 14 | code of conduct](https://bitcoincore.reviews/code-of-conduct) details the 15 | behavior we expect from all participants. 16 | 17 | **If you’re new to IRC (Internet Relay Chat),** it has its 18 | own little culture and etiquette. 19 | 20 | The basics: 21 | 22 | - Follow the Golden Rule: treat others as you’d like to be treated. 23 | - Assume the best in others (tone is hard over text). 24 | - Talk in full sentences, but don't stress too much about grammar or 25 | capitalization. 26 | - To respond directly to someone, start your message with their full 27 | nick and a colon, like this: otherperson: thanks for the 28 | help! There's no need to @ them. 29 | - Just observing (sometimes called lurking) is completely fine. 30 | 31 | For more on this subject, check out [The Beginner’s guide to 32 | IRC](https://fedoramagazine.org/beginners-guide-irc/). 33 | 34 | You’ll get the most out of Review Club if you’ve reviewed the PR going into the 35 | meeting, but it’s definitely not mandatory in order to attend. You can always 36 | show up as an observer. If you're worried (don't be!), read the meeting log of a 37 | [past PR Review Club](https://bitcoincore.reviews/meetings/). You'll see it's 38 | very casual. 39 | 40 | If you’d like to more actively participate, you should clone the [Bitcoin 41 | repository](https://github.com/bitcoin/bitcoin). You should also check out and 42 | build the PR branch locally and run all tests. Take time to review the code changes and 43 | read the comments on the PR being covered. 44 | 45 | There are also notes and questions you can review and prepare. Make a note 46 | of any questions you want to ask. 47 | 48 | The meeting will begin with **#startmeeting** and 49 | “hi” from the meeting host. Feel free to respond with “hi” so people know 50 | you’re at your keyboard and participating. The host will poll everyone on 51 | whether they've reviewed the PR (y/n). Don't feel embarrassed to say "n". 52 | 53 | Questions may be asked at any time. If you’d like to ask a question, 54 | there's no need to ask permission. If the question is off-topic, the host will kindly 55 | let you know. The host will end the session with **#endmeeting** 56 | at the end of the hour. Thanking the host at the end of the meeting is always 57 | appreciated! 58 | 59 | Follow the [PR Review Club on Twitter](https://twitter.com/BitcoinCorePRs) for 60 | scheduling announcements. 61 | 62 | **We look forward to having you at the next PR Review Club!** 63 | --------------------------------------------------------------------------------