Synchronize xpub magic numbers from trezor-common

This commit is contained in:
Martin Boehm 2019-01-28 13:34:43 +01:00
parent 42f6821cfa
commit dafe19cf29
28 changed files with 559 additions and 393 deletions

View File

@ -3,9 +3,8 @@
{{- if .Blockbook.BlockChain.AdditionalParams}} {{- if .Blockbook.BlockChain.AdditionalParams}}
{{- range $name, $value := .Blockbook.BlockChain.AdditionalParams}} {{- range $name, $value := .Blockbook.BlockChain.AdditionalParams}}
"{{$name}}": {{jsonToString $value}}, "{{$name}}": {{jsonToString $value}},
{{- end}} {{- end -}}
{{end}} {{end}}
"coin_name": "{{.Coin.Name}}", "coin_name": "{{.Coin.Name}}",
"coin_shortcut": "{{.Coin.Shortcut}}", "coin_shortcut": "{{.Coin.Shortcut}}",
"coin_label": "{{.Coin.Label}}", "coin_label": "{{.Coin.Label}}",
@ -17,6 +16,10 @@
"message_queue_binding": "{{template "IPC.MessageQueueBindingTemplate" .}}", "message_queue_binding": "{{template "IPC.MessageQueueBindingTemplate" .}}",
"subversion": "{{.Blockbook.BlockChain.Subversion}}", "subversion": "{{.Blockbook.BlockChain.Subversion}}",
"address_format": "{{.Blockbook.BlockChain.AddressFormat}}", "address_format": "{{.Blockbook.BlockChain.AddressFormat}}",
{{if .Blockbook.BlockChain.XPubMagic}} "xpub_magic": {{.Blockbook.BlockChain.XPubMagic}},
{{end}}{{if .Blockbook.BlockChain.XPubMagicSegwitP2sh}} "xpub_magic_segwit_p2sh": {{.Blockbook.BlockChain.XPubMagicSegwitP2sh}},
{{end}}{{if .Blockbook.BlockChain.XPubMagicSegwitNative}} "xpub_magic_segwit_native": {{.Blockbook.BlockChain.XPubMagicSegwitNative}},
{{end}}
"mempool_workers": {{.Blockbook.BlockChain.MempoolWorkers}}, "mempool_workers": {{.Blockbook.BlockChain.MempoolWorkers}},
"mempool_sub_workers": {{.Blockbook.BlockChain.MempoolSubWorkers}}, "mempool_sub_workers": {{.Blockbook.BlockChain.MempoolSubWorkers}},
"block_addresses_to_keep": {{.Blockbook.BlockChain.BlockAddressesToKeep}} "block_addresses_to_keep": {{.Blockbook.BlockChain.BlockAddressesToKeep}}

View File

