mirror of
https://github.com/SeedSigner/seedsigner.git
synced 2026-10-05 23:18:25 +00:00
Merge branch 'dev' into improve_embit_utils_test_coverage_343
This commit is contained in:
@@ -204,14 +204,14 @@ shasum -a 256 --ignore-missing --check seedsigner.0.6.*.sha256
|
||||
|
||||
**On Windows (inside Powershell):** Run this command
|
||||
```
|
||||
CertUtil -hashfile seedsigner.0.6.0.sha256 SHA256 | findstr /v "hash"
|
||||
CertUtil -hashfile seedsigner_os.0.6.0.Insert_Your_Pi_Models_binary_here_For_Example_pi02w.img SHA256
|
||||
```
|
||||
On Windows, you must then manually compare the resulting file hash value to the corresponding hash value shown inside the .SHA256 cleartext file.
|
||||
<BR>
|
||||
|
||||
Wait up to 30 seconds for the command to complete, and it should display:
|
||||
```
|
||||
seedsigner_os.0.6.x[Your_Pi_Model_For_Example:pi02w].img: OK
|
||||
seedsigner_os.0.6.x.[Your_Pi_Model_For_Example:pi02w].img: OK
|
||||
```
|
||||
**If you receive the "OK" message** for your **seedsigner_os.0.6.x.[Your_Pi_Model_For_Example:pi02w].img file**, as shown above, then your verification is fully complete!
|
||||
**All of your downloaded files have now been confirmed as both authentic and unaltered!** You can proceed to create/write your MicroSD card😄😄 !!
|
||||
@@ -241,7 +241,7 @@ Either of the Etcher or Pi Imager software is recommended. Some SeedSigner user
|
||||
The writing and verify steps are very quick from version 0.6.0 upwards, so please pay close attention to your screen.
|
||||
Make sure to set any write-protection physical slider on the MicroSD Card Adapter to UN-locked.
|
||||
You also don’t need to pre-format the MicroSD beforehand. You *dont* need to unzip any .zip file beforehand.
|
||||
Current Etcher and Pi Imager software will perform a verify action (by default) to make sure the card was written successfully! Watching for that verify step to complete successfully can save you a lot of headaches if you later need to troubleshoot issues where your SeedSigner device doesn’t boot up at power on.
|
||||
Current Etcher and Pi Imager software will perform a verify action (by default) to make sure the card was written successfully! Watching for that verify step to complete successfully, can save you a lot of headaches if you later need to troubleshoot issues where your SeedSigner device doesn’t boot up at power on.
|
||||
Writing the MicroSd card is also known as flashing.
|
||||
It will overwrite everything on the MicroSD card.
|
||||
If the one application fails for you, then please try again using our other recommended application.
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 764 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 108 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 315 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 605 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 876 KiB |
+164
-73
@@ -15,11 +15,12 @@ For the following steps you'll need to either connect a keyboard & monitor to th
|
||||
|
||||
### Configure the Pi
|
||||
First things first, verify that you are using the correct version of the Raspberry Pi Lite operating system by typing the command:
|
||||
```
|
||||
```bash
|
||||
cat /etc/os-release
|
||||
```
|
||||
|
||||
The output of this command should match the following text:
|
||||
```
|
||||
```bash
|
||||
PRETTY_NAME="Raspbian GNU/Linux 10 (buster)"
|
||||
NAME="Raspbian GNU/Linux"
|
||||
VERSION_ID="10"
|
||||
@@ -33,7 +34,7 @@ BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
|
||||
```
|
||||
|
||||
Now launch the Raspberry Pi's System Configuration tool using the command:
|
||||
```
|
||||
```bash
|
||||
sudo raspi-config
|
||||
```
|
||||
|
||||
@@ -45,6 +46,8 @@ Set the following:
|
||||
* `Locale`: arrow up and down through the list and select or deselect languages with the spacebar.
|
||||
* Deselect the default language option that is selected
|
||||
* Select `en_US.UTF-8 UTF-8` for US English
|
||||
* Use the `TAB` button to select `Ok` and press `ENTER`
|
||||
* On the next screen select `en_US.UTF-8` for the default locale
|
||||
* You will also need to configure the WiFi settings if you are using the #1 option above to connect to the internet
|
||||
|
||||
When you exit the System Configuration tool, you will be prompted to reboot the system; allow the system to reboot and continue with these instructions.
|
||||
@@ -52,18 +55,55 @@ When you exit the System Configuration tool, you will be prompted to reboot the
|
||||
|
||||
### Change the default password
|
||||
Change the system's default password from the default "raspberry". Run the command:
|
||||
```
|
||||
```bash
|
||||
passwd
|
||||
```
|
||||
You will be prompted to enter the current password ("raspberry") and then to enter a new password twice. In our prepared release image, the password used is `AirG@pped!`.
|
||||
|
||||
|
||||
### Install dependencies
|
||||
Copy this entire box and run it as one command (will take 15-20min to complete):
|
||||
### Install python3.10
|
||||
```bash
|
||||
# install compiler dependencies; takes ~1 minute on a Pi Zero 1.3
|
||||
# * openssl, libssl-dev: ssl support when pip fetches packages
|
||||
# * libsqlite3-dev: required by `coverage`
|
||||
sudo apt update && sudo apt install -y build-essential zlib1g-dev \
|
||||
libncurses5-dev libgdbm-dev libnss3-dev openssl libssl-dev \
|
||||
libreadline-dev libffi-dev wget libsqlite3-dev
|
||||
|
||||
# Grab the python3.10 source
|
||||
wget https://www.python.org/ftp/python/3.10.10/Python-3.10.10.tgz
|
||||
tar -xzvf Python-3.10.10.tgz
|
||||
cd Python-3.10.10
|
||||
|
||||
# Takes ~6 minutes on a Pi Zero 1.3 to check what is available
|
||||
./configure --enable-optimizations
|
||||
|
||||
# compiling takes ~80 minutes(!!) on a Pi Zero 1.3
|
||||
sudo make altinstall
|
||||
|
||||
# cleanup
|
||||
cd ..
|
||||
sudo rm -rf Python-3.10.10*
|
||||
|
||||
# Make python3.10 the default version
|
||||
sudo update-alternatives --install /usr/bin/python python /usr/local/bin/python3.10 1
|
||||
sudo update-alternatives --install /usr/bin/python3 python3 /usr/local/bin/python3.10 1
|
||||
```
|
||||
sudo apt-get update && sudo apt-get install -y wiringpi python3-pip \
|
||||
python3-numpy python-pil libopenjp2-7 git python3-opencv \
|
||||
python3-picamera libatlas-base-dev qrencode
|
||||
|
||||
Manually re-install `python3-apt` to avoid error messages in later steps (though, ironically, you will see the "ModuleNotFoundError: No module named 'apt_pkg'" error message during the `apt remove` step):
|
||||
```bash
|
||||
sudo apt remove --purge python3-apt -y
|
||||
sudo apt autoremove -y
|
||||
sudo apt install python3-apt -y
|
||||
```
|
||||
|
||||
|
||||
### Install dependencies
|
||||
Copy this entire box and run it as one command (will take a while to complete):
|
||||
```bash
|
||||
sudo apt update && sudo apt install -y wiringpi python3-pip \
|
||||
python3-numpy python-pil libjpeg-dev zlib1g-dev libopenjp2-7 \
|
||||
git python3-opencv python3-picamera libatlas-base-dev qrencode
|
||||
```
|
||||
|
||||
### Install `zbar`
|
||||
@@ -72,17 +112,17 @@ sudo apt-get update && sudo apt-get install -y wiringpi python3-pip \
|
||||
SeedSigner requires `zbar` at 0.23.x or higher.
|
||||
|
||||
Download the binary:
|
||||
```
|
||||
```bash
|
||||
curl -L http://raspbian.raspberrypi.org/raspbian/pool/main/z/zbar/libzbar0_0.23.90-1_armhf.deb --output libzbar0_0.23.90-1_armhf.deb
|
||||
```
|
||||
|
||||
And then install it:
|
||||
```
|
||||
```bash
|
||||
sudo apt install ./libzbar0_0.23.90-1_armhf.deb
|
||||
```
|
||||
|
||||
Cleanup:
|
||||
```
|
||||
```bash
|
||||
rm libzbar0_0.23.90-1_armhf.deb
|
||||
```
|
||||
|
||||
@@ -90,7 +130,7 @@ rm libzbar0_0.23.90-1_armhf.deb
|
||||
This library "provides functions for reading digital inputs and setting digital outputs, using SPI and I2C, and for accessing the system timers."
|
||||
|
||||
Run each of the following individual steps:
|
||||
```
|
||||
```bash
|
||||
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.60.tar.gz
|
||||
tar zxvf bcm2835-1.60.tar.gz
|
||||
cd bcm2835-1.60/
|
||||
@@ -102,88 +142,81 @@ sudo rm -rf bcm2835-1.60
|
||||
```
|
||||
|
||||
### Set up `virtualenv`
|
||||
```
|
||||
pip3 install virtualenvwrapper
|
||||
```bash
|
||||
python -m pip install virtualenvwrapper
|
||||
```
|
||||
|
||||
Edit your bash profile with the command `nano ~/.profile` and add the following to the end:
|
||||
```
|
||||
```bash
|
||||
export WORKON_HOME=$HOME/.envs
|
||||
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
|
||||
source /home/pi/.local/bin/virtualenvwrapper.sh
|
||||
```
|
||||
Then `CTRL-X` and `y` to exit and save changes.
|
||||
|
||||
Now create the python virtualenv for SeedSigner with these two commands:
|
||||
```
|
||||
Now create the virtualenv for SeedSigner:
|
||||
```bash
|
||||
source ~/.profile
|
||||
mkvirtualenv --python=python3 seedsigner-env
|
||||
mkvirtualenv seedsigner-env
|
||||
```
|
||||
|
||||
For convenience you can configure your `.profile` to auto-activate the SeedSigner virtualenv when you ssh in. Once again `nano ~/.profile` and add at the end:
|
||||
```
|
||||
```bash
|
||||
workon seedsigner-env
|
||||
```
|
||||
|
||||
Optional: If you're going to be testing new code on the SeedSigner, you'll find yourself often needing to kill the SeedSigner code that automatically runs at startup (we'll be configuring this further down). As an extra convenience you can list the process id so that you can then kill it from the terminal:
|
||||
```
|
||||
ps aux | grep main.py
|
||||
```
|
||||
|
||||
Save your changes with `CTRL-X` and `y`.
|
||||
|
||||
Now when you `ssh` in you'll see something like:
|
||||
```
|
||||
pi 297 65.4 9.7 74096 36736 ? Rsl 09:26 10:29 /home/pi/.envs/seedsigner-env/bin/python main.py
|
||||
pi 857 0.0 0.4 7332 1876 pts/0 S+ 09:42 0:00 grep --color=auto main.py
|
||||
```
|
||||
|
||||
The top line is our SeedSigner code running. To stop it, run:
|
||||
```
|
||||
kill 297
|
||||
```
|
||||
Where `297` is the process id listed in the output above (it'll be different each time).
|
||||
|
||||
|
||||
### Download the SeedSigner code:
|
||||
```
|
||||
```bash
|
||||
git clone https://github.com/SeedSigner/seedsigner
|
||||
cd seedsigner
|
||||
```
|
||||
|
||||
If you want to run a specific branch within the main SeedSigner repo, switch to it with:
|
||||
```
|
||||
git checkout yourtargetbranch
|
||||
```
|
||||
|
||||
And if you want to test a pull request (PR), for example PR #123:
|
||||
```
|
||||
git fetch origin pull/123/head:pr_123
|
||||
git checkout pr_123
|
||||
```
|
||||
|
||||
where `pr_123` is any name you want to give to the new branch in your local repo that will hold the PR.
|
||||
|
||||
|
||||
### Install Python `pip` dependencies:
|
||||
```
|
||||
pip3 install -r requirements.txt
|
||||
```bash
|
||||
# Takes 1hr 45min on a Pi Zero 1.3
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
#### `pyzbar`
|
||||
Note: The `requirements.txt` installs a fork of the python `pyzbar` repo (for now pointing to the fork in Keith's `kdmukai` github account [https://github.com/kdmukai/pyzbar](https://github.com/kdmukai/pyzbar)).
|
||||
Note: The `requirements.txt` installs a fork of the python `pyzbar` repo.
|
||||
|
||||
The fork is required because the main `pyzbar` repo has been abandoned. This [github issue](https://github.com/NaturalHistoryMuseum/pyzbar/issues/124#issuecomment-971967091) discusses the changes needed in order to support reading binary data from `zbar`, which is required for our `CompactSeedQR` format which writes byte data instead of strings. The changes specifically reference the following PRs which have already been merged into Keith's fork:
|
||||
* [PR 76](https://github.com/NaturalHistoryMuseum/pyzbar/pull/76/files): enables scanning to continue even when a null byte (`x\00`) is found.
|
||||
* [PR 82](https://github.com/NaturalHistoryMuseum/pyzbar/pull/82): enable `zbar`'s new binary mode. Note that this PR has a trivial bug that was fixed in Keith's fork.
|
||||
* [PR 82](https://github.com/NaturalHistoryMuseum/pyzbar/pull/82): enable `zbar`'s new binary mode. Note that this PR has a trivial bug that was fixed in our fork.
|
||||
|
||||
|
||||
### Finish configuring the virtualenv
|
||||
Set the SeedSigner `src/` directory as the project directory for the virtualenv (this is where the virtualenv will take you when you activate it):
|
||||
```bash
|
||||
cd src
|
||||
setvirtualenvproject
|
||||
```
|
||||
|
||||
Test it out:
|
||||
```bash
|
||||
# exit the virtualenv
|
||||
deactivate
|
||||
|
||||
# change dirs to somewhere else
|
||||
cd ~
|
||||
|
||||
# activate the virtualenv
|
||||
workon seedsigner-env
|
||||
|
||||
# you should now be back in the SeedSigner src/ directory
|
||||
pwd
|
||||
```
|
||||
|
||||
|
||||
### Configure `systemd` to run SeedSigner at boot:
|
||||
```
|
||||
```bash
|
||||
sudo nano /etc/systemd/system/seedsigner.service
|
||||
```
|
||||
|
||||
Add the following contents to the text file that was created:
|
||||
```
|
||||
```ini
|
||||
[Unit]
|
||||
Description=Seedsigner
|
||||
|
||||
@@ -199,46 +232,98 @@ WantedBy=multi-user.target
|
||||
|
||||
_Note: For local dev you'll want to edit the `Restart=always` line to `Restart=no`. This way when your dev code crashes it won't keep trying to restart itself. Note that the UI "Reset" will no longer work when auto-restarts are disabled._
|
||||
|
||||
_Note: Debugging output is completely wiped via routing the output to `/dev/null 2>&1`. When working in local dev, you're better off disabling the `systemd` SeedSigner service and just directly running the app so you can see all the debugging output live._
|
||||
_Note: Debugging output is completely wiped via routing the output to `/dev/null 2>&1`. When working in local dev, you'll `kill` the `systemd` SeedSigner service and just directly run the code on demand so you can see all the debugging output live._
|
||||
|
||||
Use `CTRL-X` and `y` to exit and save changes.
|
||||
|
||||
Configure the service to start running (this will restart the seedsigner code automatically at startup and if it crashes):
|
||||
```
|
||||
```bash
|
||||
sudo systemctl enable seedsigner.service
|
||||
```
|
||||
|
||||
Now reboot the Raspberry Pi:
|
||||
```
|
||||
```bash
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
After the Raspberry Pi reboots, you should see the SeedSigner splash screen and the SeedSigner menu subsequently appear on the LCD screen (note that it can take up to 60 seconds for the menu to appear).
|
||||
|
||||
|
||||
#### Optional: kill `systemd` SeedSigner process on login
|
||||
If you're going to be testing new code on the device, you'll find yourself often needing to kill the SeedSigner instance that `systemd` automatically runs at startup.
|
||||
|
||||
You can configure your `~/.profile` to find and kill the SeedSigner process when you ssh in.
|
||||
|
||||
`nano ~/.profile` and add at the end:
|
||||
```bash
|
||||
# Find the SeedSigner process and kill it
|
||||
kill $(ps aux | grep '[m]ain.py' | awk '{print $2}')
|
||||
```
|
||||
|
||||
|
||||
### Further OS modifications
|
||||
Disable and remove the system's virtual memory / swap file with the commands:
|
||||
```
|
||||
|
||||
```bash
|
||||
sudo apt remove dphys-swapfile -y
|
||||
sudo apt autoremove -y
|
||||
sudo rm /var/swap
|
||||
```
|
||||
|
||||
## Local testing and development
|
||||
For those who will use the SeedSigner installation for testing/development, it can be helpful to change the system's host name so it doesn't potentially conflict with other Raspberry Pis that may already be present on your network. (For those who don't plan to use the installation for testing or development, you can skip this portion of the process.) To change the host name first edit the "hostname" with the command:
|
||||
## Manually start the SeedSigner code
|
||||
```bash
|
||||
# activate the virtualenv if you haven't already
|
||||
workon seedsigner-env
|
||||
|
||||
# You should now be in the SeedSigner src/ directory. List its contents:
|
||||
ls
|
||||
|
||||
# You should see the main.py file. Run it:
|
||||
python main.py
|
||||
|
||||
# To kill the process, use CTRL-C
|
||||
```
|
||||
|
||||
|
||||
## Local testing and development
|
||||
|
||||
### Run specific branches or PRs
|
||||
The default branch is `dev`. If you want to run a specific release tag or a specific branch:
|
||||
```bash
|
||||
# release tag for v0.6.0:
|
||||
git checkout 0.6.0
|
||||
```
|
||||
|
||||
And if you want to test a pull request (PR), for example PR #123:
|
||||
```bash
|
||||
git fetch origin pull/123/head:pr_123
|
||||
git checkout pr_123
|
||||
```
|
||||
|
||||
where `pr_123` is any name you want to give to the new branch in your local repo that will hold the PR.
|
||||
|
||||
|
||||
### Change the host name
|
||||
For those who will use the SeedSigner installation for testing/development, it can be helpful to change the system's host name so it doesn't potentially conflict with other Raspberry Pis that may already be present on your network. (For those who don't plan to use the installation for testing or development, you can skip this portion of the process.) To change the host name first edit the "hostname" with the command:
|
||||
|
||||
```bash
|
||||
sudo nano /etc/hostname
|
||||
```
|
||||
and change "raspberrypi" to "seedsigner" (or another name). Use `CTRL-X` and `y` to exit and save changes. You'll also need to edit the "hosts" file with the command:
|
||||
```
|
||||
|
||||
and change "raspberrypi" to "seedsigner" (or another name). Use `CTRL-X` and `y` to exit and save changes.
|
||||
|
||||
You'll also need to edit the "hosts" file with the command:
|
||||
```bash
|
||||
sudo nano /etc/hosts
|
||||
```
|
||||
|
||||
and change "raspberrypi" to "seedsigner" (or the other name you previously chose). Use `CTRL-X` and `y` to exit and save changes.
|
||||
|
||||
### Set a static IP
|
||||
Your local machine that `ssh`s into the SeedSigner can sometimes get confused if you're connecting to different SeedSigners that are all identified as `pi@seedsigner.local`. In this case it helps to set a static ip and just `ssh` directly to that instead.
|
||||
|
||||
First find your current `nameserver`:
|
||||
```
|
||||
```bash
|
||||
sudo cat /etc/resolv.conf
|
||||
```
|
||||
|
||||
@@ -260,21 +345,26 @@ static domain_name_servers=192.168.1.254
|
||||
`CTRL-X` and `y` to save changes.
|
||||
|
||||
After your next reboot, access this SeedSigner using its new static ip:
|
||||
```
|
||||
```bash
|
||||
# Use the static ip you set above:
|
||||
ssh pi@192.168.1.200
|
||||
|
||||
# But the hostname will still work, too:
|
||||
ssh pi@seedsigner.local
|
||||
```
|
||||
|
||||
### More convenient `ssh` access:
|
||||
Power SeedSigner devs will find themselves connecting to a lot of different SeedSigners. This can cause headaches with `ssh`'s built-in protections; a different device that uses the same `ssh` credentials is normally a potential spoofing attack. But we're doing this to ourselves on purpose and so we can carve out exceptions.
|
||||
|
||||
On your local machine, run `nano ~/.ssh/config` and add to the end:
|
||||
```
|
||||
```conf
|
||||
host seedsigner.local
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile /dev/null
|
||||
User pi
|
||||
LogLevel QUIET
|
||||
|
||||
# Set this to the static ip you set above:
|
||||
host 192.168.1.200
|
||||
StrictHostKeyChecking no
|
||||
UserKnownHostsFile /dev/null
|
||||
@@ -293,7 +383,7 @@ The second entry does the same for a specific static ip; you'll want this if you
|
||||
You can also configure the SeedSigner so that you don't have to enter the `pi` password when you `ssh` in.
|
||||
|
||||
run `ssh-copy-id` with the same values that you connect via `ssh`:
|
||||
```
|
||||
```bash
|
||||
ssh-copy-id pi@seedsigner.local
|
||||
|
||||
# or if you're connecting over static ip, something like:
|
||||
@@ -307,7 +397,7 @@ _Note: If you don't have any ssh keys on your local machine, you'll need to crea
|
||||
|
||||
## Disable wifi/Bluetooth when using other Raspi boards
|
||||
If you plan to use your installation on a Raspberry Pi that is not a Zero version 1.3, but rather on a Raspberry Pi that has WiFi and Bluetooth capabilities, it is a good idea to disable the following WiFi & Bluetooth, as well as other relevant services (assuming you are not creating this installation for testing/development purposes). Enter the followiing commands to disable WiFi, Bluetooth, & other relevant services:
|
||||
```
|
||||
```bash
|
||||
sudo systemctl disable bluetooth.service
|
||||
sudo systemctl disable wpa_supplicant.service
|
||||
sudo systemctl disable dhcpcd.service
|
||||
@@ -316,12 +406,13 @@ sudo systemctl disable networking.service
|
||||
sudo systemctl disable dphys-swapfile.service
|
||||
sudo ifconfig wlan0 down
|
||||
```
|
||||
|
||||
Please note that if you are using WiFi to connect/interact with your Raspberry Pi, the last command will sever that connection.
|
||||
|
||||
You can now safely power the Raspberry Pi off from the SeedSigner main menu.
|
||||
|
||||
If you do not plan to use your installation for testing/development, it is also a good idea to disable WiFi and Bluetooth by editing the config.txt file found in the installation's "boot" partition. You can add the following text to the end of that file with any simple text editor (Windows: Notepad, Mac: TextEdit, Linux: nano):
|
||||
```
|
||||
```ini
|
||||
dtoverlay=disable-bt
|
||||
dtoverlay=pi3-disable-wifi
|
||||
```
|
||||
|
||||
@@ -70,7 +70,7 @@ It's important to note here that QR codes can encode data in a number of differe
|
||||
|
||||
QR codes are typically used to encode a website url, in which case the "Alphanumeric" format has to be used (the encoded data can consist of upper- and lowercase letters, numbers, and certain allowed symbols).
|
||||
|
||||
If you have a long url like `https://ohnoihavealongurl.com` (29 characters), the chart shows that it would not fit in a 21x21 QR code; its max capacity is 25 alphanumeric chars. But it's within the 47-char capacity of the 29x29 size.
|
||||
If you have a long url like `https://ohnoihavealongurl.com` (29 characters), the chart shows that it would not fit in a 21x21 QR code; its max capacity is 25 alphanumeric chars. But it's within the 47-char capacity of the 25x25 size.
|
||||
|
||||
### Bit efficiency matters
|
||||
Notice that the "Numeric" column has greater capacity. This is because when you have fewer possible characters to encode, it takes less data to specify each one.
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
## The Open Pill Enclosure
|
||||
|
||||
The "Open Pill" was the second officially released SeedSigner enclosure. Given some of the challenges associated with the "Orange Pill", the Open Pill was designed for quick, inexpensive, and simple deployment. No secondary hardware components are required for assembly and the design consists of a single printed part that can be produced with even basic 3D printers. This simpler design was intended to put the focus back on the project's software, which was improving by leaps and bounds when the enclosure was released.
|
||||
|
||||
<img src="/docs/img/Open_Pill_Models.JPG" width="400" height="400">
|
||||
|
||||
### Characterisics:
|
||||
- Supported Camera? Legacy RPi Camera (w/ gold Pi Zero Cable)
|
||||
- Supported HAT? Waveshare 240x240 pixel LCD display + controls
|
||||
- Recommended printing process? FDM
|
||||
- Recommended printing materials? PLA
|
||||
- Secondary Hardware Required? No
|
||||
- Data-enabled USB Port accessible? Yes
|
||||
- Mini-HDMI port accessible? Yes
|
||||
- Removeable Memory Card? Yes
|
||||
- Comfortable controls? No (see note below)
|
||||
|
||||
### Assembly Demonstration:
|
||||
https://www.youtube.com/watch?v=gXPFJygZobE
|
||||
|
||||
|
||||
### Comfortable Controls Optional Upgrade:
|
||||
The bare joystick on an open pill or open pill mini design can be uncomfortable for some thumbs. Twitter user @Vulcan21com developed a DIY solution to add comfort to the exposed joystick using a M2.5 knurled nut standardized under DIN 466, widely available at many hardware stores. The joystick itself has no threading, but it is possible to screw the M2.5 nut onto the joystick with a bit of precision and patience. While screwing it on for the first time it will cut a light thread into the plastic. Be gentle as to not transfer too much torque into the joystick. The result will look like this:
|
||||
|
||||
<img src="/docs/img/Open_Pill_w_Comfort_Joystick.png">
|
||||
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
## The Open Pill Mini Enclosure
|
||||
|
||||
The "Open Pill Mini" is simply a smaller version of the original "Open Pill" that is designed to incorporate a more compact camera specifically designed for the Raspberry Pi Zero -- this enclosure is just about as small as a SeedSigner can conceivably get. It is pictured below, alongside the original Open Pill enclosure.
|
||||
|
||||
<img src="/docs/img/Open_Pill_Mini_Models.JPG" width="400" height="400">
|
||||
|
||||
### Characterisics:
|
||||
- Supported Camera? "ZeroCam" designed specifically for RPi Zero
|
||||
- Supported HAT? Waveshare 240x240 pixel LCD display + controls
|
||||
- Recommended printing process? FDM
|
||||
- Recommended printing materials? PLA
|
||||
- Secondary Hardware Required? No
|
||||
- Data-enabled USB Port accessible? Yes
|
||||
- Mini-HDMI port accessible? Yes
|
||||
- Removeable Memory Card? Yes
|
||||
- Comfortable controls? No (see note below)
|
||||
|
||||
### Assembly Demonstration:
|
||||
(assembly is very similar to the original Open Pill assembly, depicted below)
|
||||
https://www.youtube.com/watch?v=aIIc2DiZYcI
|
||||
|
||||
### Comfortable Controls Optional Upgrade:
|
||||
The bare joystick on an open pill or open pill mini design can be uncomfortable for some thumbs. Twitter user @Vulcan21com developed a DIY solution to add comfort to the exposed joystick using a M2.5 knurled nut standardized under DIN 466, widely available at many hardware stores. The joystick itself has no threading, but it is possible to screw the M2.5 nut onto the joystick with a bit of precision and patience. While screwing it on for the first time it will cut a light thread into the plastic. Be gentle as to not transfer too much torque into the joystick. The result will look like this:
|
||||
|
||||
<img src="/docs/img/Open_Pill_w_Comfort_Joystick.png">
|
||||
(image displayed is Open Pill, not Open Pill Mini)
|
||||
@@ -0,0 +1,19 @@
|
||||
## The Open Pill Mini w/ Coverplate Enclosure
|
||||
|
||||
The "Open Pill Mini w/ Coverplate" was designed as an attempt to incorporate the best of the "Orange Pill" and the "Open Pill" enclosures into a single design. It is fully enclosed for improved aesthetics and protection of electronic components, yet is compact and can be manufactured with a simple FDM printer, also not requiring any additional hardware components. A first for this enclosure was preventing access to the SeedSigner's data-enabled USB port as an additional security assurance for users.
|
||||
|
||||
<img src="/docs/img/Open_Pill_Mini_w_Faceplate.JPG" width="400" height="400">
|
||||
|
||||
### Characterisics:
|
||||
- Supported Camera? "ZeroCam" designed specifically for RPi Zero
|
||||
- Supported HAT? Waveshare 240x240 pixel LCD display + controls
|
||||
- Recommended printing process? FDM for enclosure & controls
|
||||
- Recommended printing materials? PLA for enclosure, TPU for controls
|
||||
- Secondary Hardware Required? No
|
||||
- Data-enabled USB Port accessible? No
|
||||
- Mini-HDMI port accessible? No
|
||||
- Removeable Memory Card? Yes
|
||||
- Comfortable controls? Yes
|
||||
|
||||
### Assembly Demonstration:
|
||||
https://www.youtube.com/watch?v=6-5cDneXoWs
|
||||
@@ -0,0 +1,24 @@
|
||||
## The Orange Pill Enclosure
|
||||
|
||||
The "Orange Pill" was the first SeedSigner enclosure. It's eye-catching design is the enclosure most commonly associated with the SeedSigner project for many. While aesthetically appealing and fun to showcase to others, the thumbstick topper's sub-optimal design, the need for secondary hardware components, and other drawbacks make this enclosure a less desirable choice for every day SeedSigner use.
|
||||
|
||||
<img src="/docs/img/Orange_Pill_Models.JPG" width="400" height="400">
|
||||
|
||||
### Characterisics:
|
||||
- Supported Camera? Legacy RPi Camera (w/ gold Pi Zero Cable)
|
||||
- Supported HAT? Waveshare 240x240 pixel LCD display + controls
|
||||
- Recommended printing process? FDM for enclosure, SLA for controls
|
||||
- Recommended printing materials? PLA for enclosure, resin for controls
|
||||
- Secondary Hardware Required? Yes
|
||||
- Data-enabled USB Port accessible? Yes
|
||||
- Mini-HDMI port accessible? Yes
|
||||
- Removeable Memory Card? Requires partial disassembly
|
||||
- Comfortable controls? Yes (but thumbstick can be clumsy)
|
||||
|
||||
### Secondary Hardware Required:
|
||||
- Four (4): 10mm M2.5 F-F spacers
|
||||
- Four (4): 6mm M2.5 screws
|
||||
- Four (4): 12mm M2.5 screws
|
||||
|
||||
### Assembly Demonstration:
|
||||
https://www.youtube.com/watch?v=aIIc2DiZYcI
|
||||
@@ -0,0 +1,25 @@
|
||||
## The Simple Pill Enclosure
|
||||
|
||||
The "Simple Pill" is a community-contributed design by @blackcoffeebtc. The most significant innovation of this design was the adaptation of a DPAD-stype thumbstick topper for a SeedSigner enclosure, offering a much more comfortable and responsive control experience. The Simple Pill was also the first enclosure to allow for easy access to the device's memory card.
|
||||
|
||||
<img src="/docs/img/Simple_Pill_Models.JPG" width="400" height="400">
|
||||
|
||||
### Characterisics:
|
||||
- Supported Camera? Legacy RPi Camera (w/ gold Pi Zero Cable)
|
||||
- Supported HAT? Waveshare 240x240 pixel LCD display + controls
|
||||
- Recommended printing process? FDM for enclosure, SLA for controls
|
||||
- Recommended printing materials? PLA for enclosure, resin for controls
|
||||
- Secondary Hardware Required? Yes
|
||||
- Data-enabled USB Port accessible? Yes
|
||||
- Mini-HDMI port accessible? Yes
|
||||
- Removeable Memory Card? Yes
|
||||
- Comfortable controls? Yes
|
||||
|
||||
### Secondary Hardware Required:
|
||||
- Four (4): 10mm M2.5 F-F spacers
|
||||
- Four (4): 6mm M2.5 screws
|
||||
- Four (4): 12mm M2.5 screws
|
||||
|
||||
### Assembly Demonstration:
|
||||
(assembly is similar to that of the original Orange Pill)
|
||||
https://www.youtube.com/watch?v=aIIc2DiZYcI
|
||||
@@ -309,7 +309,12 @@ class Controller(Singleton):
|
||||
# So we extract the Exception type and trim off any "foo.bar." namespacing:
|
||||
last_line = traceback.format_exc().splitlines()[-1]
|
||||
exception_type = last_line.split(":")[0].split(".")[-1]
|
||||
exception_msg = last_line.split(":")[1]
|
||||
|
||||
# Extract the error message, if there is one
|
||||
if ":" in last_line:
|
||||
exception_msg = last_line.split(":")[1]
|
||||
else:
|
||||
exception_msg = ""
|
||||
|
||||
# Scan for the last debugging line that includes a line number reference
|
||||
line_info = None
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
from dataclasses import dataclass
|
||||
from lzma import is_check_supported
|
||||
from PIL import Image, ImageDraw, ImageFilter
|
||||
from typing import List
|
||||
import time
|
||||
|
||||
@@ -379,7 +379,8 @@ class SeedMnemonicEntryScreen(BaseTopNavScreen):
|
||||
|
||||
self.keyboard.render_keys()
|
||||
|
||||
elif input in HardwareButtonsConstants.KEYS__LEFT_RIGHT_UP_DOWN:
|
||||
elif input in HardwareButtonsConstants.KEYS__LEFT_RIGHT_UP_DOWN \
|
||||
or input in (Keyboard.ENTER_TOP, Keyboard.ENTER_BOTTOM):
|
||||
if ret_val in self.possible_alphabet:
|
||||
# Live joystick movement; haven't locked this new letter in yet.
|
||||
# Replace the last letter w/the currently selected one. But don't
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import spidev
|
||||
import RPi.GPIO as GPIO
|
||||
import time
|
||||
import numpy as np
|
||||
import array
|
||||
|
||||
|
||||
|
||||
@@ -153,11 +153,10 @@ class ST7789(object):
|
||||
if imwidth != self.width or imheight != self.height:
|
||||
raise ValueError('Image must be same dimensions as display \
|
||||
({0}x{1}).' .format(self.width, self.height))
|
||||
img = np.asarray(Image)
|
||||
pix = np.zeros((self.width,self.height,2), dtype = np.uint8)
|
||||
pix[...,[0]] = np.add(np.bitwise_and(img[...,[0]],0xF8),np.right_shift(img[...,[1]],5))
|
||||
pix[...,[1]] = np.add(np.bitwise_and(np.left_shift(img[...,[1]],3),0xE0),np.right_shift(img[...,[2]],3))
|
||||
pix = pix.flatten().tolist()
|
||||
# convert 24-bit RGB-8:8:8 to gBRG-3:5:5:3; then per-pixel byteswap to 16-bit RGB-5:6:5
|
||||
arr = array.array("H", Image.convert("BGR;16").tobytes())
|
||||
arr.byteswap()
|
||||
pix = arr.tobytes()
|
||||
self.SetWindows ( 0, 0, self.width, self.height)
|
||||
GPIO.output(self._dc,GPIO.HIGH)
|
||||
for i in range(0,len(pix),4096):
|
||||
|
||||
@@ -148,7 +148,7 @@ class PSBTParser():
|
||||
leaf_hashes, derivation = list(out.taproot_bip32_derivations.values())[0]
|
||||
der = derivation.derivation
|
||||
my_pubkey = self.root.derive(der)
|
||||
sc = script.p2tr(my_pubkey)
|
||||
sc = script.p2tr(my_pubkey)
|
||||
|
||||
if sc.data == self.psbt.tx.vout[i].script_pubkey.data:
|
||||
is_change = True
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import json
|
||||
import os
|
||||
import platform
|
||||
|
||||
from typing import Any, List
|
||||
|
||||
@@ -10,7 +11,7 @@ from .singleton import Singleton
|
||||
|
||||
|
||||
class Settings(Singleton):
|
||||
HOSTNAME = os.uname()[1]
|
||||
HOSTNAME = platform.uname()[1]
|
||||
SEEDSIGNER_OS = "seedsigner-os"
|
||||
SETTINGS_FILENAME = "/mnt/microsd/settings.json" if HOSTNAME == SEEDSIGNER_OS else "settings.json"
|
||||
|
||||
@@ -202,4 +203,4 @@ class Settings(Singleton):
|
||||
# set persistent settings to only have disabled as an option, adding additional help text that microSD is removed
|
||||
entry = SettingsDefinition.get_settings_entry(SettingsConstants.SETTING__PERSISTENT_SETTINGS)
|
||||
entry.selection_options = SettingsConstants.OPTIONS__ONLY_DISABLED
|
||||
entry.help_text = "MicroSD card is removed"
|
||||
entry.help_text = "MicroSD card is removed"
|
||||
|
||||
@@ -942,6 +942,16 @@ class SeedBIP85SelectChildIndexView(View):
|
||||
if ret == RET_CODE__BACK_BUTTON:
|
||||
return Destination(BackStackView)
|
||||
|
||||
if not 0 <= int(ret) < 2**31:
|
||||
return Destination(
|
||||
SeedBIP85InvalidChildIndexView,
|
||||
view_args=dict(
|
||||
seed_num=self.seed_num,
|
||||
num_words=self.num_words
|
||||
),
|
||||
skip_current_view=True
|
||||
)
|
||||
|
||||
return Destination(
|
||||
SeedWordsWarningView,
|
||||
view_args=dict(
|
||||
@@ -951,6 +961,32 @@ class SeedBIP85SelectChildIndexView(View):
|
||||
)
|
||||
|
||||
|
||||
class SeedBIP85InvalidChildIndexView(View):
|
||||
def __init__(self, seed_num: int, num_words: int):
|
||||
super().__init__()
|
||||
self.seed_num = seed_num
|
||||
self.num_words = num_words
|
||||
|
||||
|
||||
def run(self):
|
||||
DireWarningScreen(
|
||||
title="BIP-85 Index Error",
|
||||
show_back_button=False,
|
||||
status_headline=f"Invalid Child Index",
|
||||
text=f"BIP-85 Child Index must be between 0 and {2**31-1}.",
|
||||
button_data=["Try Again"]
|
||||
).display()
|
||||
|
||||
return Destination(
|
||||
SeedBIP85SelectChildIndexView,
|
||||
view_args=dict(
|
||||
seed_num=self.seed_num,
|
||||
num_words=self.num_words
|
||||
),
|
||||
skip_current_view=True
|
||||
)
|
||||
|
||||
|
||||
|
||||
"""****************************************************************************
|
||||
Seed Words Backup Test
|
||||
|
||||
@@ -43,6 +43,48 @@ def test_singleton_get_instance_preserves_state(reset_controller):
|
||||
assert controller.unverified_address == "123abc"
|
||||
|
||||
|
||||
def test_handle_exception(reset_controller):
|
||||
""" Handle exceptions that get caught by the controller """
|
||||
|
||||
def process_exception_asserting_valid_error(exception_type, exception_msg=None):
|
||||
"""
|
||||
Exceptions caught by the controller are forwarded to the
|
||||
UnhandledExceptionView with view_args["error"] being a list
|
||||
of three strings, ie: [exception_type, line_info, exception_msg]
|
||||
"""
|
||||
try:
|
||||
if exception_msg:
|
||||
raise exception_type(exception_msg)
|
||||
else:
|
||||
raise exception_type()
|
||||
except Exception as e:
|
||||
error = controller.handle_exception(e).view_args["error"]
|
||||
|
||||
# assert that error structure is valid
|
||||
assert len(error) == 3
|
||||
assert error[0] in str(exception_type)
|
||||
assert type(error[1]) == str
|
||||
if exception_msg:
|
||||
assert exception_msg in error[2]
|
||||
else:
|
||||
assert error[2] == ""
|
||||
|
||||
# Initialize the controller
|
||||
controller = Controller.get_instance()
|
||||
|
||||
exception_tests = [
|
||||
# exceptions with an exception_msg
|
||||
(Exception, "foo"),
|
||||
(KeyError, "key not found"),
|
||||
# exceptions without an exception_msg
|
||||
(Exception, ""),
|
||||
(Exception, None),
|
||||
]
|
||||
|
||||
for exception_type, exception_msg in exception_tests:
|
||||
process_exception_asserting_valid_error(exception_type, exception_msg)
|
||||
|
||||
|
||||
def test_missing_settings_get_defaults(reset_controller):
|
||||
""" Should gracefully handle all missing fields from `settings.json` """
|
||||
|
||||
|
||||
@@ -1,8 +1,47 @@
|
||||
import pytest
|
||||
from mock import MagicMock
|
||||
from seedsigner.models import PSBTParser
|
||||
from seedsigner.models import PSBTParser, Seed
|
||||
from embit import psbt
|
||||
from binascii import a2b_base64
|
||||
from seedsigner.models.settings_definition import SettingsConstants
|
||||
|
||||
def test_sig_count():
|
||||
print("test")
|
||||
|
||||
def test_p2tr_change_detection():
|
||||
""" Should successfully detect change in a p2tr to p2tr psbt spend
|
||||
|
||||
PSBT Tx and Wallet Details
|
||||
- Single Sig Wallet P2TR (Taproot) with no passphrase
|
||||
- Regtest 394aed14 m/86'/1'/0' tpubDCawGrRg7YdHdFb9p4mmD8GBaZjJegL53FPFRrMkGoLcgLATJfksUs2y1Q7dVzixAkgecazsxEsUuyj3LyDw7eVVYHQyojwrc2hfesK4wXW
|
||||
- 1 Inputs
|
||||
- 3,190,493,401 sats
|
||||
- 2 Outputs
|
||||
- 1 Output spend to another wallet (bcrt1p6p00wazu4nnqac29fvky6vhjnnhku5u2g9njss62rvy7e0yuperq86f5ek) p2tr address
|
||||
- 1 Output change
|
||||
- addresss bcrt1prz4g6saush37epdwhvwpu78td3q7yfz3xxz37axlx7udck6wracq3rwq30)
|
||||
- amount 2,871,443,918 sats
|
||||
- Change addresses is index 1/1
|
||||
- Fee 155 sats
|
||||
"""
|
||||
|
||||
psbt_base64 = "cHNidP8BAIkCAAAAAf8upuiIWF1VTgC/Q8ZWRrameRigaXpRcQcBe8ye+TK3AQAAAAAXCgAAAs7BJqsAAAAAIlEgGKqNQ7yF4+yFrrscHnjrbEHiJFExhR903ze43FtOH3BwTgQTAAAAACJRINBe93RcrOYO4UVLLE0y8pzvblOKQWcoQ0obCey8nA5GAAAAAE8BBDWHzwNMUx9OgAAAAJdr+WtwWfVa6IPbpKZ4KgRC0clbm11Gl155IPA27n2FAvQCrFGH6Ac2U0Gcy1IH5f5ltgUBDz2+fe8iqL6JzZdgEDlK7RRWAACAAQAAgAAAAIAAAQB9AgAAAAGAKOOUFIzw9pbRDaZ7F0DYhLImrdMn//OSm++ff5VNdAAAAAAAAQAAAAKsjLwAAAAAABYAFKEcuxvXmB3rWHSqSviP5mrKMZoL2RArvgAAAAAiUSBGU0Lg5fx/ECsB1Z4ZUqXQFSLFnlmpm0rm5R2l599h2AAAAAABASvZECu+AAAAACJRIEZTQuDl/H8QKwHVnhlSpdAVIsWeWambSublHaXn32HYAQMEAAAAACEWF7hZVn7pIDR429kAn/WDeQiWjZey1iGHztsL1H83QLMZADlK7RRWAACAAQAAgAAAAIABAAAAAAAAAAEXIBe4WVZ+6SA0eNvZAJ/1g3kIlo2XstYhh87bC9R/N0CzACEHbJdqWyMxF2eOPr6YRXUJmry04HUbgKyeM2IZeG+NI9AZADlK7RRWAACAAQAAgAAAAIABAAAAAQAAAAEFIGyXalsjMRdnjj6+mEV1CZq8tOB1G4CsnjNiGXhvjSPQAAA="
|
||||
|
||||
raw = a2b_base64(psbt_base64)
|
||||
tx = psbt.PSBT.parse(raw)
|
||||
|
||||
mnemonic = "goddess rough corn exclude cream trial fee trumpet million prevent gaze power".split()
|
||||
pw = ""
|
||||
seed = Seed(mnemonic, passphrase=pw)
|
||||
|
||||
pp = PSBTParser(p=tx, seed=seed, network=SettingsConstants.REGTEST)
|
||||
|
||||
assert pp.change_data == [
|
||||
{
|
||||
'output_index': 0,
|
||||
'address': 'bcrt1prz4g6saush37epdwhvwpu78td3q7yfz3xxz37axlx7udck6wracq3rwq30',
|
||||
'amount': 2871443918,
|
||||
'fingerprint': ['394aed14'],
|
||||
'derivation_path': ['m/86h/1h/0h/1/1']}
|
||||
]
|
||||
assert pp.spend_amount == 319049328
|
||||
assert pp.change_amount == 2871443918
|
||||
assert pp.destination_addresses == ['bcrt1p6p00wazu4nnqac29fvky6vhjnnhku5u2g9njss62rvy7e0yuperq86f5ek']
|
||||
assert pp.destination_amounts == [319049328]
|
||||
Reference in New Issue
Block a user