@ -13,18 +13,6 @@ import (
) )
type Config struct { type Config struct {
Meta struct {
BuildDatetime string // generated field
PackageMaintainer string `json:"package_maintainer"`
PackageMaintainerEmail string `json:"package_maintainer_email"`
}
Env struct {
Version string `json:"version"`
BackendInstallPath string `json:"backend_install_path"`
BackendDataPath string `json:"backend_data_path"`
BlockbookInstallPath string `json:"blockbook_install_path"`
BlockbookDataPath string `json:"blockbook_data_path"`
} `json:"env"`
Coin struct { Coin struct {
Name string `json:"name"` Name string `json:"name"`
Shortcut string `json:"shortcut"` Shortcut string `json:"shortcut"`
@ -63,7 +51,7 @@ type Config struct {
Mainnet bool `json:"mainnet"` Mainnet bool `json:"mainnet"`
ServerConfigFile string `json:"server_config_file"` ServerConfigFile string `json:"server_config_file"`
ClientConfigFile string `json:"client_config_file"` ClientConfigFile string `json:"client_config_file"`
AdditionalParams interface{} `json:"additional_params"` AdditionalParams interface{} `json:"additional_params,omitempty"`
} `json:"backend"` } `json:"backend"`
Blockbook struct { Blockbook struct {
PackageName string `json:"package_name"` PackageName string `json:"package_name"`
@ -73,16 +61,31 @@ type Config struct {
ExplorerURL string `json:"explorer_url"` ExplorerURL string `json:"explorer_url"`
AdditionalParams string `json:"additional_params"` AdditionalParams string `json:"additional_params"`
BlockChain struct { BlockChain struct {
Parse bool `json:"parse"` Parse bool `json:"parse,omitempty"`
Subversion string `json:"subversion"` Subversion string `json:"subversion,omitempty"`
AddressFormat string `json:"address_format"` AddressFormat string `json:"address_format,omitempty"`
MempoolWorkers int `json:"mempool_workers"` MempoolWorkers int `json:"mempool_workers"`
MempoolSubWorkers int `json:"mempool_sub_workers"` MempoolSubWorkers int `json:"mempool_sub_workers"`
BlockAddressesToKeep int `json:"block_addresses_to_keep"` BlockAddressesToKeep int `json:"block_addresses_to_keep"`
XPubMagic uint32 `json:"xpub_magic,omitempty"`
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh,omitempty"`
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native,omitempty"`
AdditionalParams map[string]json.RawMessage `json:"additional_params"` AdditionalParams map[string]json.RawMessage `json:"additional_params"`
} `json:"block_chain"` } `json:"block_chain"`
} `json:"blockbook"` } `json:"blockbook"`
IntegrationTests map[string][]string `json:"integration_tests"` Meta struct {
BuildDatetime string `json:"-"` // generated field
PackageMaintainer string `json:"package_maintainer"`
PackageMaintainerEmail string `json:"package_maintainer_email"`
} `json:"meta"`
Env struct {
Version string `json:"version"`
BackendInstallPath string `json:"backend_install_path"`
BackendDataPath string `json:"backend_data_path"`
BlockbookInstallPath string `json:"blockbook_install_path"`
BlockbookDataPath string `json:"blockbook_data_path"`
} `json:"-"`
} }
func jsonToString(msg json.RawMessage) (string, error) { func jsonToString(msg json.RawMessage) (string, error) {
@ -266,7 +269,7 @@ func makeOutputDir(path string) error {
} }
func writeTemplate(path string, info os.FileInfo, templ *template.Template, config *Config) error { func writeTemplate(path string, info os.FileInfo, templ *template.Template, config *Config) error {
f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY, info.Mode()) f, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, info.Mode())
if err != nil { if err != nil {
return err return err
} }

View File

@ -0,0 +1,122 @@
//usr/bin/go run $0 $@ ; exit
package main
import (
build "blockbook/build/tools"
"encoding/json"
"errors"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
)
const (
configsDir = "configs"
trezorCommonDefsURL = "https://raw.githubusercontent.com/trezor/trezor-common/master/defs/bitcoin/"
)
type trezorCommonDef struct {
Name string `json:"coin_name"`
Shortcut string `json:"coin_shortcut"`
Label string `json:"coin_label"`
XPubMagic uint32 `json:"xpub_magic"`
XPubMagicSegwitP2sh uint32 `json:"xpub_magic_segwit_p2sh"`
XPubMagicSegwitNative uint32 `json:"xpub_magic_segwit_native"`
}
func getTrezorCommonDef(coin string) (*trezorCommonDef, error) {
req, err := http.NewRequest("GET", trezorCommonDefsURL+coin+".json", nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, errors.New("Github request status code " + strconv.Itoa(resp.StatusCode))
}
bb, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
var tcd trezorCommonDef
json.Unmarshal(bb, &tcd)
return &tcd, nil
}
func writeConfig(coin string, config *build.Config) error {
path := filepath.Join(configsDir, "coins", coin+".json")
out, err := os.OpenFile(path, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
return err
}
defer out.Close()
buf, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
n, err := out.Write(buf)
if err != nil {
return err
}
if n < len(buf) {
return io.ErrShortWrite
}
return nil
}
func main() {
var coins []string
if len(os.Args) < 2 {
filepath.Walk(filepath.Join(configsDir, "coins"), func(path string, info os.FileInfo, err error) error {
n := strings.TrimSuffix(info.Name(), ".json")
if n != info.Name() {
coins = append(coins, n)
}
return nil
})
} else {
coins = append(coins, os.Args[1])
}
for _, coin := range coins {
config, err := build.LoadConfig(configsDir, coin)
if err == nil {
var tcd *trezorCommonDef
tcd, err = getTrezorCommonDef(coin)
if err == nil {
if tcd.Name != "" {
config.Coin.Name = tcd.Name
}
if tcd.Shortcut != "" {
config.Coin.Shortcut = tcd.Shortcut
}
if tcd.Label != "" {
config.Coin.Label = tcd.Label
}
if tcd.XPubMagic != 0 {
config.Blockbook.BlockChain.XPubMagic = tcd.XPubMagic
}
if tcd.XPubMagicSegwitP2sh != 0 {
config.Blockbook.BlockChain.XPubMagicSegwitP2sh = tcd.XPubMagicSegwitP2sh
}
if tcd.XPubMagicSegwitNative != 0 {
config.Blockbook.BlockChain.XPubMagicSegwitNative = tcd.XPubMagicSegwitNative
}
err = writeConfig(coin, config)
if err == nil {
fmt.Printf("%v updated\n", coin)
}
}
}
if err != nil {
fmt.Printf("%v update error %v\n", coin, err)
}
}
}

View File

@ -54,6 +54,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -54,6 +54,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 70617039,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -40,9 +40,6 @@
"server_config_file": "bitcoin_like.conf", "server_config_file": "bitcoin_like.conf",
"client_config_file": "bitcoin_like_client.conf", "client_config_file": "bitcoin_like_client.conf",
"additional_params": { "additional_params": {
"mempoolexpiry": 72,
"timeout": 768,
"maxconnections": 250,
"addnode": [ "addnode": [
"188.126.0.134", "188.126.0.134",
"45.56.84.44", "45.56.84.44",
@ -232,7 +229,10 @@
"45.27.161.195:33852", "45.27.161.195:33852",
"45.27.161.195:36738", "45.27.161.195:36738",
"45.27.161.195:58628" "45.27.161.195:58628"
] ],
"maxconnections": 250,
"mempoolexpiry": 72,
"timeout": 768
} }
}, },
"blockbook": { "blockbook": {
@ -248,6 +248,8 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,9 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"xpub_magic_segwit_native": 78792518,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,9 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 70617039,
"xpub_magic_segwit_p2sh": 71979618,
"xpub_magic_segwit_native": 73342198,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -56,6 +56,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 50221772,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -56,6 +56,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 70617039,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,8 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -40,10 +40,10 @@
"server_config_file": "bitcoin_like.conf", "server_config_file": "bitcoin_like.conf",
"client_config_file": "bitcoin_like_client.conf", "client_config_file": "bitcoin_like_client.conf",
"additional_params": { "additional_params": {
"whitelist": "127.0.0.1", "discover": 0,
"rpcthreads": 16, "rpcthreads": 16,
"upnp": 0, "upnp": 0,
"discover": 0 "whitelist": "127.0.0.1"
} }
}, },
"blockbook": { "blockbook": {
@ -58,6 +58,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 49990397,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -27,8 +27,7 @@
"verification_type": "gpg-sha256", "verification_type": "gpg-sha256",
"verification_source": "https://www.fujicoin.org/fujicoin/3.0/SHA256SUMS.asc", "verification_source": "https://www.fujicoin.org/fujicoin/3.0/SHA256SUMS.asc",
"extract_command": "tar -C backend -xf", "extract_command": "tar -C backend -xf",
"exclude_files": [ "exclude_files": [],
],
"exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/fujicoind -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/fujicoind -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid",
"logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/*.log", "logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/*.log",
"postinst_script_template": "", "postinst_script_template": "",
@ -38,8 +37,7 @@
"mainnet": true, "mainnet": true,
"server_config_file": "bitcoin_like.conf", "server_config_file": "bitcoin_like.conf",
"client_config_file": "bitcoin_like_client.conf", "client_config_file": "bitcoin_like_client.conf",
"additional_params": { "additional_params": {}
}
}, },
"blockbook": { "blockbook": {
"package_name": "blockbook-fujicoin", "package_name": "blockbook-fujicoin",
@ -53,6 +51,9 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"xpub_magic_segwit_native": 78792518,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,8 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 27106558,
"xpub_magic_segwit_p2sh": 28471030,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -56,6 +56,9 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"xpub_magic_segwit_native": 78792518,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -56,6 +56,9 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 70617039,
"xpub_magic_segwit_p2sh": 71979618,
"xpub_magic_segwit_native": 73342198,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -57,6 +57,7 @@
"mempool_workers": 4, "mempool_workers": 4,
"mempool_sub_workers": 8, "mempool_sub_workers": 8,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,8 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 27108450,
"xpub_magic_segwit_p2sh": 28471030,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 70617039,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,8 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -40,14 +40,14 @@
"server_config_file": "bitcoin_like.conf", "server_config_file": "bitcoin_like.conf",
"client_config_file": "bitcoin_like_client.conf", "client_config_file": "bitcoin_like_client.conf",
"additional_params": { "additional_params": {
"whitelist": "127.0.0.1",
"upnp": 0,
"discover": 0,
"whitelistrelay": 1,
"listenonion": 0,
"addnode": [ "addnode": [
"45.24.110.177:8334" "45.24.110.177:8334"
] ],
"discover": 0,
"listenonion": 0,
"upnp": 0,
"whitelist": "127.0.0.1",
"whitelistrelay": 1
} }
}, },
"blockbook": { "blockbook": {
@ -62,6 +62,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -53,6 +53,8 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 1000, "block_addresses_to_keep": 1000,
"xpub_magic": 76067358,
"xpub_magic_segwit_p2sh": 77429938,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,7 @@
"mempool_workers": 4, "mempool_workers": 4,
"mempool_sub_workers": 8, "mempool_sub_workers": 8,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -55,6 +55,7 @@
"mempool_workers": 4, "mempool_workers": 4,
"mempool_sub_workers": 8, "mempool_sub_workers": 8,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 70617039,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -66,6 +66,7 @@
"mempool_workers": 8, "mempool_workers": 8,
"mempool_sub_workers": 2, "mempool_sub_workers": 2,
"block_addresses_to_keep": 300, "block_addresses_to_keep": 300,
"xpub_magic": 76067358,
"additional_params": {} "additional_params": {}
} }
}, },

View File

@ -237,7 +237,7 @@ func writeMarkdown(output string, slice PortInfoSlice) error {
out := os.Stdout out := os.Stdout
if output != "stdout" { if output != "stdout" {
out, err = os.OpenFile(output, os.O_CREATE|os.O_WRONLY, 0644) out, err = os.OpenFile(output, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil { if err != nil {
return err return err
} }

View File

@ -8,7 +8,7 @@
| Dash | 9033 | 9133 | 8033 | 38333 | | Dash | 9033 | 9133 | 8033 | 38333 |
| Litecoin | 9034 | 9134 | 8034 | 38334 | | Litecoin | 9034 | 9134 | 8034 | 38334 |
| Bitcoin Gold | 9035 | 9135 | 8035 | 38335 | | Bitcoin Gold | 9035 | 9135 | 8035 | 38335 |
| Ethereum | 9036 | 9136 | 8036 | 38336 p2p, 8136 http | | Ethereum | 9036 | 9136 | 8036 | 8136 http, 38336 p2p |
| Ethereum Classic | 9037 | 9137 | 8037 | | | Ethereum Classic | 9037 | 9137 | 8037 | |
| Dogecoin | 9038 | 9138 | 8038 | 38338 | | Dogecoin | 9038 | 9138 | 8038 | 38338 |
| Namecoin | 9039 | 9139 | 8039 | 38339 | | Namecoin | 9039 | 9139 | 8039 | 38339 |
@ -33,5 +33,6 @@
| Vertcoin Testnet | 19040 | 19140 | 18040 | 48340 | | Vertcoin Testnet | 19040 | 19140 | 18040 | 48340 |
| Monacoin Testnet | 19041 | 19141 | 18041 | 48341 | | Monacoin Testnet | 19041 | 19141 | 18041 | 48341 |
| Groestlcoin Testnet | 19045 | 19145 | 18045 | 48345 | | Groestlcoin Testnet | 19045 | 19145 | 18045 | 48345 |
| Koto Testnet | 19051 | 19151 | 18051 | 48351 |
> NOTE: This document is generated from coin definitions in `configs/coins`. > NOTE: This document is generated from coin definitions in `configs/coins`.