├── .gitignore ├── LICENSE ├── README.md ├── changelog.txt ├── client ├── .gitignore ├── common │ ├── bwidth.go │ ├── common.go │ ├── config.go │ └── mining.go ├── init.go ├── main.go ├── miners.json ├── network │ ├── addr.go │ ├── cblk.go │ ├── core.go │ ├── data.go │ ├── hdrs.go │ ├── invs.go │ ├── ping.go │ ├── tick.go │ ├── trxs.go │ ├── vars.go │ └── ver.go ├── peersdb │ ├── peerdb.go │ └── peerdb_test.go ├── rpcapi │ ├── address.go │ ├── block.go │ ├── mining.go │ └── rpcapi.go ├── speedups │ ├── sipadll.go │ └── sipasec.go ├── ssl_cert │ └── README.md ├── start.bat ├── start.sh ├── txpool │ ├── check.go │ ├── disk.go │ ├── mining.go │ ├── network.go │ ├── pkgs.go │ ├── rjected.go │ ├── sort.go │ ├── system.go │ └── tosend.go ├── usif │ ├── fees.go │ ├── textui │ │ ├── beta.go │ │ ├── commands.go │ │ ├── mining.go │ │ ├── network.go │ │ ├── peers.go │ │ ├── transactions.go │ │ └── wallet.go │ ├── usif.go │ └── webui │ │ ├── blocks.go │ │ ├── config.go │ │ ├── counts.go │ │ ├── home.go │ │ ├── mining.go │ │ ├── network.go │ │ ├── sendtx.go │ │ ├── txs.go │ │ ├── wallets.go │ │ └── webui.go ├── wallet │ ├── db.go │ ├── disk.go │ └── onoff.go └── www │ ├── blocks.html │ ├── counts.html │ ├── help.html │ ├── home.html │ ├── miners.html │ ├── net.html │ ├── send.html │ ├── static │ ├── back_online.mp3 │ ├── bech32.js │ ├── chainsync.png │ ├── copy.png │ ├── crypto.js │ ├── dark.png │ ├── del-black.png │ ├── del-white.png │ ├── empty.png │ ├── export-black.png │ ├── export-white.png │ ├── favicon.ico │ ├── feeschart.js │ ├── free-black.png │ ├── free-white.png │ ├── gocoin.js │ ├── gocoin_dark.css │ ├── gocoin_light.css │ ├── import-black.png │ ├── import-white.png │ ├── in-black.png │ ├── in-white.png │ ├── info-black.png │ ├── info-white.png │ ├── jquery.flot.crosshair.js │ ├── jquery.flot.min.js │ ├── jquery.flot.time.min.js │ ├── jquery.min.js │ ├── light.png │ ├── loading.gif │ ├── message.png │ ├── music-black.png │ ├── music-white.png │ ├── new_block.mp3 │ ├── nosort-black.png │ ├── nosort-white.png │ ├── out-black.png │ ├── out-white.png │ ├── pkgsort-off-black.png │ ├── pkgsort-off-white.png │ ├── pkgsort-on-black.png │ ├── pkgsort-on-white.png │ ├── qrcode-black.png │ ├── qrcode-white.png │ ├── qrcode.min.js │ ├── refresh-black.png │ ├── refresh-white.png │ ├── request-black.png │ ├── request-white.png │ ├── saving.png │ ├── send.png │ ├── send_once.png │ ├── server-black.png │ ├── server-white.png │ ├── sort-black.png │ ├── sort-white.png │ ├── stats.png │ ├── switch-off.png │ ├── switch-on.png │ ├── theme-switch-black.png │ ├── theme-switch-white.png │ ├── warning-black.png │ └── warning-white.png │ ├── templ │ ├── error.html │ ├── page_head.html │ ├── page_tail.html │ ├── restarting.html │ ├── shutdown.html │ ├── txs_load.html │ └── wallet_off.html │ ├── txs.html │ └── wallet.html ├── go.mod ├── lib ├── btc │ ├── addr.go │ ├── addr_test.go │ ├── block.go │ ├── block_test.go │ ├── const.go │ ├── ecdsa.go │ ├── ecdsa_test.go │ ├── funcs.go │ ├── funcs_test.go │ ├── hash.go │ ├── hash_test.go │ ├── key.go │ ├── key_test.go │ ├── multisig.go │ ├── multisig_test.go │ ├── netaddr.go │ ├── opcodes.go │ ├── script.go │ ├── taproot.go │ ├── target.go │ ├── target_test.go │ ├── tx.go │ ├── tx_sys.go │ ├── uint256.go │ ├── unspent.go │ ├── wallet.go │ ├── wallet_test.go │ ├── wallethd.go │ └── wallethd_test.go ├── chain │ ├── block_check.go │ ├── blockdb.go │ ├── chain.go │ ├── chain_accept.go │ ├── chain_diff.go │ ├── chain_load.go │ ├── chain_tree.go │ ├── const.go │ └── dbg.go ├── others │ ├── bech32 │ │ ├── bech32.go │ │ ├── bech32_test.go │ │ ├── segwit.go │ │ └── segwit_test.go │ ├── bip39 │ │ ├── LICENSE │ │ ├── README.md │ │ ├── bip39.go │ │ ├── bip39_test.go │ │ └── wordlist.go │ ├── blockdb │ │ ├── README.md │ │ └── blockdb.go │ ├── cgo │ │ ├── README.md │ │ ├── ec_bench │ │ │ ├── gonative.go │ │ │ ├── sipadll.go │ │ │ └── sipasec.go │ │ └── sipasec │ │ │ ├── .gitignore │ │ │ ├── README.md │ │ │ ├── sipasec.go │ │ │ ├── sipasec_test.go │ │ │ ├── sipasec_unix.go │ │ │ └── sipasec_windows.go │ ├── ltc │ │ └── ltc.go │ ├── memory │ │ ├── AUTHORS │ │ ├── CONTRIBUTORS │ │ ├── LICENSE │ │ ├── LICENSE-GO │ │ ├── LICENSE-MMAP-GO │ │ ├── README.md │ │ ├── counters.go │ │ ├── memory.go │ │ ├── memory32.go │ │ ├── memory64.go │ │ ├── mmap_darwin.go │ │ ├── mmap_freebsd_32.go │ │ ├── mmap_freebsd_64.go │ │ ├── mmap_linux_32.go │ │ ├── mmap_linux_64.go │ │ ├── mmap_linux_s390x.go │ │ ├── mmap_netbsd_32.go │ │ ├── mmap_netbsd_64.go │ │ ├── mmap_openbsd.go │ │ ├── mmap_unix.go │ │ ├── mmap_windows.go │ │ └── trace.go │ ├── prof │ │ └── profiler.go │ ├── qdb │ │ ├── README.md │ │ ├── db.go │ │ ├── db_disk.go │ │ ├── db_test.go │ │ ├── index.go │ │ ├── index_disk.go │ │ ├── membind.go │ │ ├── os_membinds │ │ │ ├── README.md │ │ │ ├── membind_linux.go │ │ │ └── membind_windows.go │ │ └── stats.go │ ├── rawtxlib │ │ └── rawtxtool.go │ ├── ripemd160 │ │ ├── LICENSE │ │ ├── ripemd160.go │ │ ├── ripemd160_test.go │ │ └── ripemd160block.go │ ├── scrypt │ │ ├── LICENSE │ │ ├── README.md │ │ ├── pbkdf2 │ │ │ ├── pbkdf2.go │ │ │ └── pbkdf2_test.go │ │ ├── scrypt.go │ │ └── scrypt_test.go │ ├── siphash │ │ ├── .travis.yml │ │ ├── README.md │ │ ├── blocks.go │ │ ├── blocks_amd64.s │ │ ├── blocks_arm.s │ │ ├── hash.go │ │ ├── hash128.go │ │ ├── hash128_amd64.s │ │ ├── hash128_arm.s │ │ ├── hash_amd64.s │ │ ├── hash_arm.s │ │ ├── hash_asm.go │ │ ├── siphash.go │ │ └── siphash_test.go │ ├── snappy │ │ ├── AUTHORS │ │ ├── CONTRIBUTORS │ │ ├── LICENSE │ │ ├── README │ │ ├── decode.go │ │ ├── decode_amd64.go │ │ ├── decode_amd64.s │ │ ├── decode_other.go │ │ ├── encode.go │ │ ├── encode_amd64.go │ │ ├── encode_amd64.s │ │ ├── encode_other.go │ │ └── snappy.go │ ├── sys │ │ ├── atomic.go │ │ ├── dblock_unix.go │ │ ├── dblock_windows.go │ │ ├── dutex.go │ │ ├── hidepass_unix.go │ │ ├── hidepass_windows.go │ │ ├── ipnet.go │ │ ├── mutexes.go │ │ └── stuff.go │ └── utils │ │ ├── fetchbl.go │ │ ├── fetchtx.go │ │ ├── unspent.go │ │ └── verbose.go ├── script │ ├── checker.go │ ├── dbg.go │ ├── misc.go │ ├── script.go │ ├── script_test.go │ ├── stack.go │ ├── taproot_test.go │ ├── tx_test.go │ └── witness.go ├── secp256k1 │ ├── .gitignore │ ├── COPYING │ ├── README.md │ ├── ec.go │ ├── ec_test.go │ ├── field.go │ ├── field_10x26.go │ ├── field_5x52.go │ ├── field_test.go │ ├── multi_test.go │ ├── num.go │ ├── schnorr.go │ ├── schnorr_test.go │ ├── secp256k1.go │ ├── sig.go │ ├── sig_test.go │ ├── xy.go │ ├── xyz.go │ ├── xyz_test.go │ ├── z_consts_10x26.go │ ├── z_consts_5x52.go │ └── z_init.go ├── test │ ├── README.md │ ├── base58_encode_decode.json │ ├── bip340_test_vectors.csv │ ├── bip341_script_tests.json │ ├── script_tests.json │ ├── sighash.json │ ├── tx_invalid.json │ └── tx_valid.json └── utxo │ ├── unspent.go │ ├── unspent_db.go │ ├── unspent_rec.go │ ├── unspent_recc.go │ ├── unspent_recu.go │ └── unspent_test.go ├── todo.txt ├── tools ├── balio │ └── balio.go ├── base58 │ └── base58.go ├── bdb │ ├── bdb.go │ └── defrag.go ├── bip39wal │ └── bip39wal.go ├── blockinfo │ └── blockinfo.go ├── bootdat_qt │ └── bootdat_qt.go ├── btcversig │ └── btcversig.go ├── fetchblock │ └── fetchblock.go ├── fetchtx │ └── fetchtx.go ├── goc │ └── goc.go ├── hdwal │ └── hdwal.go ├── importblocks │ └── importblocks.go ├── mkmulti │ └── mkmulti.go ├── peers │ └── peers.go ├── sipa_dll │ ├── secp256k1.dll │ ├── sipadll.go │ └── sipadll_test.go ├── tap2old │ └── tap2old.go ├── trumpic │ ├── .gitignore │ ├── block_879613_fees.go │ ├── blocks │ │ └── readme.txt │ ├── fees.zip │ ├── getfees │ │ └── getfees.go │ ├── trumpic.go │ └── working_blocks.txt ├── txaddsig │ └── txaddsig.go ├── txmod │ └── txmod.go ├── txoutset │ └── txoutset.go ├── type2determ │ └── type2determ.go ├── type2next │ └── type2next.go ├── unspent4_to_UTXO │ └── unspent4_to_UTXO.go ├── utxo │ ├── benchmark.go │ ├── compress.go │ ├── fileinfo.go │ └── utxo.go ├── verify_script │ └── verify_script.go └── verify_tx │ └── verify_tx.go ├── version.go ├── wallet ├── .gitignore ├── config.go ├── encrypt.go ├── main.go ├── multisig.go ├── send.go ├── signmsg.go ├── signtx.go ├── stuff.go ├── unspent.go ├── wallet.cfg ├── wallet.go └── wallet_test.go └── website ├── .htaccess ├── 2503-fi-cod_effect.png ├── 2503-fi-twaek_effect.png ├── README.md ├── d3_quick.png ├── d3_turbo.png ├── dd_quick.png ├── de_gocoin_vs_core.png ├── dw32_quick.png ├── favicon.ico ├── fin_quick.png ├── fin_turbo.png ├── gocoin_index.html ├── gocoin_installation.html ├── gocoin_issues.html ├── gocoin_links.html ├── gocoin_manual.html ├── gocoin_manual_client.html ├── gocoin_manual_config.html ├── gocoin_manual_multisig.html ├── gocoin_manual_spending.html ├── gocoin_manual_wallet.html ├── gocoin_performance.html ├── gocoin_tweaks.html ├── index.html ├── logo.png ├── menu.html ├── page.php ├── quick_sync_gocoin_vs_core.png ├── quick_sync_gocoin_vs_core_mar25.png ├── rep_quick.png └── style.css /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | *.bin 3 | *.dat 4 | *.a 5 | client/sipadll.go 6 | client/sipasec.go 7 | client/openssl.go 8 | .DS_Store 9 | .vscode 10 | -------------------------------------------------------------------------------- /client/.gitignore: -------------------------------------------------------------------------------- 1 | client 2 | *.conf 3 | ssl_cert/*.crt 4 | ssl_cert/*.key 5 | -------------------------------------------------------------------------------- /client/common/mining.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "io/ioutil" 7 | 8 | "github.com/piotrnar/gocoin/lib/btc" 9 | ) 10 | 11 | type oneMinerId struct { 12 | Name string 13 | Tag []byte 14 | } 15 | 16 | var MinerIds []oneMinerId 17 | 18 | // return miner ID of the given coinbase transaction 19 | func TxMiner(cbtx *btc.Tx) (string, int) { 20 | txdat := cbtx.Serialize() 21 | for i, m := range MinerIds { 22 | if bytes.Equal(m.Tag, []byte("_p2pool_")) { // P2Pool 23 | if len(cbtx.TxOut) > 10 && 24 | bytes.Equal(cbtx.TxOut[len(cbtx.TxOut)-1].Pk_script[:2], []byte{0x6A, 0x28}) { 25 | return m.Name, i 26 | } 27 | } else if bytes.Equal(m.Tag, []byte("_RSK_")) { // RSK Pool 28 | if len(cbtx.TxOut) > 1 { 29 | txo := cbtx.TxOut[len(cbtx.TxOut)-1] 30 | if len(txo.Pk_script) >= 10 && txo.Pk_script[0] == 0x6A && string(txo.Pk_script[2:10]) == "RSKBLOCK" { 31 | return m.Name, i 32 | } 33 | } 34 | } else if bytes.Contains(txdat, m.Tag) { 35 | return m.Name, i 36 | } 37 | } 38 | 39 | for _, txo := range cbtx.TxOut { 40 | adr := btc.NewAddrFromPkScript(txo.Pk_script, Testnet) 41 | if adr != nil { 42 | return adr.String(), -1 43 | } 44 | } 45 | 46 | return "", -1 47 | } 48 | 49 | func ReloadMiners() { 50 | d, _ := ioutil.ReadFile("miners.json") 51 | if d != nil { 52 | var MinerIdFile [][3]string 53 | e := json.Unmarshal(d, &MinerIdFile) 54 | if e != nil { 55 | println("miners.json", e.Error()) 56 | return 57 | } 58 | MinerIds = nil 59 | for _, r := range MinerIdFile { 60 | var rec oneMinerId 61 | rec.Name = r[0] 62 | if r[1] != "" { 63 | rec.Tag = []byte(r[1]) 64 | } else { 65 | if a, _ := btc.NewAddrFromString(r[2]); a != nil { 66 | rec.Tag = a.OutScript() 67 | } else { 68 | println("Error in miners.json for", r[0]) 69 | continue 70 | } 71 | } 72 | MinerIds = append(MinerIds, rec) 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /client/miners.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["AntPool", "AntPool", ""], 3 | ["BTC.TOP", "BTC.TOP/", ""], 4 | ["BTC.COM", "BTC.COM/", ""], 5 | ["BTC.COM", "BTC.com/", ""], 6 | ["BTC.COM", "btc.com/", ""], 7 | ["BTC.COM", "btccom", ""], 8 | ["ViaBTC", "/ViaBTC/", ""], 9 | ["BTCC", "/BTCC/", ""], 10 | ["F2Pool", "/F2Pool/", "1KFHE7w8BhaENAswwryaoccDb6qcT6DbYY"], 11 | ["F2Pool", "/f2pool", "1K6KoYC69NnafWJ7YgtrpwJxBLiijWqwa6"], 12 | ["Slush", "/slush/", ""], 13 | ["Bixin", "/Bixin/", ""], 14 | ["Bixin", "", "1KsFhYKLs8qb1GHqrPxHoywNQpet2CtP9t"], 15 | ["Bitfury", "/Bitfury/", ""], 16 | ["BitClub", "/BitClub Network/", ""], 17 | ["BW.COM", "/BW Pool/", ""], 18 | ["1Hash", "Mined by 1hash.com", ""], 19 | ["GBMiners", "/mined by gbminers/", ""], 20 | ["Bitcoin.com", "/pool.bitcoin.com", ""], 21 | ["BTPOOL", "/BTPOOL/", ""], 22 | ["Bitcoin-Russia", "/Bitcoin-Russia.ru/", ""], 23 | ["KanoPool", "KanoPool", ""], 24 | ["Bitcoin-India", "/Bitcoin-India/", ""], 25 | ["ConnectBTC", "/ConnectBTC - Home for Miners/", ""], 26 | ["BATPOOL", "/BATPOOL/", ""], 27 | ["58coin", "/58coin.com/", ""], 28 | ["DPOOL", "/DPOOL.TOP/", ""], 29 | ["canoepool", "/canoepool/", ""], 30 | ["Helix", "/Helix/", ""], 31 | ["BWPool", "BWPool", ""], 32 | ["SecretSuperstar", "/SecretSuperstar/", ""], 33 | ["Huobi", "/Huobi/", ""], 34 | ["Huobi", "/HuoBi/", ""], 35 | ["Huobi", "", "18Zcyxqna6h7Z7bRjhKvGpr8HSfieQWXqj"], 36 | ["tigerpool.net", "tigerpool.net", ""], 37 | ["Rawpool.com", "/Rawpool.com/", ""], 38 | ["poolin", "poolin.com", ""], 39 | ["bytepool.com", "/bytepool.com/", ""], 40 | ["www.okpool.top", "/www.okpool.top/", ""], 41 | ["Bitdeer", "/Bitdeer", ""], 42 | ["1THash&58COIN", "/1THash&58COIN/", ""], 43 | ["NovaBlock", "/NovaBlock/", ""], 44 | ["SpiderPool.com", "/SpiderPool.com/", ""], 45 | ["OKEX", "/www.okex.com/", ""], 46 | ["Lubian", "/lubian.com/", ""], 47 | ["Binance", "binance", ""], 48 | ["Binance", "/Binance/", ""], 49 | ["SpiderPool", "SpiderPool", ""], 50 | ["OKKONG", "/hash.okkong.com/", ""], 51 | ["Sigmapool", "Sigmapool.com/", ""], 52 | ["MiningCity", "/MiningCity/", ""], 53 | ["1THash", "/1THash/", ""], 54 | ["bitdeer", "/bitdeer/", ""], 55 | ["Foundry", "/Foundry", ""], 56 | ["BTCPool", "BTCPool", ""], 57 | ["BTCPool", "BTCpool", ""], 58 | ["BTCPool", "btcpool", ""], 59 | ["BTCPool", "BTC-POOL", ""], 60 | ["SBICrypto", "/SBICrypto", ""], 61 | ["Mara Pool", "MARA ", ""], 62 | ["one_more_mcd", "/one_more_mcd/", ""], 63 | ["Luxor", "Powered by Luxor", ""], 64 | ["bitdeer", "bitdeer/", ""], 65 | ["Terra Pool", "terrapool.io", ""], 66 | ["OKKONG", "okkong.com", ""], 67 | ["Blockfills", "/BlockfillsPool/", ""], 68 | ["pegapool", "/pegapool/", ""], 69 | ["NiceHash", "/NiceHash/", ""], 70 | ["Titan.io", "_Titan.io_", ""], 71 | ["mmpool", "/mmpool/", ""], 72 | ["Lucky pool", "Lucky pool", ""], 73 | ["WhitePool", "WhitePool", ""], 74 | ["OCEAN", "OCEAN.XYZ", ""], 75 | ["ultimus", "/ultimus/", ""], 76 | ["RSK Merged", "_RSK_", ""], 77 | ["P2Pool", "_p2pool_", ""] 78 | ] 79 | -------------------------------------------------------------------------------- /client/peersdb/peerdb_test.go: -------------------------------------------------------------------------------- 1 | package peersdb 2 | 3 | import ( 4 | "os" 5 | "testing" 6 | 7 | "github.com/piotrnar/gocoin/client/common" 8 | "github.com/piotrnar/gocoin/lib/others/qdb" 9 | ) 10 | 11 | func test_one_addr(t *testing.T, host string, ip [4]byte, port uint16) { 12 | var p *PeerAddr 13 | var e error 14 | p, e = NewAddrFromString(host, false) 15 | 16 | if e != nil { 17 | t.Fatal(e.Error(), host, port) 18 | } 19 | if p.Ip4 != ip { 20 | t.Error("Bad IP4 returned", host, port) 21 | } 22 | if p.Services != Services { 23 | t.Error("Bad Services returned", host, port) 24 | } 25 | if p.Port != port { 26 | t.Error("Bad port returned", host, port) 27 | } 28 | 29 | p, e = NewAddrFromString(host+":1234", true) 30 | if e != nil { 31 | t.Fatal(e.Error(), host, port) 32 | } 33 | if p.Ip4 != ip { 34 | t.Error("Bad IP4 returned", host, port) 35 | } 36 | if p.Services != Services { 37 | t.Error("Bad Services returned", host, port) 38 | } 39 | if p.Port != port { 40 | t.Error("Bad port returned", host, port) 41 | } 42 | 43 | p, e = NewAddrFromString(host+":1234", false) 44 | if e != nil { 45 | t.Fatal(e.Error(), host, port) 46 | } 47 | if p.Ip4 != ip { 48 | t.Error("Bad IP4 returned", host, port) 49 | } 50 | if p.Services != Services { 51 | t.Error("Bad Services returned", host, port) 52 | } 53 | if p.Port != 1234 { 54 | t.Error("Bad port returned", host, port) 55 | } 56 | 57 | _, e = NewAddrFromString(host+":123456", false) 58 | if e == nil { 59 | t.Error("Error expected as port number too high", host, port) 60 | } 61 | 62 | _, e = NewAddrFromString(host+":123456", true) 63 | if e != nil { 64 | t.Error("No Error expected as port number to be ignored", host, port) 65 | } 66 | } 67 | 68 | func TestNewAddrFromString(t *testing.T) { 69 | PeerDB, _ = qdb.NewDB("tmpdir", true) 70 | 71 | // mainnet 72 | common.DefaultTcpPort = 8333 73 | test_one_addr(t, "fi.gocoin.pl", [4]byte{95, 217, 73, 162}, 8333) 74 | test_one_addr(t, "1.2.3.4", [4]byte{1, 2, 3, 4}, 8333) 75 | 76 | // Testnet 77 | common.DefaultTcpPort = 18333 78 | test_one_addr(t, "kaja.gocoin.pl", [4]byte{195, 136, 152, 164}, 18333) 79 | test_one_addr(t, "255.254.253.252", [4]byte{255, 254, 253, 252}, 18333) 80 | 81 | var e error 82 | _, e = NewAddrFromString("1.2.3.4.5", false) 83 | if e == nil { 84 | println("error expected") 85 | } 86 | 87 | _, e = NewAddrFromString("1.2.3.256", false) 88 | if e == nil { 89 | println("error expected") 90 | } 91 | PeerDB.Close() 92 | os.RemoveAll("tmpdir") 93 | } 94 | -------------------------------------------------------------------------------- /client/rpcapi/address.go: -------------------------------------------------------------------------------- 1 | package rpcapi 2 | 3 | import ( 4 | "encoding/hex" 5 | "github.com/piotrnar/gocoin/lib/btc" 6 | //"github.com/piotrnar/gocoin/client/common" 7 | ) 8 | 9 | /* 10 | 11 | {"result": 12 | {"isvalid":true, 13 | "address":"mqzwxBkSH1UKqEAjGwvkj6aV5Gc6BtBCSs", 14 | "scriptPubKey":"76a91472fc9e6b1bbbd40a66653989a758098bfbf1b54788ac", 15 | "ismine":false, 16 | "iswatchonly":false, 17 | "isscript":false 18 | } 19 | */ 20 | 21 | type ValidAddressResponse struct { 22 | Address string `json:"address"` 23 | ScriptPubKey string `json:"scriptPubKey"` 24 | IsValid bool `json:"isvalid"` 25 | IsMine bool `json:"ismine"` 26 | IsWatchOnly bool `json:"iswatchonly"` 27 | IsScript bool `json:"isscript"` 28 | } 29 | 30 | type InvalidAddressResponse struct { 31 | IsValid bool `json:"isvalid"` 32 | } 33 | 34 | func ValidateAddress(addr string) interface{} { 35 | a, e := btc.NewAddrFromString(addr) 36 | if e != nil { 37 | return new(InvalidAddressResponse) 38 | } 39 | res := new(ValidAddressResponse) 40 | res.IsValid = true 41 | res.Address = addr 42 | res.ScriptPubKey = hex.EncodeToString(a.OutScript()) 43 | return res 44 | //res.IsMine = false 45 | //res.IsWatchOnly = false 46 | //res.IsScript = false 47 | } 48 | -------------------------------------------------------------------------------- /client/speedups/sipasec.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | /* 4 | This is a EC_Verify speedup that is advised for non Windows systems. 5 | 6 | 1) Build and install sipa's secp256k1 lib for your system 7 | 8 | 2) Copy this file one level up and remove "speedup.go" from there 9 | 10 | 3) Rebuild clinet.exe and enjoy sipa's verify lib. 11 | */ 12 | 13 | import ( 14 | "github.com/piotrnar/gocoin/client/common" 15 | "github.com/piotrnar/gocoin/lib/btc" 16 | "github.com/piotrnar/gocoin/lib/others/cgo/sipasec" 17 | ) 18 | 19 | func sipa_ec_verify(k, s, h []byte) bool { 20 | return sipasec.EC_Verify(k, s, h) == 1 21 | } 22 | 23 | func schnorr_ec_verify(pkey, sign, msg []byte) bool { 24 | return sipasec.Schnorr_Verify(pkey, sign, msg) == 1 25 | } 26 | 27 | func check_pay_to_contract(m_keydata, base, hash []byte, parity bool) bool { 28 | return sipasec.CheckPayToContract(m_keydata, base, hash, parity) == 1 29 | } 30 | 31 | func init() { 32 | common.Log.Println("Using libsecp256k1.a for ECVerify, SchnorrVerify & CheckPayToContact") 33 | btc.EC_Verify = sipa_ec_verify 34 | btc.Schnorr_Verify = schnorr_ec_verify 35 | btc.Check_PayToContract = check_pay_to_contract 36 | } 37 | -------------------------------------------------------------------------------- /client/start.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | :again 3 | client.exe %1 %2 %3 %4 %5 %6 %7 %8 %9 4 | if errorlevel 67 goto terminate 5 | if errorlevel 66 goto again 6 | :terminate 7 | -------------------------------------------------------------------------------- /client/start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | while true; do 4 | ./client $* 5 | if [ $? -ne 66 ]; then 6 | break 7 | fi 8 | done 9 | 10 | -------------------------------------------------------------------------------- /client/txpool/system.go: -------------------------------------------------------------------------------- 1 | package txpool 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | func (t *OneTxToSend) SysSize() (size int) { 8 | size = int(unsafe.Sizeof(*t)) 9 | size += t.Tx.SysSize() 10 | if t.inPackages != nil { 11 | size += 8 * cap(t.inPackages) 12 | } 13 | if t.MemInputs != nil { 14 | size += (cap(t.MemInputs) + 7) & ^7 // round the size up to the nearest 8 bytes 15 | } 16 | return 17 | } 18 | 19 | func (t *OneTxRejected) SysSize() (size int) { 20 | size = int(unsafe.Sizeof(*t)) 21 | if t.Waiting4 != nil { 22 | size += int(unsafe.Sizeof(*t.Waiting4)) 23 | } 24 | if t.Tx != nil { 25 | size += t.Tx.SysSize() 26 | } 27 | return 28 | } 29 | 30 | func (t2s *OneTxToSend) memInputsSet(newval []bool) { 31 | if t2s.Footprint == 0 || cap(newval) == cap(t2s.MemInputs) { 32 | t2s.MemInputs = newval 33 | return 34 | } 35 | var old_size, new_size int 36 | if t2s.MemInputs != nil { 37 | old_size = (cap(t2s.MemInputs) + 7) & ^7 // round the size up to the nearest 8 bytes 38 | } 39 | t2s.MemInputs = newval 40 | if t2s.MemInputs != nil { 41 | new_size = (cap(t2s.MemInputs) + 7) & ^7 // round the size up to the nearest 8 bytes 42 | } 43 | if old_size != new_size { 44 | t2s.Footprint -= uint32(old_size) 45 | t2s.Footprint += uint32(new_size) 46 | TransactionsToSendSize -= uint64(old_size) 47 | TransactionsToSendSize += uint64(new_size) 48 | } 49 | } 50 | 51 | func (t2s *OneTxToSend) inPackagesSet(newval []*OneTxsPackage) { 52 | if t2s.Footprint == 0 || cap(newval) == cap(t2s.inPackages) { 53 | t2s.inPackages = newval 54 | return 55 | } 56 | var old_size, new_size int 57 | if t2s.inPackages != nil { 58 | old_size = 8 * cap(t2s.inPackages) 59 | } 60 | t2s.inPackages = newval 61 | if t2s.inPackages != nil { 62 | new_size = 8 * cap(t2s.inPackages) 63 | } 64 | if old_size != new_size { 65 | t2s.Footprint -= uint32(old_size) 66 | t2s.Footprint += uint32(new_size) 67 | TransactionsToSendSize -= uint64(old_size) 68 | TransactionsToSendSize += uint64(new_size) 69 | } 70 | } 71 | 72 | func FeePackagesSysSize() (size int) { 73 | size = int(unsafe.Sizeof(FeePackages)) + cap(FeePackages)*int(unsafe.Sizeof(FeePackages[0])) 74 | if len(FeePackages) > 0 { 75 | size += len(FeePackages) * int(unsafe.Sizeof(*FeePackages[0])) 76 | for _, fp := range FeePackages { 77 | size += cap(fp.Txs) * int(unsafe.Sizeof(fp.Txs[0])) 78 | } 79 | } 80 | return 81 | } 82 | -------------------------------------------------------------------------------- /client/usif/webui/counts.go: -------------------------------------------------------------------------------- 1 | package webui 2 | 3 | import ( 4 | "encoding/json" 5 | "net/http" 6 | "sort" 7 | 8 | "github.com/piotrnar/gocoin/client/common" 9 | ) 10 | 11 | func json_counts(w http.ResponseWriter, r *http.Request) { 12 | if !ipchecker(r) { 13 | return 14 | } 15 | type one_var_cnt struct { 16 | Var string `json:"var"` 17 | Cnt uint64 `json:"cnt"` 18 | } 19 | type one_net_rec struct { 20 | Var string `json:"var"` 21 | Rcvd uint64 `json:"rcvd"` 22 | Rbts uint64 `json:"rbts"` 23 | Sent uint64 `json:"sent"` 24 | Sbts uint64 `json:"sbts"` 25 | } 26 | 27 | var all_var_cnt struct { 28 | Gen []*one_var_cnt `json:"gen"` 29 | Txs []*one_var_cnt `json:"txs"` 30 | Net []*one_net_rec `json:"net"` 31 | } 32 | 33 | common.CounterMutex.Lock() 34 | for k, v := range common.Counter { 35 | if k[4] == '_' { 36 | var i int 37 | for i = 0; i < len(all_var_cnt.Net); i++ { 38 | if all_var_cnt.Net[i].Var == k[5:] { 39 | break 40 | } 41 | } 42 | if i == len(all_var_cnt.Net) { 43 | fin := k[5:] 44 | var nrec one_net_rec 45 | nrec.Var = fin 46 | nrec.Rcvd = common.Counter["rcvd_"+fin] 47 | nrec.Rbts = common.Counter["rbts_"+fin] 48 | nrec.Sent = common.Counter["sent_"+fin] 49 | nrec.Sbts = common.Counter["sbts_"+fin] 50 | all_var_cnt.Net = append(all_var_cnt.Net, &nrec) 51 | } 52 | } else if k[:2] == "Tx" { 53 | all_var_cnt.Txs = append(all_var_cnt.Txs, &one_var_cnt{Var: k[2:], Cnt: v}) 54 | } else { 55 | all_var_cnt.Gen = append(all_var_cnt.Gen, &one_var_cnt{Var: k, Cnt: v}) 56 | } 57 | } 58 | common.CounterMutex.Unlock() 59 | sort.Slice(all_var_cnt.Gen, func(i, j int) bool { 60 | return all_var_cnt.Gen[i].Var < all_var_cnt.Gen[j].Var 61 | }) 62 | sort.Slice(all_var_cnt.Txs, func(i, j int) bool { 63 | return all_var_cnt.Txs[i].Var < all_var_cnt.Txs[j].Var 64 | }) 65 | sort.Slice(all_var_cnt.Net, func(i, j int) bool { 66 | return all_var_cnt.Net[i].Var < all_var_cnt.Net[j].Var 67 | }) 68 | 69 | bx, er := json.Marshal(all_var_cnt) 70 | if er == nil { 71 | w.Header()["Content-Type"] = []string{"application/json"} 72 | w.Write(bx) 73 | } else { 74 | println(er.Error()) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /client/www/static/back_online.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/back_online.mp3 -------------------------------------------------------------------------------- /client/www/static/chainsync.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/chainsync.png -------------------------------------------------------------------------------- /client/www/static/copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/copy.png -------------------------------------------------------------------------------- /client/www/static/dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/dark.png -------------------------------------------------------------------------------- /client/www/static/del-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/del-black.png -------------------------------------------------------------------------------- /client/www/static/del-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/del-white.png -------------------------------------------------------------------------------- /client/www/static/empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/empty.png -------------------------------------------------------------------------------- /client/www/static/export-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/export-black.png -------------------------------------------------------------------------------- /client/www/static/export-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/export-white.png -------------------------------------------------------------------------------- /client/www/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/favicon.ico -------------------------------------------------------------------------------- /client/www/static/free-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/free-black.png -------------------------------------------------------------------------------- /client/www/static/free-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/free-white.png -------------------------------------------------------------------------------- /client/www/static/import-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/import-black.png -------------------------------------------------------------------------------- /client/www/static/import-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/import-white.png -------------------------------------------------------------------------------- /client/www/static/in-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/in-black.png -------------------------------------------------------------------------------- /client/www/static/in-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/in-white.png -------------------------------------------------------------------------------- /client/www/static/info-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/info-black.png -------------------------------------------------------------------------------- /client/www/static/info-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/info-white.png -------------------------------------------------------------------------------- /client/www/static/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/light.png -------------------------------------------------------------------------------- /client/www/static/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/loading.gif -------------------------------------------------------------------------------- /client/www/static/message.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/message.png -------------------------------------------------------------------------------- /client/www/static/music-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/music-black.png -------------------------------------------------------------------------------- /client/www/static/music-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/music-white.png -------------------------------------------------------------------------------- /client/www/static/new_block.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/new_block.mp3 -------------------------------------------------------------------------------- /client/www/static/nosort-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/nosort-black.png -------------------------------------------------------------------------------- /client/www/static/nosort-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/nosort-white.png -------------------------------------------------------------------------------- /client/www/static/out-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/out-black.png -------------------------------------------------------------------------------- /client/www/static/out-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/out-white.png -------------------------------------------------------------------------------- /client/www/static/pkgsort-off-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/pkgsort-off-black.png -------------------------------------------------------------------------------- /client/www/static/pkgsort-off-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/pkgsort-off-white.png -------------------------------------------------------------------------------- /client/www/static/pkgsort-on-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/pkgsort-on-black.png -------------------------------------------------------------------------------- /client/www/static/pkgsort-on-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/pkgsort-on-white.png -------------------------------------------------------------------------------- /client/www/static/qrcode-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/qrcode-black.png -------------------------------------------------------------------------------- /client/www/static/qrcode-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/qrcode-white.png -------------------------------------------------------------------------------- /client/www/static/refresh-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/refresh-black.png -------------------------------------------------------------------------------- /client/www/static/refresh-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/refresh-white.png -------------------------------------------------------------------------------- /client/www/static/request-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/request-black.png -------------------------------------------------------------------------------- /client/www/static/request-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/request-white.png -------------------------------------------------------------------------------- /client/www/static/saving.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/saving.png -------------------------------------------------------------------------------- /client/www/static/send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/send.png -------------------------------------------------------------------------------- /client/www/static/send_once.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/send_once.png -------------------------------------------------------------------------------- /client/www/static/server-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/server-black.png -------------------------------------------------------------------------------- /client/www/static/server-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/server-white.png -------------------------------------------------------------------------------- /client/www/static/sort-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/sort-black.png -------------------------------------------------------------------------------- /client/www/static/sort-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/sort-white.png -------------------------------------------------------------------------------- /client/www/static/stats.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/stats.png -------------------------------------------------------------------------------- /client/www/static/switch-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/switch-off.png -------------------------------------------------------------------------------- /client/www/static/switch-on.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/switch-on.png -------------------------------------------------------------------------------- /client/www/static/theme-switch-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/theme-switch-black.png -------------------------------------------------------------------------------- /client/www/static/theme-switch-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/theme-switch-white.png -------------------------------------------------------------------------------- /client/www/static/warning-black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/warning-black.png -------------------------------------------------------------------------------- /client/www/static/warning-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/client/www/static/warning-white.png -------------------------------------------------------------------------------- /client/www/templ/error.html: -------------------------------------------------------------------------------- 1 | 7 |
8 |
9 | You will be automatically redirected in 5 seconds... 10 | -------------------------------------------------------------------------------- /client/www/templ/page_tail.html: -------------------------------------------------------------------------------- 1 | 2 | --> 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /client/www/templ/restarting.html: -------------------------------------------------------------------------------- 1 |
2 | Your node is restarting. Once it is back online, reload the Home page. 3 | 10 | -------------------------------------------------------------------------------- /client/www/templ/shutdown.html: -------------------------------------------------------------------------------- 1 |
2 | Your node is shutting down. If you manually restart it, go back to the Home page. 3 | 10 | -------------------------------------------------------------------------------- /client/www/templ/txs_load.html: -------------------------------------------------------------------------------- 1 |
{TX_RAW_DATA}
2 | 17 | -------------------------------------------------------------------------------- /client/www/templ/wallet_off.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | Minimum output value to be included in wallet's balance: BTC 4 | 15 | 16 | 25 | 26 | 27 | 97 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/piotrnar/gocoin 2 | 3 | go 1.18 4 | -------------------------------------------------------------------------------- /lib/btc/block_test.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | import ( 4 | "io/ioutil" 5 | "net/http" 6 | "os" 7 | "testing" 8 | ) 9 | 10 | const block_hash = "0000000000000000000884ad62c7036a7e2022bca3f0bd68628414150e8a0ea6" 11 | 12 | var _block_filename = "" 13 | 14 | func block_filename() string { 15 | if _block_filename == "" { 16 | _block_filename = os.TempDir() + string(os.PathSeparator) + block_hash 17 | } 18 | return _block_filename 19 | } 20 | 21 | // fetch_block downloads a block from blockchain.info and stores it in the TEMP folder. 22 | func fetch_block(b *testing.B) { 23 | url := "https://blockstream.info/api/block/" + block_hash + "/raw" 24 | r, er := http.Get(url) 25 | if er == nil { 26 | if r.StatusCode == 200 { 27 | raw, er := ioutil.ReadAll(r.Body) 28 | r.Body.Close() 29 | if er == nil { 30 | er = ioutil.WriteFile(block_filename(), raw, 0600) 31 | if er != nil { 32 | b.Fatal(er.Error()) 33 | } 34 | } else { 35 | b.Fatal(er.Error()) 36 | } 37 | } else { 38 | b.Fatal("Unexpected HTTP Status code", r.StatusCode, url) 39 | } 40 | } else { 41 | b.Fatal(er.Error()) 42 | } 43 | } 44 | 45 | func BenchmarkBuildTxList(b *testing.B) { 46 | raw, e := ioutil.ReadFile(block_filename()) 47 | if e != nil { 48 | fetch_block(b) 49 | if raw, e = ioutil.ReadFile(block_filename()); e != nil { 50 | b.Fatal(e.Error()) 51 | } 52 | } 53 | b.SetBytes(int64(len(raw))) 54 | bl, e := NewBlock(raw) 55 | if e != nil { 56 | b.Fatal(e.Error()) 57 | } 58 | b.ResetTimer() 59 | for i := 0; i < b.N; i++ { 60 | bl.TxCount = 0 61 | bl.BuildTxList() 62 | } 63 | } 64 | 65 | func BenchmarkCalcMerkle(b *testing.B) { 66 | raw, e := ioutil.ReadFile(block_filename()) 67 | if e != nil { 68 | fetch_block(b) 69 | if raw, e = ioutil.ReadFile(block_filename()); e != nil { 70 | b.Fatal(e.Error()) 71 | } 72 | } 73 | bl, e := NewBlock(raw) 74 | if e != nil { 75 | b.Fatal(e.Error()) 76 | } 77 | bl.BuildTxList() 78 | mtr := make([][32]byte, len(bl.Txs), 3*len(bl.Txs)) // make the buffer 3 times longer as we use append() inside CalcMerkle 79 | for i, tx := range bl.Txs { 80 | mtr[i] = tx.Hash.Hash 81 | } 82 | b.ResetTimer() 83 | for i := 0; i < b.N; i++ { 84 | CalcMerkle(mtr) 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /lib/btc/const.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | const ( 4 | COIN = 1e8 5 | MAX_MONEY = 21000000 * COIN 6 | MAX_BLOCK_WEIGHT = 4e6 7 | MessageMagic = "Bitcoin Signed Message:\n" 8 | LOCKTIME_THRESHOLD = 500000000 9 | MAX_SCRIPT_ELEMENT_SIZE = 520 10 | MAX_BLOCK_SIGOPS_COST = 80000 11 | MAX_PUBKEYS_PER_MULTISIG = 20 12 | WITNESS_SCALE_FACTOR = 4 13 | 14 | SERVICE_NETWORK = 1 << 0 15 | SERVICE_SEGWIT = 1 << 3 16 | SERVICE_NETWORK_LIMITED = 1 << 10 17 | ) 18 | -------------------------------------------------------------------------------- /lib/btc/ecdsa.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | import ( 4 | "crypto/rand" 5 | "crypto/sha256" 6 | "errors" 7 | "math/big" 8 | "sync/atomic" 9 | 10 | "github.com/piotrnar/gocoin/lib/secp256k1" 11 | ) 12 | 13 | var ( 14 | ecdsaVerifyCnt uint64 15 | schnorrVerifyCnt uint64 16 | checkp2cVerifyCnt uint64 17 | 18 | EcdsaSignWithRFC6979 bool // set this to true to create RFC6979 deterministic ECDSA signatures 19 | 20 | EC_Verify func(k, s, h []byte) bool 21 | Schnorr_Verify func(pkey, sign, msg []byte) bool 22 | Check_PayToContract func(m_keydata, base, hash []byte, parity bool) bool 23 | ) 24 | 25 | func EcdsaVerifyCnt() uint64 { 26 | return atomic.LoadUint64(&ecdsaVerifyCnt) 27 | } 28 | 29 | func SchnorrVerifyCnt() uint64 { 30 | return atomic.LoadUint64(&schnorrVerifyCnt) 31 | } 32 | 33 | func CheckPay2ContractCnt() uint64 { 34 | return atomic.LoadUint64(&checkp2cVerifyCnt) 35 | } 36 | 37 | func EcdsaVerify(kd []byte, sd []byte, hash []byte) bool { 38 | atomic.AddUint64(&ecdsaVerifyCnt, 1) 39 | if len(kd) == 0 || len(sd) == 0 { 40 | return false 41 | } 42 | if EC_Verify != nil { 43 | return EC_Verify(kd, sd, hash) 44 | } 45 | return secp256k1.Verify(kd, sd, hash) 46 | } 47 | 48 | func EcdsaSign(priv, hash []byte) (r, s *big.Int, err error) { 49 | var sig secp256k1.Signature 50 | var sec, msg, nonce secp256k1.Number 51 | 52 | sec.SetBytes(priv) 53 | msg.SetBytes(hash) 54 | 55 | if EcdsaSignWithRFC6979 { 56 | // RFC6979 nonce calculation (e.g. Trezor compatible) 57 | var counter int 58 | var non32 [32]byte 59 | for { 60 | RFC6979_Nonce(priv, hash, nil, nil, counter, non32[:]) 61 | nonce.SetBytes(non32[:]) 62 | if nonce.Sign() > 0 && nonce.Cmp(&secp256k1.TheCurve.Order.Int) < 0 { 63 | break 64 | } 65 | } 66 | } else { 67 | // Old method GoCoin nonce calculation 68 | sha := sha256.New() 69 | sha.Write(priv) 70 | sha.Write(hash) 71 | for { 72 | var buf [32]byte 73 | rand.Read(buf[:]) 74 | sha.Write(buf[:]) 75 | nonce.SetBytes(sha.Sum(nil)) 76 | if nonce.Sign() > 0 && nonce.Cmp(&secp256k1.TheCurve.Order.Int) < 0 { 77 | break 78 | } 79 | } 80 | } 81 | 82 | if sig.Sign(&sec, &msg, &nonce, nil) != 1 { 83 | err = errors.New("ESCDS Sign error()") 84 | } 85 | return &sig.R.Int, &sig.S.Int, err 86 | } 87 | 88 | func SchnorrVerify(pkey, sig, msg []byte) bool { 89 | atomic.AddUint64(&schnorrVerifyCnt, 1) 90 | if Schnorr_Verify != nil { 91 | return Schnorr_Verify(pkey, sig, msg) 92 | } 93 | return secp256k1.SchnorrVerify(pkey, sig, msg) 94 | } 95 | 96 | func CheckPayToContract(m_keydata, base, hash []byte, parity bool) bool { 97 | atomic.AddUint64(&checkp2cVerifyCnt, 1) 98 | if Check_PayToContract != nil { 99 | return Check_PayToContract(m_keydata, base, hash, parity) 100 | } 101 | return secp256k1.CheckPayToContract(m_keydata, base, hash, parity) 102 | } 103 | -------------------------------------------------------------------------------- /lib/btc/key.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | import ( 4 | "errors" 5 | "encoding/hex" 6 | "github.com/piotrnar/gocoin/lib/secp256k1" 7 | ) 8 | 9 | type PublicKey struct { 10 | secp256k1.XY 11 | } 12 | 13 | type Signature struct { 14 | secp256k1.Signature 15 | HashType byte 16 | } 17 | 18 | func NewPublicKey(buf []byte) (res *PublicKey, e error) { 19 | res = new(PublicKey) 20 | if !res.XY.ParsePubkey(buf) { 21 | e = errors.New("NewPublicKey: Unknown format: "+hex.EncodeToString(buf[:])) 22 | res = nil 23 | } 24 | return 25 | } 26 | 27 | 28 | func NewSignature(buf []byte) (*Signature, error) { 29 | sig := new(Signature) 30 | le := sig.ParseBytes(buf) 31 | if le < 0 { 32 | return nil, errors.New("NewSignature: ParseBytes error") 33 | } 34 | if le>24 9 | neg := (nCompact&0x00800000)!=0 10 | word := nCompact & 0x007fffff 11 | if size <= 3 { 12 | word >>= 8*(3-size); 13 | res = big.NewInt(int64(word)) 14 | } else { 15 | res = big.NewInt(int64(word)) 16 | res.Lsh(res, uint(8*(size-3))) 17 | } 18 | if neg { 19 | res.Neg(res) 20 | } 21 | return res 22 | } 23 | 24 | 25 | func GetDifficulty(bits uint32) (diff float64) { 26 | shift := int(bits >> 24) & 0xff 27 | diff = float64(0x0000ffff) / float64(bits & 0x00ffffff) 28 | for shift < 29 { 29 | diff *= 256.0 30 | shift++ 31 | } 32 | for shift > 29 { 33 | diff /= 256.0 34 | shift-- 35 | } 36 | return 37 | } 38 | 39 | 40 | func GetCompact(b *big.Int) uint32 { 41 | 42 | size := uint32(len(b.Bytes())) 43 | var compact uint32 44 | 45 | if size <= 3 { 46 | compact = uint32(b.Int64() << uint(8*(3-size))) 47 | } else { 48 | b = new(big.Int).Rsh(b, uint(8*(size-3))) 49 | compact = uint32(b.Int64()) 50 | } 51 | 52 | // The 0x00800000 bit denotes the sign. 53 | // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. 54 | if (compact & 0x00800000) != 0 { 55 | compact >>= 8 56 | size++ 57 | } 58 | compact |= size << 24 59 | if b.Cmp(big.NewInt(0)) < 0 { 60 | compact |= 0x00800000 61 | } 62 | return compact 63 | } 64 | 65 | 66 | func CheckProofOfWork(hash *Uint256, bits uint32) bool { 67 | return hash.BigInt().Cmp(SetCompact(bits)) <= 0 68 | } 69 | -------------------------------------------------------------------------------- /lib/btc/target_test.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | import ( 4 | // "fmt" 5 | "testing" 6 | "math" 7 | "math/big" 8 | ) 9 | 10 | type onevec struct { 11 | e string 12 | d float64 13 | b uint32 14 | } 15 | 16 | var testvecs = []onevec { 17 | {b:0x1b0404cb, e:"00000000000404CB000000000000000000000000000000000000000000000000"}, 18 | {b:0x1d00ffff, e:"00000000FFFF0000000000000000000000000000000000000000000000000000"}, 19 | {b:436330132, d:8974296.01488785}, 20 | {b:436543292, d:3275464.59}, 21 | {b:436591499, d:2864140.51}, 22 | {b:436841986, d:1733207.51}, 23 | {b:437155514, d:1159929.50}, 24 | {b:436789733, d:1888786.71}, 25 | {b:453031340, d:92347.59}, 26 | {b:453281356, d:14484.16}, 27 | {b:470771548, d:16.62}, 28 | {b:486604799, d:1.00}, 29 | } 30 | 31 | func TestTarget(t *testing.T) { 32 | for i := range testvecs { 33 | x := SetCompact(testvecs[i].b) 34 | d := GetDifficulty(testvecs[i].b) 35 | 36 | c := GetCompact(x) 37 | //fmt.Printf("%d. %d/%d -> %.8f / %.8f\n", i, testvecs[i].b, c, d, testvecs[i].d) 38 | if testvecs[i].b != c { 39 | t.Error("Set/GetCompact mismatch at alement", i) 40 | } 41 | 42 | if testvecs[i].e!="" { 43 | y, _ := new(big.Int).SetString(testvecs[i].e, 16) 44 | if x.Cmp(y) != 0 { 45 | t.Error("Target mismatch at alement", i) 46 | } 47 | } 48 | 49 | if testvecs[i].d!=0 && math.Abs(d-testvecs[i].d) > 0.1 { 50 | t.Error("Difficulty mismatch at alement", i) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /lib/btc/tx_sys.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | import ( 4 | "unsafe" 5 | ) 6 | 7 | func (po *TxPrevOut) SysSize() int { 8 | return int(unsafe.Sizeof(*po)) 9 | } 10 | 11 | func (ti *TxIn) SysSize() (size int) { 12 | size = int(unsafe.Sizeof(*ti)) 13 | if ti.ScriptSig != nil { 14 | size += (cap(ti.ScriptSig) + 7) & ^7 15 | } 16 | return 17 | } 18 | 19 | func (to *TxOut) SysSize() (size int) { 20 | size = int(unsafe.Sizeof(*to)) 21 | if to.Pk_script != nil { 22 | size += (cap(to.Pk_script) + 7) &^ 7 23 | } 24 | return 25 | } 26 | 27 | func (tx *Tx) SysSize() (size int) { 28 | size = int(unsafe.Sizeof(*tx)) 29 | 30 | if tx.TxIn != nil { 31 | size += cap(tx.TxIn) * 8 32 | for _, ti := range tx.TxIn { 33 | size += ti.SysSize() 34 | } 35 | } 36 | 37 | if tx.TxOut != nil { 38 | size += cap(tx.TxOut) * 8 39 | for _, to := range tx.TxOut { 40 | size += to.SysSize() 41 | } 42 | } 43 | 44 | if tx.SegWit != nil { 45 | size += cap(tx.SegWit) * 8 46 | for _, sw := range tx.SegWit { 47 | if sw != nil { 48 | size += cap(sw) * 8 49 | for _, sww := range sw { 50 | if sww != nil { 51 | size += (cap(sww) + 7) &^ 7 52 | } 53 | } 54 | } 55 | } 56 | } 57 | if tx.Raw != nil { 58 | size += (cap(tx.Raw) + 7) &^ 7 59 | } 60 | 61 | if tx.TxVerVars == nil { 62 | return 63 | } 64 | size += int(unsafe.Sizeof(*tx.TxVerVars)) 65 | 66 | if tx.hashPrevouts != nil { 67 | size += int(unsafe.Sizeof(*tx.hashPrevouts)) 68 | } 69 | if tx.hashSequence != nil { 70 | size += int(unsafe.Sizeof(*tx.hashSequence)) 71 | } 72 | if tx.hashOutputs != nil { 73 | size += int(unsafe.Sizeof(*tx.hashOutputs)) 74 | } 75 | 76 | if tx.Spent_outputs != nil { 77 | size += 8 * cap(tx.Spent_outputs) 78 | for _, so := range tx.Spent_outputs { 79 | size += so.SysSize() 80 | } 81 | } 82 | 83 | if tx.tapSingleHashes != nil { 84 | size += int(unsafe.Sizeof(*tx.tapSingleHashes)) 85 | } 86 | if tx.tapOutSingleHash != nil { 87 | size += int(unsafe.Sizeof(*tx.tapOutSingleHash)) 88 | } 89 | 90 | return 91 | } 92 | -------------------------------------------------------------------------------- /lib/btc/uint256.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | import ( 4 | "bytes" 5 | "encoding/binary" 6 | "encoding/hex" 7 | "fmt" 8 | "math/big" 9 | ) 10 | 11 | const Uint256IdxLen = 8 // The bigger it is, the more memory is needed, but lower chance of a collision 12 | 13 | type Uint256 struct { 14 | Hash [32]byte 15 | } 16 | 17 | type BIDX [Uint256IdxLen]byte 18 | 19 | func NewUint256(h []byte) (res *Uint256) { 20 | res = new(Uint256) 21 | copy(res.Hash[:], h) 22 | return 23 | } 24 | 25 | // Get from MSB hexstring 26 | func NewUint256FromString(s string) (res *Uint256) { 27 | d, e := hex.DecodeString(s) 28 | if e != nil { 29 | //println("NewUint256FromString", s, e.Error()) 30 | return 31 | } 32 | if len(d) != 32 { 33 | //println("NewUint256FromString", s, "not 32 bytes long") 34 | return 35 | } 36 | res = new(Uint256) 37 | for i := 0; i < 32; i++ { 38 | res.Hash[31-i] = d[i] 39 | } 40 | return 41 | } 42 | 43 | func NewSha2Hash(data []byte) (res *Uint256) { 44 | res = new(Uint256) 45 | ShaHash(data, res.Hash[:]) 46 | return 47 | } 48 | 49 | func (u *Uint256) Bytes() []byte { 50 | return u.Hash[:] 51 | } 52 | 53 | func (u *Uint256) String() (s string) { 54 | for i := 0; i < 32; i++ { 55 | s += fmt.Sprintf("%02x", u.Hash[31-i]) 56 | } 57 | return 58 | } 59 | 60 | func (u *Uint256) Equal(o *Uint256) bool { 61 | return bytes.Equal(u.Hash[:], o.Hash[:]) 62 | } 63 | 64 | func (u *Uint256) Calc(data []byte) { 65 | ShaHash(data, u.Hash[:]) 66 | } 67 | 68 | func BIdx(hash []byte) (o BIDX) { 69 | copy(o[:], hash[:Uint256IdxLen]) 70 | return 71 | } 72 | 73 | func (u *Uint256) BIdx() (o BIDX) { 74 | o = BIdx(u.Hash[:]) 75 | return 76 | } 77 | 78 | func BIdxString(o [Uint256IdxLen]byte) (s string) { 79 | s = fmt.Sprintf("%016x", binary.LittleEndian.Uint64(o[:])) 80 | return 81 | } 82 | 83 | func (u *Uint256) BigInt() *big.Int { 84 | var buf [32]byte 85 | for i := range buf { 86 | buf[i] = u.Hash[31-i] 87 | } 88 | return new(big.Int).SetBytes(buf[:]) 89 | } 90 | -------------------------------------------------------------------------------- /lib/btc/unspent.go: -------------------------------------------------------------------------------- 1 | package btc 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | ) 7 | 8 | type AllUnspentTx []*OneUnspentTx 9 | 10 | // OneUnspentTx is returned by GetUnspentFromPkScr. 11 | type OneUnspentTx struct { 12 | *BtcAddr 13 | destAddr string 14 | Value uint64 15 | TxPrevOut 16 | MinedAt uint32 17 | } 18 | 19 | func (x AllUnspentTx) Len() int { 20 | return len(x) 21 | } 22 | 23 | func (x AllUnspentTx) Less(i, j int) bool { 24 | if x[i].MinedAt == x[j].MinedAt { 25 | if x[i].TxPrevOut.Hash == x[j].TxPrevOut.Hash { 26 | return x[i].TxPrevOut.Vout < x[j].TxPrevOut.Vout 27 | } 28 | return binary.LittleEndian.Uint64(x[i].TxPrevOut.Hash[24:32]) < 29 | binary.LittleEndian.Uint64(x[j].TxPrevOut.Hash[24:32]) 30 | } 31 | return x[i].MinedAt < x[j].MinedAt 32 | } 33 | 34 | func (x AllUnspentTx) Swap(i, j int) { 35 | x[i], x[j] = x[j], x[i] 36 | } 37 | 38 | func (ou *OneUnspentTx) String() (s string) { 39 | s = fmt.Sprintf("%15.8f ", float64(ou.Value)/1e8) + ou.TxPrevOut.String() 40 | if ou.BtcAddr != nil { 41 | s += " " + ou.DestAddr() + ou.BtcAddr.Label() 42 | } 43 | if ou.MinedAt != 0 { 44 | s += fmt.Sprint(" ", ou.MinedAt) 45 | } 46 | return 47 | } 48 | 49 | func (ou *OneUnspentTx) UnspentTextLine() (s string) { 50 | s = fmt.Sprintf("%s # %.8f BTC @ %s%s, block %d", ou.TxPrevOut.String(), 51 | float64(ou.Value)/1e8, ou.DestAddr(), ou.BtcAddr.Label(), ou.MinedAt) 52 | return 53 | } 54 | 55 | func (ou *OneUnspentTx) DestAddr() string { 56 | if ou.destAddr == "" { 57 | return ou.BtcAddr.String() 58 | } 59 | return ou.destAddr 60 | } 61 | -------------------------------------------------------------------------------- /lib/chain/chain_diff.go: -------------------------------------------------------------------------------- 1 | package chain 2 | 3 | import ( 4 | "math/big" 5 | 6 | "github.com/piotrnar/gocoin/lib/btc" 7 | ) 8 | 9 | const ( 10 | POWRetargetSpam = 14 * 24 * 60 * 60 // two weeks 11 | TargetSpacing = 10 * 60 12 | targetInterval = POWRetargetSpam / TargetSpacing 13 | ) 14 | 15 | func (ch *Chain) GetNextWorkRequired(lst *BlockTreeNode, ts uint32) (res uint32) { 16 | // Genesis block 17 | if lst.Parent == nil { 18 | return ch.Consensus.MaxPOWBits 19 | } 20 | 21 | if ((lst.Height + 1) % targetInterval) != 0 { 22 | // Special difficulty rule for testnet: 23 | if ch.testnet() { 24 | // If the new block's timestamp is more than 2* 10 minutes 25 | // then allow mining of a min-difficulty block. 26 | if ts > lst.Timestamp()+TargetSpacing*2 { 27 | return ch.Consensus.MaxPOWBits 28 | } else { 29 | // Return the last non-special-min-difficulty-rules-block 30 | prv := lst 31 | for prv.Parent != nil && (prv.Height%targetInterval) != 0 && prv.Bits() == ch.Consensus.MaxPOWBits { 32 | prv = prv.Parent 33 | } 34 | return prv.Bits() 35 | } 36 | } 37 | return lst.Bits() 38 | } 39 | 40 | prv := lst 41 | for i := 0; i < targetInterval-1; i++ { 42 | prv = prv.Parent 43 | } 44 | 45 | actualTimespan := int64(lst.Timestamp()) - int64(prv.Timestamp()) 46 | 47 | if actualTimespan < POWRetargetSpam/4 { 48 | actualTimespan = POWRetargetSpam / 4 49 | } 50 | if actualTimespan > POWRetargetSpam*4 { 51 | actualTimespan = POWRetargetSpam * 4 52 | } 53 | 54 | // Retarget 55 | var bnewbn *big.Int 56 | if ch.testnet4() { 57 | // Use the last non-special-min-difficulty-rules-block 58 | prv = lst 59 | for prv.Parent != nil && (prv.Height%targetInterval) != 0 && prv.Bits() == ch.Consensus.MaxPOWBits { 60 | prv = prv.Parent 61 | } 62 | bnewbn = btc.SetCompact(prv.Bits()) 63 | } else { 64 | bnewbn = btc.SetCompact(lst.Bits()) 65 | } 66 | bnewbn.Mul(bnewbn, big.NewInt(actualTimespan)) 67 | bnewbn.Div(bnewbn, big.NewInt(POWRetargetSpam)) 68 | 69 | if bnewbn.Cmp(ch.Consensus.MaxPOWValue) > 0 { 70 | bnewbn = ch.Consensus.MaxPOWValue 71 | } 72 | 73 | res = btc.GetCompact(bnewbn) 74 | 75 | return 76 | } 77 | 78 | // MorePOW returns true if b1 has more POW than b2. 79 | func (b1 *BlockTreeNode) MorePOW(b2 *BlockTreeNode) bool { 80 | var b1sum, b2sum float64 81 | for b1.Height > b2.Height { 82 | b1sum += btc.GetDifficulty(b1.Bits()) 83 | b1 = b1.Parent 84 | } 85 | for b2.Height > b1.Height { 86 | b2sum += btc.GetDifficulty(b2.Bits()) 87 | b2 = b2.Parent 88 | } 89 | for b1 != b2 { 90 | b1sum += btc.GetDifficulty(b1.Bits()) 91 | b2sum += btc.GetDifficulty(b2.Bits()) 92 | b1 = b1.Parent 93 | b2 = b2.Parent 94 | } 95 | return b1sum > b2sum 96 | } 97 | -------------------------------------------------------------------------------- /lib/chain/const.go: -------------------------------------------------------------------------------- 1 | package chain 2 | 3 | const( 4 | BlockMapInitLen = 500e3 5 | MovingCheckopintDepth = 2016 // Do not accept forks that wold go deeper in a past 6 | BIP16SwitchTime = 1333238400 // BIP16 didn't become active until Apr 1 2012 7 | COINBASE_MATURITY = 100 8 | MedianTimeSpan = 11 9 | ) 10 | -------------------------------------------------------------------------------- /lib/chain/dbg.go: -------------------------------------------------------------------------------- 1 | package chain 2 | 3 | const ( 4 | DBG_WASTED = 1 << 0 5 | DBG_UNSPENT = 1 << 1 6 | DBG_BLOCKS = 1 << 2 7 | DBG_ORPHAS = 1 << 3 8 | DBG_TX = 1 << 4 9 | DBG_SCRIPT = 1 << 5 10 | DBG_VERIFY = 1 << 6 11 | DBG_SCRERR = 1 << 7 12 | ) 13 | 14 | var dbgmask uint32 = 0 15 | 16 | func DbgSwitch(b uint32, on bool) { 17 | if on { 18 | dbgmask |= b 19 | } else { 20 | dbgmask ^= (b & dbgmask) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /lib/others/bech32/segwit.go: -------------------------------------------------------------------------------- 1 | package bech32 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | ) 7 | 8 | // convert_bits returns nil on error. 9 | func convert_bits(outbits uint, in []byte, inbits uint, pad bool) []byte { 10 | var val uint32 11 | var bits uint 12 | maxv := uint32(1<= outbits { 18 | bits -= outbits 19 | out.WriteByte(byte((val >> bits) & maxv)) 20 | } 21 | } 22 | if pad { 23 | if bits != 0 { 24 | out.WriteByte(byte((val << (outbits - bits)) & maxv)) 25 | } 26 | } else if ((val<<(outbits-bits))&maxv) != 0 || bits >= inbits { 27 | return nil 28 | } 29 | return out.Bytes() 30 | } 31 | 32 | // SegwitEncode returns an empty string on error. 33 | func SegwitEncode(hrp string, witver int, witprog []byte) string { 34 | if witver > 16 { 35 | return "" 36 | } 37 | if witver == 0 && len(witprog) != 20 && len(witprog) != 32 { 38 | return "" 39 | } 40 | if len(witprog) < 2 || len(witprog) > 40 { 41 | return "" 42 | } 43 | return Encode(hrp, append([]byte{byte(witver)}, convert_bits(5, witprog, 8, true)...), witver > 0) 44 | } 45 | 46 | // SegwitDecode returns (0, nil) on error. 47 | func SegwitDecode(hrp, addr string) (witver int, witdata []byte, er error) { 48 | hrp_actual, data, bech32m := Decode(addr) 49 | if hrp_actual == "" || len(data) == 0 || len(data) > 65 { 50 | er = errors.New("BECH32 decode error") 51 | return 52 | } 53 | if hrp != hrp_actual { 54 | er = errors.New("HRP mismatch") 55 | return 56 | } 57 | if data[0] > 16 { 58 | er = errors.New("WITNESS Version too high") 59 | return 60 | } 61 | if data[0] == 0 && bech32m { 62 | er = errors.New("WITNESS using M for Version 0") 63 | return 64 | } 65 | if data[0] != 0 && !bech32m { 66 | er = errors.New("WITNESS not using M when needed") 67 | return 68 | } 69 | witdata = convert_bits(8, data[1:], 5, false) 70 | if witdata == nil { 71 | er = errors.New("ERROR from convert_bits") 72 | return 73 | } 74 | if len(witdata) < 2 || len(witdata) > 40 { 75 | er = errors.New("WITNESS data length error") 76 | witdata = nil 77 | return 78 | } 79 | if data[0] == 0 && len(witdata) != 20 && len(witdata) != 32 { 80 | er = errors.New("WITNESS Version 0 data length error") 81 | witdata = nil 82 | return 83 | } 84 | witver = int(data[0]) 85 | return 86 | } 87 | -------------------------------------------------------------------------------- /lib/others/bip39/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2020 Tyler Smith and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /lib/others/bip39/README.md: -------------------------------------------------------------------------------- 1 | # bip39 2 | 3 | Package bip39 originated from "github.com/tyler-smith/go-bip39" 4 | 5 | Shipped with Gocoin source code for security and convenience. 6 | 7 | Only English mnemonics supported by this version. 8 | -------------------------------------------------------------------------------- /lib/others/blockdb/README.md: -------------------------------------------------------------------------------- 1 | This package can be used for reading blocks from the storage of the reference (satoshi's) client. -------------------------------------------------------------------------------- /lib/others/blockdb/blockdb.go: -------------------------------------------------------------------------------- 1 | /* 2 | This package is suposed to help importin Satoshi's bitcoin 3 | client blockchain into Gocoin's bitcoin client. 4 | */ 5 | package blockdb 6 | 7 | import ( 8 | "fmt" 9 | "os" 10 | "bytes" 11 | "errors" 12 | ) 13 | 14 | 15 | type BlockDB struct { 16 | dir string 17 | magic [4]byte 18 | f *os.File 19 | currfileidx uint32 20 | } 21 | 22 | 23 | func NewBlockDB(dir string, magic [4]byte) (res *BlockDB) { 24 | f, e := os.Open(idx2fname(dir, 0)) 25 | if e != nil { 26 | panic(e.Error()) 27 | } 28 | res = new(BlockDB) 29 | res.dir = dir 30 | res.magic = magic 31 | res.f = f 32 | return 33 | } 34 | 35 | 36 | func idx2fname(dir string, fidx uint32) string { 37 | if fidx == 0xffffffff { 38 | return "blk99999.dat" 39 | } 40 | return fmt.Sprintf("%s/blk%05d.dat", dir, fidx) 41 | } 42 | 43 | 44 | func readBlockFromFile(f *os.File, mag []byte) (res []byte, e error) { 45 | var buf [4]byte 46 | _, e = f.Read(buf[:]) 47 | if e != nil { 48 | return 49 | } 50 | 51 | if !bytes.Equal(buf[:], mag[:]) { 52 | e = errors.New(fmt.Sprintf("BlockDB: Unexpected magic: %02x%02x%02x%02x", 53 | buf[0], buf[1], buf[2], buf[3])) 54 | return 55 | } 56 | 57 | _, e = f.Read(buf[:]) 58 | if e != nil { 59 | return 60 | } 61 | le := uint32(lsb2uint(buf[:])) 62 | if le<81 { 63 | e = errors.New(fmt.Sprintf("Incorrect block size %d", le)) 64 | return 65 | } 66 | 67 | res = make([]byte, le) 68 | _, e = f.Read(res[:]) 69 | if e!=nil { 70 | return 71 | } 72 | 73 | return 74 | } 75 | 76 | 77 | func (db *BlockDB)readOneBlock() (res []byte, e error) { 78 | fpos, _ := db.f.Seek(0, 1) 79 | res, e = readBlockFromFile(db.f, db.magic[:]) 80 | if e != nil { 81 | db.f.Seek(int64(fpos), os.SEEK_SET) // restore the original position 82 | return 83 | } 84 | return 85 | } 86 | 87 | func (db *BlockDB) FetchNextBlock() (bl []byte, e error) { 88 | if db.f == nil { 89 | println("DB file not open - this should never happen") 90 | os.Exit(1) 91 | } 92 | bl, e = db.readOneBlock() 93 | if e != nil { 94 | f, e2 := os.Open(idx2fname(db.dir, db.currfileidx+1)) 95 | if e2 == nil { 96 | db.currfileidx++ 97 | db.f.Close() 98 | db.f = f 99 | bl, e = db.readOneBlock() 100 | } 101 | } 102 | return 103 | } 104 | 105 | func lsb2uint(lt []byte) (res uint64) { 106 | for i:=0; i pacman -S make autoconf automake libtool lzip gmp 19 | 20 | 21 | 3. secp256k1 22 | Now use "MSYS2 UCRT64" shell and execute: 23 | 24 | > cd ~ 25 | > git clone https://github.com/bitcoin/bitcoin.git 26 | > cd bitcoin/src/secp256k1/ 27 | > ./autogen.sh 28 | > ./configure 29 | > make 30 | > make install 31 | 32 | 33 | 34 | If everything went well, you should see "PASS" executing "go test" in this folder. 35 | Then copy "gocoin/client/speedups/sipasec.go" to "gocoin/client/" to boost your client. 36 | */ 37 | 38 | // #cgo LDFLAGS: -lsecp256k1 -lgmp 39 | import "C" 40 | -------------------------------------------------------------------------------- /lib/others/ltc/ltc.go: -------------------------------------------------------------------------------- 1 | package ltc 2 | 3 | import ( 4 | "bytes" 5 | 6 | "github.com/piotrnar/gocoin/lib/btc" 7 | "github.com/piotrnar/gocoin/lib/others/utils" 8 | "github.com/piotrnar/gocoin/lib/utxo" 9 | ) 10 | 11 | const LTC_ADDR_VERSION = 48 12 | const LTC_ADDR_VERSION_SCRIPT = 50 13 | 14 | // LTC signing uses different seed string 15 | func HashFromMessage(msg []byte, out []byte) { 16 | const MessageMagic = "Litecoin Signed Message:\n" 17 | b := new(bytes.Buffer) 18 | btc.WriteVlen(b, uint64(len(MessageMagic))) 19 | b.Write([]byte(MessageMagic)) 20 | btc.WriteVlen(b, uint64(len(msg))) 21 | b.Write(msg) 22 | btc.ShaHash(b.Bytes(), out) 23 | } 24 | 25 | func AddrVerPubkey(testnet bool) byte { 26 | if !testnet { 27 | return LTC_ADDR_VERSION 28 | } 29 | return btc.AddrVerPubkey(testnet) 30 | } 31 | 32 | // At some point Litecoin started using addresses with M in front (version 50) - see github issue #41 33 | func AddrVerScript(testnet bool) byte { 34 | if !testnet { 35 | return LTC_ADDR_VERSION_SCRIPT 36 | } 37 | return btc.AddrVerScript(testnet) 38 | } 39 | 40 | func NewAddrFromPkScript(scr []byte, testnet bool) (ad *btc.BtcAddr) { 41 | ad = btc.NewAddrFromPkScript(scr, testnet) 42 | if ad != nil && ad.Version == btc.AddrVerPubkey(false) { 43 | ad.Version = LTC_ADDR_VERSION 44 | } 45 | return 46 | } 47 | 48 | func GetUnspent(addr *btc.BtcAddr) (res utxo.AllUnspentTx) { 49 | var er error 50 | 51 | res, er = utils.GetUnspentFromBlockchair(addr, "litecoin") 52 | if er == nil { 53 | return 54 | } 55 | println("GetUnspentFromBlockchair:", er.Error()) 56 | 57 | return 58 | } 59 | 60 | func verify_txid(txid *btc.Uint256, rawtx []byte) bool { 61 | tx, _ := btc.NewTx(rawtx) 62 | if tx == nil { 63 | return false 64 | } 65 | tx.SetHash(rawtx) 66 | return txid.Equal(&tx.Hash) 67 | } 68 | 69 | // GetTxFromWeb downloads testnet's raw transaction from a web server. 70 | func GetTxFromWeb(txid *btc.Uint256) (raw []byte) { 71 | raw = utils.GetTxFromBlockchair(txid, "litecoin") 72 | if raw != nil && verify_txid(txid, raw) { 73 | return 74 | } 75 | println("GetTxFromBlockchair failed", len(raw), txid.String()) 76 | 77 | return 78 | } 79 | -------------------------------------------------------------------------------- /lib/others/memory/AUTHORS: -------------------------------------------------------------------------------- 1 | # This file lists authors for copyright purposes. This file is distinct from 2 | # the CONTRIBUTORS files. See the latter for an explanation. 3 | # 4 | # Names should be added to this file as: 5 | # Name or Organization 6 | # 7 | # The email address is not required for organizations. 8 | # 9 | # Please keep the list sorted. 10 | 11 | Jan Mercl <0xjnml@gmail.com> 12 | Steffen Butzer 13 | Gleb Sakhnov 14 | -------------------------------------------------------------------------------- /lib/others/memory/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This file lists people who contributed code to this repository. The AUTHORS 2 | # file lists the copyright holders; this file lists people. 3 | # 4 | # Names should be added to this file like so: 5 | # Name 6 | # 7 | # Please keep the list sorted. 8 | 9 | Anup Kodlekere 10 | Jan Mercl <0xjnml@gmail.com> 11 | Steffen Butzer 12 | ZHU Zijia 13 | Gleb Sakhnov 14 | -------------------------------------------------------------------------------- /lib/others/memory/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 The Memory Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the names of the authors nor the names of the 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /lib/others/memory/LICENSE-GO: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /lib/others/memory/LICENSE-MMAP-GO: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011, Evan Shaw 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | * Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | * Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | * Neither the name of the copyright holder nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 | DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY 19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 | 26 | -------------------------------------------------------------------------------- /lib/others/memory/README.md: -------------------------------------------------------------------------------- 1 | # memory 2 | 3 | Package memory originated from "modernc.org/memory" 4 | New address: https://gitlab.com/cznic/memory 5 | 6 | It is used by Gocoin client node to allocate UTXO records in memory. 7 | The idea is to improve performance by disablig GC over UTXO records. -------------------------------------------------------------------------------- /lib/others/memory/counters.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Memory Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package memory // import "modernc.org/memory" 6 | 7 | const counters = true 8 | -------------------------------------------------------------------------------- /lib/others/memory/memory32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Memory Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build 386 || arm || armbe || mips || mipsle || ppc || s390 || s390x || sparc 6 | // +build 386 arm armbe mips mipsle ppc s390 s390x sparc 7 | 8 | package memory // import "modernc.org/memory" 9 | 10 | type rawmem [1<<31 - 2]byte 11 | -------------------------------------------------------------------------------- /lib/others/memory/memory64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2018 The Memory Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build amd64 || amd64p32 || arm64 || arm64be || mips64 || mips64le || mips64p32 || mips64p32le || ppc64 || ppc64le || sparc64 || riscv64 6 | // +build amd64 amd64p32 arm64 arm64be mips64 mips64le mips64p32 mips64p32le ppc64 ppc64le sparc64 riscv64 7 | 8 | package memory // import "modernc.org/memory" 9 | 10 | type rawmem [1<<50 - 1]byte 11 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_darwin.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Memory Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build amd64 || arm64 6 | // +build amd64 arm64 7 | 8 | package memory 9 | 10 | import ( 11 | _ "unsafe" 12 | ) 13 | 14 | // Function syscall.mmap for darwin and openbsd calls internal/abi.FuncPCABI0, 15 | // which is implemented as a compile intrinsic so the code cannot be reused. 16 | // Using go:linkname directive to link mmapSyscall to syscall.mmap 17 | 18 | //go:linkname mmapSyscall syscall.mmap 19 | func mmapSyscall(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) 20 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_freebsd_32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-GO file. 4 | 5 | //go:build freebsd && 386 6 | // +build freebsd,386 7 | 8 | package memory 9 | 10 | import ( 11 | "syscall" 12 | ) 13 | 14 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/zsyscall_freebsd_386.go 15 | func mmapSyscall(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { 16 | r0, _, e1 := syscall.Syscall9(syscall.SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos), uintptr(pos>>32), 0, 0) 17 | ret = uintptr(r0) 18 | if e1 != 0 { 19 | err = e1 20 | } 21 | return 22 | } 23 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_freebsd_64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-GO file. 4 | 5 | //go:build freebsd && amd64 6 | // +build freebsd,amd64 7 | 8 | package memory 9 | 10 | import ( 11 | "syscall" 12 | ) 13 | 14 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/zsyscall_freebsd_amd64.go;l=1337-1346 15 | func mmapSyscall(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { 16 | r0, _, e1 := syscall.Syscall6(syscall.SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), uintptr(pos)) 17 | ret = uintptr(r0) 18 | if e1 != 0 { 19 | err = e1 20 | } 21 | return 22 | } 23 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_linux_32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-GO file. 4 | 5 | //go:build linux && (386 || arm || mips || mipsle) 6 | // +build linux 7 | // +build 386 arm mips mipsle 8 | 9 | package memory 10 | 11 | import ( 12 | "syscall" 13 | ) 14 | 15 | // Function syscall.mmap and syscall.mmap2 are same for linux/386, linux/arm, 16 | // linux/mips and linux/mipsle 17 | 18 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/syscall_linux_386.go;l=99-105 19 | func mmapSyscall(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { 20 | page := uintptr(offset / 4096) 21 | if offset != int64(page)*4096 { 22 | return 0, syscall.EINVAL 23 | } 24 | return mmap2Syscall(addr, length, prot, flags, fd, page) 25 | } 26 | 27 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/zsyscall_linux_386.go;l=1361-1370 28 | func mmap2Syscall(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) { 29 | r0, _, e1 := syscall.Syscall6(syscall.SYS_MMAP2, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(pageOffset)) 30 | xaddr = uintptr(r0) 31 | if e1 != 0 { 32 | err = e1 33 | } 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_linux_64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-GO file. 4 | 5 | //go:build linux && (amd64 || arm64 || mips64 || mips64le || riscv64 || ppc64le) 6 | // +build linux 7 | // +build amd64 arm64 mips64 mips64le riscv64 ppc64le 8 | 9 | package memory 10 | 11 | import ( 12 | "syscall" 13 | ) 14 | 15 | // Function syscall.mmap is same for linux/amd64, linux/arm64, linux/mips64, 16 | // linux/mips64le and linux/riscv64. 17 | 18 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/zsyscall_linux_amd64.go;l=1575-1584 19 | func mmapSyscall(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { 20 | r0, _, e1 := syscall.Syscall6(syscall.SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)) 21 | xaddr = uintptr(r0) 22 | if e1 != 0 { 23 | err = e1 24 | } 25 | return 26 | } 27 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_linux_s390x.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-GO file. 4 | 5 | package memory 6 | 7 | import ( 8 | "syscall" 9 | "unsafe" 10 | ) 11 | 12 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/syscall_linux_s390x.go;l=105-115 13 | // Linux on s390x uses the old mmap interface, which requires arguments to be passed in a struct. 14 | // mmap2 also requires arguments to be passed in a struct; it is currently not exposed in . 15 | func mmapSyscall(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { 16 | mmap_args := [6]uintptr{addr, length, uintptr(prot), uintptr(flags), uintptr(fd), uintptr(offset)} 17 | r0, _, e1 := syscall.Syscall(syscall.SYS_MMAP, uintptr(unsafe.Pointer(&mmap_args[0])), 0, 0) 18 | xaddr = uintptr(r0) 19 | if e1 != 0 { 20 | err = e1 21 | } 22 | return 23 | } 24 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_netbsd_32.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-GO file. 4 | 5 | //go:build netbsd && 386 6 | // +build netbsd,386 7 | 8 | package memory 9 | 10 | import ( 11 | "syscall" 12 | ) 13 | 14 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/zsyscall_freebsd_386.go 15 | func mmapSyscall(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { 16 | r0, _, e1 := syscall.Syscall9(syscall.SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), uintptr(pos>>32), 0) 17 | ret = uintptr(r0) 18 | if e1 != 0 { 19 | err = e1 20 | } 21 | return 22 | } 23 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_netbsd_64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-GO file. 4 | 5 | //go:build netbsd && amd64 6 | // +build netbsd,amd64 7 | 8 | package memory 9 | 10 | import ( 11 | "syscall" 12 | ) 13 | 14 | // https://cs.opensource.google/go/go/+/refs/tags/go1.17.8:src/syscall/zsyscall_netbsd_amd64.go;l=1190 15 | func mmapSyscall(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error) { 16 | r0, _, e1 := syscall.Syscall9(syscall.SYS_MMAP, uintptr(addr), uintptr(length), uintptr(prot), uintptr(flag), uintptr(fd), 0, uintptr(pos), 0, 0) 17 | ret = uintptr(r0) 18 | if e1 != 0 { 19 | err = e1 20 | } 21 | return 22 | } 23 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_openbsd.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Memory Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:build 386 || amd64 6 | // +build 386 amd64 7 | 8 | package memory 9 | 10 | import ( 11 | _ "unsafe" 12 | ) 13 | 14 | // Function syscall.mmap for darwin and openbsd calls internal/abi.FuncPCABI0, 15 | // which is implemented as a compile intrinsic so the code cannot be reused. 16 | // Using go:linkname directive to link mmapSyscall to syscall.mmap 17 | 18 | //go:linkname mmapSyscall syscall.mmap 19 | func mmapSyscall(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) 20 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_unix.go: -------------------------------------------------------------------------------- 1 | // Copyright 2011 Evan Shaw. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE-MMAP-GO file. 4 | 5 | //go:build darwin || dragonfly || freebsd || linux || openbsd || solaris || netbsd 6 | // +build darwin dragonfly freebsd linux openbsd solaris netbsd 7 | 8 | // Modifications (c) 2017 The Memory Authors. 9 | 10 | package memory // import "modernc.org/memory" 11 | 12 | import ( 13 | "os" 14 | "syscall" 15 | ) 16 | 17 | const pageSizeLog = 20 18 | 19 | var ( 20 | osPageMask = osPageSize - 1 21 | osPageSize = os.Getpagesize() 22 | ) 23 | 24 | func unmap(addr uintptr, size int) error { 25 | _, _, errno := syscall.Syscall(syscall.SYS_MUNMAP, addr, uintptr(size), 0) 26 | if errno != 0 { 27 | return errno 28 | } 29 | 30 | return nil 31 | } 32 | 33 | // pageSize aligned. 34 | func mmap(size int) (uintptr, int, error) { 35 | size = roundup(size, osPageSize) 36 | // The actual mmap syscall varies by architecture. mmapSyscall provides same 37 | // functionality as the unexported funtion syscall.mmap and is declared in 38 | // mmap_*_*.go and mmap_fallback.go. To add support for a new architecture, 39 | // check function mmap in src/syscall/syscall_*_*.go or 40 | // src/syscall/zsyscall_*_*.go in Go's source code. 41 | p, err := mmapSyscall(0, uintptr(size+pageSize), syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_PRIVATE|syscall.MAP_ANON, -1, 0) 42 | if err != nil { 43 | return 0, 0, err 44 | } 45 | 46 | n := size + pageSize 47 | if p&uintptr(osPageMask) != 0 { 48 | panic("internal error") 49 | } 50 | 51 | mod := int(p) & pageMask 52 | if mod != 0 { 53 | m := pageSize - mod 54 | if err := unmap(p, m); err != nil { 55 | return 0, 0, err 56 | } 57 | 58 | n -= m 59 | p += uintptr(m) 60 | } 61 | 62 | if p&uintptr(pageMask) != 0 { 63 | panic("internal error") 64 | } 65 | 66 | if n-size != 0 { 67 | if err := unmap(p+uintptr(size), n-size); err != nil { 68 | return 0, 0, err 69 | } 70 | } 71 | 72 | return p, size, nil 73 | } 74 | -------------------------------------------------------------------------------- /lib/others/memory/mmap_windows.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Memory Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package memory // import "modernc.org/memory" 6 | 7 | import ( 8 | "os" 9 | "syscall" 10 | ) 11 | 12 | const ( 13 | _MEM_COMMIT = 0x1000 14 | _MEM_RESERVE = 0x2000 15 | _MEM_DECOMMIT = 0x4000 16 | _MEM_RELEASE = 0x8000 17 | 18 | _PAGE_READWRITE = 0x0004 19 | _PAGE_NOACCESS = 0x0001 20 | ) 21 | 22 | const pageSizeLog = 16 23 | 24 | var ( 25 | modkernel32 = syscall.NewLazyDLL("kernel32.dll") 26 | osPageMask = osPageSize - 1 27 | osPageSize = os.Getpagesize() 28 | procVirtualAlloc = modkernel32.NewProc("VirtualAlloc") 29 | procVirtualFree = modkernel32.NewProc("VirtualFree") 30 | ) 31 | 32 | // pageSize aligned. 33 | func mmap(size int) (uintptr, int, error) { 34 | size = roundup(size, pageSize) 35 | addr, _, err := procVirtualAlloc.Call(0, uintptr(size), _MEM_COMMIT|_MEM_RESERVE, _PAGE_READWRITE) 36 | if err.(syscall.Errno) != 0 || addr == 0 { 37 | return addr, size, err 38 | } 39 | return addr, size, nil 40 | } 41 | 42 | func unmap(addr uintptr, size int) error { 43 | r, _, err := procVirtualFree.Call(addr, 0, _MEM_RELEASE) 44 | if r == 0 { 45 | return err 46 | } 47 | 48 | return nil 49 | } 50 | -------------------------------------------------------------------------------- /lib/others/memory/trace.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Memory Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package memory // import "modernc.org/memory" 6 | 7 | const trace = false 8 | -------------------------------------------------------------------------------- /lib/others/prof/profiler.go: -------------------------------------------------------------------------------- 1 | package prof 2 | 3 | import ( 4 | "sync" 5 | "time" 6 | "fmt" 7 | "sort" 8 | ) 9 | 10 | var ( 11 | ioprof sync.Once 12 | chpStart map[string]int64 13 | chpTotal map[string]int64 14 | start int64 15 | 16 | ProfilerDisabled bool = true 17 | ) 18 | 19 | type oneval struct { 20 | name string 21 | tim int64 22 | } 23 | type sortif struct { 24 | val []oneval 25 | } 26 | 27 | func (i sortif) Len() int { 28 | return len(i.val) 29 | } 30 | 31 | func (x sortif) Less(i, j int) bool { 32 | return x.val[i].tim > x.val[j].tim 33 | } 34 | 35 | func (x sortif) Swap(i, j int) { 36 | x.val[i], x.val[j] = x.val[j], x.val[i] 37 | } 38 | 39 | 40 | func Sta(name string) { 41 | if ProfilerDisabled { 42 | return 43 | } 44 | _, ok := chpStart[name] 45 | if ok { 46 | panic(name+" already started") 47 | } 48 | chpStart[name] = time.Now().UnixNano() 49 | } 50 | 51 | func Sto(name string) { 52 | if ProfilerDisabled { 53 | return 54 | } 55 | tim, ok := chpStart[name] 56 | if !ok { 57 | panic(name+" not started") 58 | } 59 | delete(chpStart, name) 60 | del := time.Now().UnixNano()-tim 61 | tim, ok = chpTotal[name] 62 | if ok { 63 | chpTotal[name] = tim+del 64 | } else { 65 | chpTotal[name] = del 66 | } 67 | } 68 | 69 | func Stop() { 70 | ProfilerDisabled = true 71 | stop := time.Now().UnixNano() - start 72 | 73 | if stop == 0 { 74 | fmt.Println(len(chpTotal), "checkpoints but in zero time") 75 | return 76 | } 77 | 78 | var mk sortif 79 | mk.val = make([]oneval, len(chpTotal)) 80 | i := 0 81 | for k, v := range chpTotal { 82 | mk.val[i].name = k 83 | mk.val[i].tim = v 84 | i++ 85 | } 86 | sort.Sort(mk) 87 | 88 | for i := range mk.val { 89 | fmt.Printf("%40s : %8.3fs = %3d%%\n", mk.val[i].name, 90 | float64(mk.val[i].tim)/1e9, 100*mk.val[i].tim/stop) 91 | } 92 | } 93 | 94 | func Start() { 95 | chpStart = make(map[string]int64) 96 | chpTotal = make(map[string]int64) 97 | start = time.Now().UnixNano() 98 | ProfilerDisabled = false 99 | } 100 | -------------------------------------------------------------------------------- /lib/others/qdb/README.md: -------------------------------------------------------------------------------- 1 | From Gocoin version 1.9.0 it is no longer used for UTXO db. 2 | Now it is only used for maintaining peers database. 3 | -------------------------------------------------------------------------------- /lib/others/qdb/db_disk.go: -------------------------------------------------------------------------------- 1 | // Copyright 2009 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Qdb is a fast persistent storage database. 7 | 8 | The records are binary blobs that can have a variable length, up to 4GB. 9 | 10 | The key must be a unique 64-bit value, most likely a hash of the actual key. 11 | 12 | They data is stored on a disk, in a folder specified during the call to NewDB(). 13 | There are can be three possible files in that folder 14 | * qdb.0, qdb.1 - these files store a compact version of the entire database 15 | * qdb.log - this one stores the changes since the most recent qdb.0 or qdb.1 16 | 17 | */ 18 | package qdb 19 | 20 | import ( 21 | "os" 22 | "io" 23 | "fmt" 24 | "strconv" 25 | "path/filepath" 26 | "encoding/binary" 27 | ) 28 | 29 | 30 | func (db *DB) seq2fn(seq uint32) string { 31 | return fmt.Sprintf("%s%08x.dat", db.Dir, seq) 32 | } 33 | 34 | func (db *DB) checklogfile() { 35 | // If could not open, create it 36 | if db.LogFile == nil { 37 | fn := db.seq2fn(db.DataSeq) 38 | db.LogFile, _ = os.Create(fn) 39 | binary.Write(db.LogFile, binary.LittleEndian, uint32(db.DataSeq)) 40 | db.LastValidLogPos = 4 41 | } 42 | } 43 | 44 | 45 | // load record from disk, if not loaded yet 46 | func (db *DB) loadrec(idx *oneIdx) { 47 | if idx.data == nil { 48 | var f *os.File 49 | if f, _ = db.DatFiles[idx.DataSeq]; f==nil { 50 | fn := db.seq2fn(idx.DataSeq) 51 | f, _ = os.Open(fn) 52 | if f==nil { 53 | println("file", fn, "not found") 54 | os.Exit(1) 55 | } 56 | db.DatFiles[idx.DataSeq] = f 57 | } 58 | idx.LoadData(f) 59 | } 60 | } 61 | 62 | // add record at the end of the log 63 | func (db *DB) addtolog(f io.Writer, key KeyType, val []byte) (fpos int64) { 64 | if f==nil { 65 | db.checklogfile() 66 | db.LogFile.Seek(db.LastValidLogPos, os.SEEK_SET) 67 | f = db.LogFile 68 | } 69 | 70 | fpos = db.LastValidLogPos 71 | f.Write(val) 72 | db.LastValidLogPos += int64(len(val)) // 4 bytes for CRC 73 | 74 | return 75 | } 76 | 77 | // add record at the end of the log 78 | func (db *DB) cleanupold(used map[uint32]bool) { 79 | filepath.Walk(db.Dir, func(path string, info os.FileInfo, err error) error { 80 | fn := info.Name() 81 | if len(fn)==12 && fn[8:12]==".dat" { 82 | v, er := strconv.ParseUint(fn[:8], 16, 32) 83 | if er == nil && uint32(v)!=db.DataSeq { 84 | if _, ok := used[uint32(v)]; !ok { 85 | //println("deleting", v, path) 86 | if f, _ := db.DatFiles[uint32(v)]; f!=nil { 87 | f.Close() 88 | delete(db.DatFiles, uint32(v)) 89 | } 90 | os.Remove(path) 91 | } 92 | } 93 | } 94 | return nil 95 | }) 96 | } 97 | -------------------------------------------------------------------------------- /lib/others/qdb/membind.go: -------------------------------------------------------------------------------- 1 | package qdb 2 | 3 | import ( 4 | "os" 5 | "unsafe" 6 | "reflect" 7 | "sync/atomic" 8 | ) 9 | 10 | var ( 11 | membind_use_wrapper bool 12 | _heap_alloc func(le uint32) data_ptr_t 13 | _heap_free func(ptr data_ptr_t) 14 | _heap_store func(v []byte) data_ptr_t 15 | ) 16 | 17 | 18 | type data_ptr_t unsafe.Pointer 19 | 20 | func (v *oneIdx) FreeData() { 21 | if v.data==nil { 22 | return 23 | } 24 | if membind_use_wrapper { 25 | _heap_free(v.data) 26 | atomic.AddInt64(&ExtraMemoryConsumed, -int64(v.datlen)) 27 | atomic.AddInt64(&ExtraMemoryAllocCnt, -1) 28 | } 29 | v.data = nil 30 | } 31 | 32 | func (v *oneIdx) Slice() (res []byte) { 33 | if membind_use_wrapper { 34 | res = *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data:uintptr(v.data), Len:int(v.datlen), Cap:int(v.datlen)})) 35 | } else { 36 | res = *(*[]byte)(v.data) 37 | } 38 | return 39 | } 40 | 41 | func newIdx(v []byte, f uint32) (r *oneIdx) { 42 | r = new(oneIdx) 43 | r.datlen = uint32(len(v)) 44 | r.SetData(v) 45 | r.flags = f 46 | return 47 | } 48 | 49 | func (r *oneIdx) SetData(v []byte) { 50 | if membind_use_wrapper { 51 | r.data = _heap_store(v) 52 | atomic.AddInt64(&ExtraMemoryConsumed, int64(r.datlen)) 53 | atomic.AddInt64(&ExtraMemoryAllocCnt, 1) 54 | } else { 55 | r.data = data_ptr_t(&v) 56 | } 57 | } 58 | 59 | func (v *oneIdx) LoadData(f *os.File) { 60 | if membind_use_wrapper { 61 | v.data = _heap_alloc(v.datlen) 62 | atomic.AddInt64(&ExtraMemoryConsumed, int64(v.datlen)) 63 | atomic.AddInt64(&ExtraMemoryAllocCnt, 1) 64 | f.Seek(int64(v.datpos), os.SEEK_SET) 65 | f.Read(*(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data:uintptr(v.data), Len:int(v.datlen), Cap:int(v.datlen)}))) 66 | } else { 67 | ptr := make([]byte, int(v.datlen)) 68 | v.data = data_ptr_t(&ptr) 69 | f.Seek(int64(v.datpos), os.SEEK_SET) 70 | f.Read(ptr) 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/others/qdb/os_membinds/README.md: -------------------------------------------------------------------------------- 1 | Since currently qdb is only used for peers management, 2 | using the membinds has a little effect and thertefore 3 | this functionality has been disabled. 4 | 5 | If you want to switch OS memory biding on, just copy 6 | all go files from this folder one level up. 7 | -------------------------------------------------------------------------------- /lib/others/qdb/os_membinds/membind_linux.go: -------------------------------------------------------------------------------- 1 | // +build linux 2 | 3 | /* 4 | If this file does not build and you don't know what to do, simply delete it and rebuild. 5 | */ 6 | 7 | package qdb 8 | 9 | /* 10 | #include 11 | #include 12 | 13 | static void *alloc_ptr(void *c, unsigned long l) { 14 | void *ptr = malloc(l); 15 | memcpy(ptr, c, l); 16 | return ptr; 17 | } 18 | 19 | static void *my_alloc(unsigned long l) { 20 | return malloc(l); 21 | } 22 | 23 | */ 24 | import "C" 25 | 26 | import ( 27 | "unsafe" 28 | ) 29 | 30 | 31 | func gcc_HeapAlloc(le uint32) data_ptr_t { 32 | return data_ptr_t(C.my_alloc(C.ulong(le))) 33 | } 34 | 35 | func gcc_HeapFree(ptr data_ptr_t) { 36 | C.free(unsafe.Pointer(ptr)) 37 | } 38 | 39 | func gcc_AllocPtr(v []byte) data_ptr_t { 40 | ptr := unsafe.Pointer(&v[0]) // see https://github.com/golang/go/issues/15172 41 | return data_ptr_t(C.alloc_ptr(ptr, C.ulong(len(v)))) 42 | } 43 | 44 | func init() { 45 | if membind_use_wrapper { 46 | panic("Another wrapper already initialized") 47 | } 48 | println("Using malloc() qdb memory bindings") 49 | _heap_alloc = gcc_HeapAlloc 50 | _heap_free = gcc_HeapFree 51 | _heap_store = gcc_AllocPtr 52 | membind_use_wrapper = true 53 | } 54 | -------------------------------------------------------------------------------- /lib/others/qdb/os_membinds/membind_windows.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | package qdb 4 | 5 | import ( 6 | "unsafe" 7 | "reflect" 8 | "syscall" 9 | ) 10 | 11 | var ( 12 | funcGlobalAlloc *syscall.Proc 13 | funcGlobalFree *syscall.Proc 14 | ) 15 | 16 | func win_HeapAlloc(le uint32) data_ptr_t { 17 | ptr, _, _ := funcGlobalAlloc.Call(0, uintptr(le)) 18 | return data_ptr_t(ptr) 19 | } 20 | 21 | func win_HeapFree(ptr data_ptr_t) { 22 | funcGlobalFree.Call(uintptr(ptr)) 23 | } 24 | 25 | func win_AllocPtr(v []byte) data_ptr_t { 26 | ptr := win_HeapAlloc(uint32(len(v))) 27 | sl := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data:uintptr(ptr), Len:int(len(v)), Cap:int(len(v))})) 28 | copy(sl, v) 29 | return ptr 30 | } 31 | 32 | 33 | func init() { 34 | if membind_use_wrapper { 35 | return 36 | } 37 | dll, er := syscall.LoadDLL("kernel32.dll") 38 | if er!=nil { 39 | return 40 | } 41 | funcGlobalAlloc, _ = dll.FindProc("GlobalAlloc") 42 | funcGlobalFree, _ = dll.FindProc("GlobalFree") 43 | if funcGlobalAlloc==nil || funcGlobalFree==nil { 44 | return 45 | } 46 | println("Using kernel32.dll for qdb memory bindings") 47 | _heap_alloc = win_HeapAlloc 48 | _heap_free = win_HeapFree 49 | _heap_store = win_AllocPtr 50 | membind_use_wrapper = true 51 | } 52 | -------------------------------------------------------------------------------- /lib/others/qdb/stats.go: -------------------------------------------------------------------------------- 1 | package qdb 2 | 3 | import ( 4 | "fmt" 5 | "sort" 6 | ) 7 | 8 | func (db *DB) cnt(k string) { 9 | db.cntadd(k, 1) 10 | } 11 | 12 | func (db *DB) cntadd(k string, val uint64) { 13 | db.counter_mutex.Lock() 14 | db.counter[k] += val 15 | db.counter_mutex.Unlock() 16 | } 17 | 18 | func (db *DB) GetStats() (s string) { 19 | db.counter_mutex.Lock() 20 | ck := make([]string, len(db.counter)) 21 | idx := 0 22 | for k, _ := range db.counter { 23 | ck[idx] = k 24 | idx++ 25 | } 26 | sort.Strings(ck) 27 | 28 | for i := range ck { 29 | k := ck[i] 30 | v := db.counter[k] 31 | if s != "" { 32 | s += ", " 33 | } 34 | s += fmt.Sprint(k, "=", v) 35 | } 36 | db.counter_mutex.Unlock() 37 | return s 38 | } 39 | -------------------------------------------------------------------------------- /lib/others/ripemd160/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /lib/others/ripemd160/ripemd160_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2010 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package ripemd160 6 | 7 | // Test vectors are from: 8 | // http://homes.esat.kuleuven.be/~bosselae/ripemd160.html 9 | 10 | import ( 11 | "fmt" 12 | "io" 13 | "testing" 14 | ) 15 | 16 | type mdTest struct { 17 | out string 18 | in string 19 | } 20 | 21 | var vectors = [...]mdTest{ 22 | {"9c1185a5c5e9fc54612808977ee8f548b2258d31", ""}, 23 | {"0bdc9d2d256b3ee9daae347be6f4dc835a467ffe", "a"}, 24 | {"8eb208f7e05d987a9b044a8e98c6b087f15a0bfc", "abc"}, 25 | {"5d0689ef49d2fae572b881b123a85ffa21595f36", "message digest"}, 26 | {"f71c27109c692c1b56bbdceb5b9d2865b3708dbc", "abcdefghijklmnopqrstuvwxyz"}, 27 | {"12a053384a9c0c88e405a06c27dcf49ada62eb2b", "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"}, 28 | {"b0e20b6e3116640286ed3a87a5713079b21f5189", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"}, 29 | {"9b752e45573d4b39f4dbd3323cab82bf63326bfb", "12345678901234567890123456789012345678901234567890123456789012345678901234567890"}, 30 | } 31 | 32 | func TestVectors(t *testing.T) { 33 | for i := 0; i < len(vectors); i++ { 34 | tv := vectors[i] 35 | md := New() 36 | for j := 0; j < 3; j++ { 37 | if j < 2 { 38 | io.WriteString(md, tv.in) 39 | } else { 40 | io.WriteString(md, tv.in[0:len(tv.in)/2]) 41 | md.Sum(nil) 42 | io.WriteString(md, tv.in[len(tv.in)/2:]) 43 | } 44 | s := fmt.Sprintf("%x", md.Sum(nil)) 45 | if s != tv.out { 46 | t.Fatalf("RIPEMD-160[%d](%s) = %s, expected %s", j, tv.in, s, tv.out) 47 | } 48 | md.Reset() 49 | } 50 | } 51 | } 52 | 53 | func millionA() string { 54 | md := New() 55 | for i := 0; i < 100000; i++ { 56 | io.WriteString(md, "aaaaaaaaaa") 57 | } 58 | return fmt.Sprintf("%x", md.Sum(nil)) 59 | } 60 | 61 | func TestMillionA(t *testing.T) { 62 | const out = "52783243c1697bdbe16d37f97f68f08325dc1528" 63 | if s := millionA(); s != out { 64 | t.Fatalf("RIPEMD-160 (1 million 'a') = %s, expected %s", s, out) 65 | } 66 | } 67 | 68 | func BenchmarkMillionA(b *testing.B) { 69 | for i := 0; i < b.N; i++ { 70 | millionA() 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /lib/others/scrypt/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009 The Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /lib/others/scrypt/README.md: -------------------------------------------------------------------------------- 1 | Package scrypt originated from "golang.org/x/crypto/scrypt" 2 | Package pbkdf2 originated from "golang.org/x/crypto/pbkdf2" 3 | 4 | Shipped with Gocoin source code for security and convenience. 5 | -------------------------------------------------------------------------------- /lib/others/scrypt/pbkdf2/pbkdf2.go: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | Package pbkdf2 implements the key derivation function PBKDF2 as defined in RFC 7 | 2898 / PKCS #5 v2.0. 8 | 9 | A key derivation function is useful when encrypting data based on a password 10 | or any other not-fully-random data. It uses a pseudorandom function to derive 11 | a secure encryption key based on the password. 12 | 13 | While v2.0 of the standard defines only one pseudorandom function to use, 14 | HMAC-SHA1, the drafted v2.1 specification allows use of all five FIPS Approved 15 | Hash Functions SHA-1, SHA-224, SHA-256, SHA-384 and SHA-512 for HMAC. To 16 | choose, you can pass the `New` functions from the different SHA packages to 17 | pbkdf2.Key. 18 | */ 19 | package pbkdf2 // import "github.com/piotrnar/gocoin/lib/others/scrypt" 20 | 21 | import ( 22 | "crypto/hmac" 23 | "hash" 24 | ) 25 | 26 | // Key derives a key from the password, salt and iteration count, returning a 27 | // []byte of length keylen that can be used as cryptographic key. The key is 28 | // derived based on the method described as PBKDF2 with the HMAC variant using 29 | // the supplied hash function. 30 | // 31 | // For example, to use a HMAC-SHA-1 based PBKDF2 key derivation function, you 32 | // can get a derived key for e.g. AES-256 (which needs a 32-byte key) by 33 | // doing: 34 | // 35 | // dk := pbkdf2.Key([]byte("some password"), salt, 4096, 32, sha1.New) 36 | // 37 | // Remember to get a good random salt. At least 8 bytes is recommended by the 38 | // RFC. 39 | // 40 | // Using a higher iteration count will increase the cost of an exhaustive 41 | // search but will also make derivation proportionally slower. 42 | func Key(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte { 43 | prf := hmac.New(h, password) 44 | hashLen := prf.Size() 45 | numBlocks := (keyLen + hashLen - 1) / hashLen 46 | 47 | var buf [4]byte 48 | dk := make([]byte, 0, numBlocks*hashLen) 49 | U := make([]byte, hashLen) 50 | for block := 1; block <= numBlocks; block++ { 51 | // N.B.: || means concatenation, ^ means XOR 52 | // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter 53 | // U_1 = PRF(password, salt || uint(i)) 54 | prf.Reset() 55 | prf.Write(salt) 56 | buf[0] = byte(block >> 24) 57 | buf[1] = byte(block >> 16) 58 | buf[2] = byte(block >> 8) 59 | buf[3] = byte(block) 60 | prf.Write(buf[:4]) 61 | dk = prf.Sum(dk) 62 | T := dk[len(dk)-hashLen:] 63 | copy(U, T) 64 | 65 | // U_n = PRF(password, U_(n-1)) 66 | for n := 2; n <= iter; n++ { 67 | prf.Reset() 68 | prf.Write(U) 69 | U = U[:0] 70 | U = prf.Sum(U) 71 | for x := range U { 72 | T[x] ^= U[x] 73 | } 74 | } 75 | } 76 | return dk[:keyLen] 77 | } 78 | -------------------------------------------------------------------------------- /lib/others/siphash/.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - 1.4 5 | - 1.5 6 | - 1.7 7 | - tip 8 | -------------------------------------------------------------------------------- /lib/others/siphash/README.md: -------------------------------------------------------------------------------- 1 | SipHash (Go) 2 | ============ 3 | 4 | [![Build Status](https://travis-ci.org/dchest/siphash.svg)](https://travis-ci.org/dchest/siphash) 5 | 6 | Go implementation of SipHash-2-4, a fast short-input PRF created by 7 | Jean-Philippe Aumasson and Daniel J. Bernstein (http://131002.net/siphash/). 8 | 9 | 10 | ## Installation 11 | 12 | $ go get github.com/dchest/siphash 13 | 14 | ## Usage 15 | 16 | import "github.com/dchest/siphash" 17 | 18 | There are two ways to use this package. 19 | The slower one is to use the standard hash.Hash64 interface: 20 | 21 | h := siphash.New(key) 22 | h.Write([]byte("Hello")) 23 | sum := h.Sum(nil) // returns 8-byte []byte 24 | 25 | or 26 | 27 | sum64 := h.Sum64() // returns uint64 28 | 29 | The faster one is to use Hash() function, which takes two uint64 parts of 30 | 16-byte key and a byte slice, and returns uint64 hash: 31 | 32 | sum64 := siphash.Hash(key0, key1, []byte("Hello")) 33 | 34 | The keys and output are little-endian. 35 | 36 | 37 | ## Functions 38 | 39 | ### func Hash(k0, k1 uint64, p []byte) uint64 40 | 41 | Hash returns the 64-bit SipHash-2-4 of the given byte slice with two 42 | 64-bit parts of 128-bit key: k0 and k1. 43 | 44 | ### func Hash128(k0, k1 uint64, p []byte) (uint64, uint64) 45 | 46 | Hash128 returns the 128-bit SipHash-2-4 of the given byte slice with two 47 | 64-bit parts of 128-bit key: k0 and k1. 48 | 49 | Note that 128-bit SipHash is considered experimental by SipHash authors at this time. 50 | 51 | ### func New(key []byte) hash.Hash64 52 | 53 | New returns a new hash.Hash64 computing SipHash-2-4 with 16-byte key. 54 | 55 | ### func New128(key []byte) hash.Hash 56 | 57 | New128 returns a new hash.Hash computing SipHash-2-4 with 16-byte key and 16-byte output. 58 | 59 | Note that 16-byte output is considered experimental by SipHash authors at this time. 60 | 61 | 62 | ## Public domain dedication 63 | 64 | Written by Dmitry Chestnykh and Damian Gryski. 65 | 66 | To the extent possible under law, the authors have dedicated all copyright 67 | and related and neighboring rights to this software to the public domain 68 | worldwide. This software is distributed without any warranty. 69 | http://creativecommons.org/publicdomain/zero/1.0/ 70 | -------------------------------------------------------------------------------- /lib/others/siphash/blocks.go: -------------------------------------------------------------------------------- 1 | // +build !arm,!amd64 appengine gccgo 2 | 3 | package siphash 4 | 5 | func once(d *digest) { 6 | blocks(d, d.x[:]) 7 | } 8 | 9 | func finalize(d *digest) uint64 { 10 | d0 := *d 11 | once(&d0) 12 | 13 | v0, v1, v2, v3 := d0.v0, d0.v1, d0.v2, d0.v3 14 | v2 ^= 0xff 15 | 16 | // Round 1. 17 | v0 += v1 18 | v1 = v1<<13 | v1>>(64-13) 19 | v1 ^= v0 20 | v0 = v0<<32 | v0>>(64-32) 21 | 22 | v2 += v3 23 | v3 = v3<<16 | v3>>(64-16) 24 | v3 ^= v2 25 | 26 | v0 += v3 27 | v3 = v3<<21 | v3>>(64-21) 28 | v3 ^= v0 29 | 30 | v2 += v1 31 | v1 = v1<<17 | v1>>(64-17) 32 | v1 ^= v2 33 | v2 = v2<<32 | v2>>(64-32) 34 | 35 | // Round 2. 36 | v0 += v1 37 | v1 = v1<<13 | v1>>(64-13) 38 | v1 ^= v0 39 | v0 = v0<<32 | v0>>(64-32) 40 | 41 | v2 += v3 42 | v3 = v3<<16 | v3>>(64-16) 43 | v3 ^= v2 44 | 45 | v0 += v3 46 | v3 = v3<<21 | v3>>(64-21) 47 | v3 ^= v0 48 | 49 | v2 += v1 50 | v1 = v1<<17 | v1>>(64-17) 51 | v1 ^= v2 52 | v2 = v2<<32 | v2>>(64-32) 53 | 54 | // Round 3. 55 | v0 += v1 56 | v1 = v1<<13 | v1>>(64-13) 57 | v1 ^= v0 58 | v0 = v0<<32 | v0>>(64-32) 59 | 60 | v2 += v3 61 | v3 = v3<<16 | v3>>(64-16) 62 | v3 ^= v2 63 | 64 | v0 += v3 65 | v3 = v3<<21 | v3>>(64-21) 66 | v3 ^= v0 67 | 68 | v2 += v1 69 | v1 = v1<<17 | v1>>(64-17) 70 | v1 ^= v2 71 | v2 = v2<<32 | v2>>(64-32) 72 | 73 | // Round 4. 74 | v0 += v1 75 | v1 = v1<<13 | v1>>(64-13) 76 | v1 ^= v0 77 | v0 = v0<<32 | v0>>(64-32) 78 | 79 | v2 += v3 80 | v3 = v3<<16 | v3>>(64-16) 81 | v3 ^= v2 82 | 83 | v0 += v3 84 | v3 = v3<<21 | v3>>(64-21) 85 | v3 ^= v0 86 | 87 | v2 += v1 88 | v1 = v1<<17 | v1>>(64-17) 89 | v1 ^= v2 90 | v2 = v2<<32 | v2>>(64-32) 91 | 92 | return v0 ^ v1 ^ v2 ^ v3 93 | } 94 | 95 | func blocks(d *digest, p []uint8) { 96 | v0, v1, v2, v3 := d.v0, d.v1, d.v2, d.v3 97 | 98 | for len(p) >= BlockSize { 99 | m := uint64(p[0]) | uint64(p[1])<<8 | uint64(p[2])<<16 | uint64(p[3])<<24 | 100 | uint64(p[4])<<32 | uint64(p[5])<<40 | uint64(p[6])<<48 | uint64(p[7])<<56 101 | 102 | v3 ^= m 103 | 104 | // Round 1. 105 | v0 += v1 106 | v1 = v1<<13 | v1>>(64-13) 107 | v1 ^= v0 108 | v0 = v0<<32 | v0>>(64-32) 109 | 110 | v2 += v3 111 | v3 = v3<<16 | v3>>(64-16) 112 | v3 ^= v2 113 | 114 | v0 += v3 115 | v3 = v3<<21 | v3>>(64-21) 116 | v3 ^= v0 117 | 118 | v2 += v1 119 | v1 = v1<<17 | v1>>(64-17) 120 | v1 ^= v2 121 | v2 = v2<<32 | v2>>(64-32) 122 | 123 | // Round 2. 124 | v0 += v1 125 | v1 = v1<<13 | v1>>(64-13) 126 | v1 ^= v0 127 | v0 = v0<<32 | v0>>(64-32) 128 | 129 | v2 += v3 130 | v3 = v3<<16 | v3>>(64-16) 131 | v3 ^= v2 132 | 133 | v0 += v3 134 | v3 = v3<<21 | v3>>(64-21) 135 | v3 ^= v0 136 | 137 | v2 += v1 138 | v1 = v1<<17 | v1>>(64-17) 139 | v1 ^= v2 140 | v2 = v2<<32 | v2>>(64-32) 141 | 142 | v0 ^= m 143 | 144 | p = p[BlockSize:] 145 | } 146 | 147 | d.v0, d.v1, d.v2, d.v3 = v0, v1, v2, v3 148 | } 149 | -------------------------------------------------------------------------------- /lib/others/siphash/blocks_amd64.s: -------------------------------------------------------------------------------- 1 | // +build amd64,!appengine,!gccgo 2 | 3 | #define ROUND(v0, v1, v2, v3) \ 4 | ADDQ v1, v0; \ 5 | RORQ $51, v1; \ 6 | ADDQ v3, v2; \ 7 | XORQ v0, v1; \ 8 | RORQ $48, v3; \ 9 | RORQ $32, v0; \ 10 | XORQ v2, v3; \ 11 | ADDQ v1, v2; \ 12 | ADDQ v3, v0; \ 13 | RORQ $43, v3; \ 14 | RORQ $47, v1; \ 15 | XORQ v0, v3; \ 16 | XORQ v2, v1; \ 17 | RORQ $32, v2 18 | 19 | // blocks(d *digest, data []uint8) 20 | TEXT ·blocks(SB),4,$0-32 21 | MOVQ d+0(FP), BX 22 | MOVQ 0(BX), R9 // R9 = v0 23 | MOVQ 8(BX), R10 // R10 = v1 24 | MOVQ 16(BX), R11 // R11 = v2 25 | MOVQ 24(BX), R12 // R12 = v3 26 | MOVQ p_base+8(FP), DI // DI = *uint64 27 | MOVQ p_len+16(FP), SI // SI = nblocks 28 | XORL DX, DX // DX = index (0) 29 | SHRQ $3, SI // SI /= 8 30 | body: 31 | CMPQ DX, SI 32 | JGE end 33 | MOVQ 0(DI)(DX*8), CX // CX = m 34 | XORQ CX, R12 35 | ROUND(R9, R10, R11, R12) 36 | ROUND(R9, R10, R11, R12) 37 | XORQ CX, R9 38 | ADDQ $1, DX 39 | JMP body 40 | end: 41 | MOVQ R9, 0(BX) 42 | MOVQ R10, 8(BX) 43 | MOVQ R11, 16(BX) 44 | MOVQ R12, 24(BX) 45 | RET 46 | 47 | // once(d *digest) 48 | TEXT ·once(SB),4,$0-8 49 | MOVQ d+0(FP), BX 50 | MOVQ 0(BX), R9 // R9 = v0 51 | MOVQ 8(BX), R10 // R10 = v1 52 | MOVQ 16(BX), R11 // R11 = v2 53 | MOVQ 24(BX), R12 // R12 = v3 54 | MOVQ 48(BX), CX // CX = d.x[:] 55 | XORQ CX, R12 56 | ROUND(R9, R10, R11, R12) 57 | ROUND(R9, R10, R11, R12) 58 | XORQ CX, R9 59 | MOVQ R9, 0(BX) 60 | MOVQ R10, 8(BX) 61 | MOVQ R11, 16(BX) 62 | MOVQ R12, 24(BX) 63 | RET 64 | 65 | // finalize(d *digest) uint64 66 | TEXT ·finalize(SB),4,$0-16 67 | MOVQ d+0(FP), BX 68 | MOVQ 0(BX), R9 // R9 = v0 69 | MOVQ 8(BX), R10 // R10 = v1 70 | MOVQ 16(BX), R11 // R11 = v2 71 | MOVQ 24(BX), R12 // R12 = v3 72 | MOVQ 48(BX), CX // CX = d.x[:] 73 | XORQ CX, R12 74 | ROUND(R9, R10, R11, R12) 75 | ROUND(R9, R10, R11, R12) 76 | XORQ CX, R9 77 | NOTB R11 78 | ROUND(R9, R10, R11, R12) 79 | ROUND(R9, R10, R11, R12) 80 | ROUND(R9, R10, R11, R12) 81 | ROUND(R9, R10, R11, R12) 82 | XORQ R12, R11 83 | XORQ R10, R9 84 | XORQ R11, R9 85 | MOVQ R9, ret+8(FP) 86 | RET 87 | -------------------------------------------------------------------------------- /lib/others/siphash/hash_asm.go: -------------------------------------------------------------------------------- 1 | // +build arm amd64,!appengine,!gccgo 2 | 3 | // Written in 2012 by Dmitry Chestnykh. 4 | // 5 | // To the extent possible under law, the author have dedicated all copyright 6 | // and related and neighboring rights to this software to the public domain 7 | // worldwide. This software is distributed without any warranty. 8 | // http://creativecommons.org/publicdomain/zero/1.0/ 9 | 10 | // This file contains a function definition for use with assembly implementations of Hash() 11 | 12 | package siphash 13 | 14 | //go:noescape 15 | 16 | // Hash returns the 64-bit SipHash-2-4 of the given byte slice with two 64-bit 17 | // parts of 128-bit key: k0 and k1. 18 | func Hash(k0, k1 uint64, b []byte) uint64 19 | 20 | //go:noescape 21 | 22 | // Hash128 returns the 128-bit SipHash-2-4 of the given byte slice with two 23 | // 64-bit parts of 128-bit key: k0 and k1. 24 | func Hash128(k0, k1 uint64, b []byte) (uint64, uint64) 25 | 26 | //go:noescape 27 | func blocks(d *digest, p []uint8) 28 | 29 | //go:noescape 30 | func finalize(d *digest) uint64 31 | 32 | //go:noescape 33 | func once(d *digest) 34 | -------------------------------------------------------------------------------- /lib/others/snappy/AUTHORS: -------------------------------------------------------------------------------- 1 | # This is the official list of Snappy-Go authors for copyright purposes. 2 | # This file is distinct from the CONTRIBUTORS files. 3 | # See the latter for an explanation. 4 | 5 | # Names should be added to this file as 6 | # Name or Organization 7 | # The email address is not required for organizations. 8 | 9 | # Please keep the list sorted. 10 | 11 | Damian Gryski 12 | Google Inc. 13 | Jan Mercl <0xjnml@gmail.com> 14 | Rodolfo Carvalho 15 | Sebastien Binet 16 | -------------------------------------------------------------------------------- /lib/others/snappy/CONTRIBUTORS: -------------------------------------------------------------------------------- 1 | # This is the official list of people who can contribute 2 | # (and typically have contributed) code to the Snappy-Go repository. 3 | # The AUTHORS file lists the copyright holders; this file 4 | # lists people. For example, Google employees are listed here 5 | # but not in AUTHORS, because Google holds the copyright. 6 | # 7 | # The submission process automatically checks to make sure 8 | # that people submitting code are listed in this file (by email address). 9 | # 10 | # Names should be added to this file only after verifying that 11 | # the individual or the individual's organization has agreed to 12 | # the appropriate Contributor License Agreement, found here: 13 | # 14 | # http://code.google.com/legal/individual-cla-v1.0.html 15 | # http://code.google.com/legal/corporate-cla-v1.0.html 16 | # 17 | # The agreement for individuals can be filled out on the web. 18 | # 19 | # When adding J Random Contributor's name to this file, 20 | # either J's name or J's organization's name should be 21 | # added to the AUTHORS file, depending on whether the 22 | # individual or corporate CLA was used. 23 | 24 | # Names should be added to this file like so: 25 | # Name 26 | 27 | # Please keep the list sorted. 28 | 29 | Damian Gryski 30 | Jan Mercl <0xjnml@gmail.com> 31 | Kai Backman 32 | Marc-Antoine Ruel 33 | Nigel Tao 34 | Rob Pike 35 | Rodolfo Carvalho 36 | Russ Cox 37 | Sebastien Binet 38 | -------------------------------------------------------------------------------- /lib/others/snappy/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 The Snappy-Go Authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the 12 | distribution. 13 | * Neither the name of Google Inc. nor the names of its 14 | contributors may be used to endorse or promote products derived from 15 | this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /lib/others/snappy/decode_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Snappy-Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !appengine 6 | // +build gc 7 | // +build !noasm 8 | 9 | package snappy 10 | 11 | // decode has the same semantics as in decode_other.go. 12 | // 13 | //go:noescape 14 | func decode(dst, src []byte) int 15 | -------------------------------------------------------------------------------- /lib/others/snappy/encode_amd64.go: -------------------------------------------------------------------------------- 1 | // Copyright 2016 The Snappy-Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build !appengine 6 | // +build gc 7 | // +build !noasm 8 | 9 | package snappy 10 | 11 | // emitLiteral has the same semantics as in encode_other.go. 12 | // 13 | //go:noescape 14 | func emitLiteral(dst, lit []byte) int 15 | 16 | // emitCopy has the same semantics as in encode_other.go. 17 | // 18 | //go:noescape 19 | func emitCopy(dst []byte, offset, length int) int 20 | 21 | // extendMatch has the same semantics as in encode_other.go. 22 | // 23 | //go:noescape 24 | func extendMatch(src []byte, i, j int) int 25 | 26 | // encodeBlock has the same semantics as in encode_other.go. 27 | // 28 | //go:noescape 29 | func encodeBlock(dst, src []byte) (d int) 30 | -------------------------------------------------------------------------------- /lib/others/sys/atomic.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | "fmt" 5 | "sync/atomic" 6 | ) 7 | 8 | type SyncBool struct { 9 | val int32 10 | } 11 | 12 | func (b *SyncBool) Get() bool { 13 | return atomic.LoadInt32(&b.val) != 0 14 | } 15 | 16 | func (b *SyncBool) Set() { 17 | atomic.StoreInt32(&b.val, 1) 18 | } 19 | 20 | func (b *SyncBool) Clr() { 21 | atomic.StoreInt32(&b.val, 0) 22 | } 23 | 24 | func (b *SyncBool) MarshalText() (text []byte, err error) { 25 | return []byte(fmt.Sprint(b.Get())), nil 26 | } 27 | 28 | func (b *SyncBool) Store(val bool) { 29 | if val { 30 | b.Set() 31 | } else { 32 | b.Clr() 33 | } 34 | } 35 | 36 | 37 | type SyncInt struct { 38 | val int64 39 | } 40 | 41 | func (b *SyncInt) Get() int { 42 | return int(atomic.LoadInt64(&b.val)) 43 | } 44 | 45 | func (b *SyncInt) Store(val int) { 46 | atomic.StoreInt64(&b.val, int64(val)) 47 | } 48 | 49 | func (b *SyncInt) Add(val int) { 50 | atomic.AddInt64(&b.val, int64(val)) 51 | } 52 | 53 | func (b *SyncInt) MarshalText() (text []byte, err error) { 54 | return []byte(fmt.Sprint(b.Get())), nil 55 | } 56 | -------------------------------------------------------------------------------- /lib/others/sys/dblock_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package sys 4 | 5 | import ( 6 | "os" 7 | "syscall" 8 | ) 9 | 10 | var ( 11 | DbLockFileName string 12 | DbLockFileHndl *os.File 13 | ) 14 | 15 | func LockDatabaseDir(GocoinHomeDir string) { 16 | os.MkdirAll(GocoinHomeDir, 0770) 17 | DbLockFileName = GocoinHomeDir+".lock" 18 | DbLockFileHndl, _ = os.Open(DbLockFileName) 19 | if DbLockFileHndl==nil { 20 | DbLockFileHndl, _ = os.Create(DbLockFileName) 21 | } 22 | if DbLockFileHndl==nil { 23 | goto error 24 | } 25 | 26 | if e:=syscall.Flock(int(DbLockFileHndl.Fd()), syscall.LOCK_EX|syscall.LOCK_NB); e!=nil { 27 | goto error 28 | } 29 | return 30 | 31 | error: 32 | println("Could not lock the databse folder for writing. Another instance might be running.") 33 | println("If it is not the case, remove this file:", DbLockFileName) 34 | os.Exit(1) 35 | } 36 | 37 | func UnlockDatabaseDir() { 38 | syscall.Flock(int(DbLockFileHndl.Fd()), syscall.LOCK_UN) 39 | DbLockFileHndl.Close() 40 | os.Remove(DbLockFileName) 41 | } 42 | -------------------------------------------------------------------------------- /lib/others/sys/dblock_windows.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | "os" 5 | ) 6 | 7 | var ( 8 | DbLockFileName string 9 | DbLockFileHndl *os.File 10 | ) 11 | 12 | func LockDatabaseDir(GocoinHomeDir string) { 13 | var e error 14 | os.MkdirAll(GocoinHomeDir, 0770) 15 | DbLockFileName = GocoinHomeDir+".lock" 16 | os.Remove(DbLockFileName) 17 | DbLockFileHndl, e = os.OpenFile(DbLockFileName, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0660) 18 | if e != nil { 19 | println(e.Error()) 20 | println("Could not lock the databse folder for writing. Another instance might be running.") 21 | println("Make sure you can delete and recreate file:", DbLockFileName) 22 | os.Exit(1) 23 | } 24 | } 25 | 26 | func UnlockDatabaseDir() { 27 | DbLockFileHndl.Close() 28 | os.Remove(DbLockFileName) 29 | } 30 | -------------------------------------------------------------------------------- /lib/others/sys/dutex.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "sync" 7 | "time" 8 | ) 9 | 10 | type Dutex struct { 11 | ltime time.Time 12 | file string 13 | varstr string 14 | line int 15 | lttot time.Duration 16 | sync.Mutex 17 | mutint sync.Mutex 18 | locked bool 19 | } 20 | 21 | func (d *Dutex) Status() (s string) { 22 | d.mutint.Lock() 23 | if d.locked { 24 | s = "LOCKED from" 25 | } else { 26 | s = "last unlocked in" 27 | } 28 | s += fmt.Sprint(" ", d.file, ":", d.line, " ", time.Since(d.ltime).String(), " ago (", d.lttot.String(), " total) -", d.varstr) 29 | d.mutint.Unlock() 30 | return 31 | } 32 | 33 | func (d *Dutex) fixfile() { 34 | var cnt int 35 | for i := len(d.file) - 1; i > 0; i-- { 36 | if d.file[i] == '/' { 37 | cnt++ 38 | if cnt == 2 { 39 | d.file = d.file[i+1:] 40 | return 41 | } 42 | } 43 | } 44 | } 45 | 46 | func (d *Dutex) SetVar(v string) { 47 | d.mutint.Lock() 48 | d.varstr = v 49 | d.mutint.Unlock() 50 | } 51 | 52 | func (d *Dutex) Lock() { 53 | d.Mutex.Lock() 54 | d.mutint.Lock() 55 | d.locked = true 56 | _, d.file, d.line, _ = runtime.Caller(1) 57 | d.fixfile() 58 | d.ltime = time.Now() 59 | d.mutint.Unlock() 60 | } 61 | 62 | func (d *Dutex) Unlock() { 63 | d.mutint.Lock() 64 | ts := time.Since(d.ltime) 65 | if ts > time.Second { 66 | println(" >>> mutex locked from", d.file, "line", d.line, "took", ts.String(), "to unlock") 67 | } 68 | d.lttot += ts 69 | d.locked = false 70 | _, d.file, d.line, _ = runtime.Caller(1) 71 | d.fixfile() 72 | d.ltime = time.Now() 73 | d.mutint.Unlock() 74 | d.Mutex.Unlock() 75 | } 76 | -------------------------------------------------------------------------------- /lib/others/sys/hidepass_unix.go: -------------------------------------------------------------------------------- 1 | // +build !windows 2 | 3 | package sys 4 | 5 | import ( 6 | "os" 7 | "fmt" 8 | "syscall" 9 | "os/signal" 10 | ) 11 | 12 | var wsta syscall.WaitStatus = 0 13 | 14 | 15 | func enterpassext(b []byte) (n int) { 16 | si := make(chan os.Signal, 10) 17 | br := make(chan bool) 18 | fd := []uintptr{os.Stdout.Fd()} 19 | 20 | signal.Notify(si, syscall.SIGHUP, syscall.SIGINT, syscall.SIGKILL, syscall.SIGQUIT, syscall.SIGTERM) 21 | go sighndl(fd, si, br) 22 | 23 | pid, er := syscall.ForkExec("/bin/stty", []string{"stty", "-echo"}, &syscall.ProcAttr{Dir: "", Files: fd}) 24 | if er == nil { 25 | syscall.Wait4(pid, &wsta, 0, nil) 26 | n = getline(b) 27 | close(br) 28 | echo(fd) 29 | fmt.Println() 30 | } else { 31 | n = getline(b) 32 | } 33 | 34 | return 35 | } 36 | 37 | 38 | func echo(fd []uintptr) { 39 | pid, e := syscall.ForkExec("/bin/stty", []string{"stty", "echo"}, &syscall.ProcAttr{Dir: "", Files: fd}) 40 | if e == nil { 41 | syscall.Wait4(pid, &wsta, 0, nil) 42 | } 43 | } 44 | 45 | 46 | func sighndl(fd []uintptr, signal chan os.Signal, br chan bool) { 47 | select { 48 | case <-signal: 49 | echo(fd) 50 | os.Exit(-1) 51 | case <-br: 52 | } 53 | } 54 | 55 | func init() { 56 | secrespass = enterpassext 57 | } 58 | -------------------------------------------------------------------------------- /lib/others/sys/hidepass_windows.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | ) 7 | 8 | // New method (requires msvcrt.dll): 9 | import ( 10 | "syscall" 11 | ) 12 | 13 | var ( 14 | msvcrt = syscall.NewLazyDLL("msvcrt.dll") 15 | _getch = msvcrt.NewProc("_getch") 16 | ) 17 | 18 | func getch() int { 19 | res, _, _ := syscall.Syscall(_getch.Addr(), 0, 0, 0, 0) 20 | return int(res) 21 | } 22 | 23 | func enterpassext(b []byte) (n int) { 24 | for { 25 | chr := byte(getch()) 26 | if chr==3 { 27 | // Ctrl+C 28 | ClearBuffer(b) 29 | os.Exit(0) 30 | } 31 | if chr==13 || chr==10 { 32 | fmt.Println() 33 | break // Enter 34 | } 35 | if chr=='\b' { 36 | if n>0 { 37 | n-- 38 | b[n] = 0 39 | fmt.Print("\b \b") 40 | } else { 41 | fmt.Print("\007") 42 | } 43 | continue 44 | } 45 | if chr<' ' { 46 | fmt.Print("\007") 47 | fmt.Println("\n", chr) 48 | continue 49 | } 50 | if n==len(b) { 51 | fmt.Print("\007") 52 | continue 53 | } 54 | fmt.Print("*") 55 | b[n] = chr 56 | n++ 57 | } 58 | return 59 | } 60 | 61 | func init() { 62 | er := _getch.Find() 63 | if er != nil { 64 | println(er.Error()) 65 | println("WARNING: Characters will be visible during password input.") 66 | return 67 | } 68 | 69 | secrespass = enterpassext 70 | } 71 | 72 | 73 | /* 74 | Old method (requires mingw): 75 | 76 | #include 77 | // end the comment here when enablign this method 78 | import "C" 79 | 80 | func getch() int { 81 | return int(C._getch()) 82 | } 83 | 84 | */ 85 | -------------------------------------------------------------------------------- /lib/others/sys/ipnet.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | ) 5 | 6 | 7 | // Discard any IP that may refer to a local network 8 | func ValidIp4(ip []byte) bool { 9 | // local host 10 | if ip[0]==0 || ip[0]==127 { 11 | return false 12 | } 13 | 14 | // RFC1918 15 | if ip[0]==10 || ip[0]==192 && ip[1]==168 || ip[0]==172 && ip[1]>=16 && ip[1]<=31 { 16 | return false 17 | } 18 | 19 | //RFC3927 20 | if ip[0]==169 && ip[1]==254 { 21 | return false 22 | } 23 | 24 | return true 25 | } 26 | 27 | 28 | func IsIPBlocked(ip4 []byte) bool { 29 | return false 30 | } 31 | -------------------------------------------------------------------------------- /lib/others/sys/mutexes.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | "fmt" 5 | "runtime" 6 | "sync" 7 | ) 8 | 9 | type Mutex struct { 10 | file string 11 | line int 12 | sync.Mutex 13 | locked bool 14 | } 15 | 16 | func (m *Mutex) Lock() { 17 | m.Mutex.Lock() 18 | m.locked = true 19 | _, m.file, m.line, _ = runtime.Caller(1) 20 | } 21 | 22 | func (m *Mutex) Unlock() { 23 | //_, m.file, m.line, _ = runtime.Caller(1) 24 | m.locked = false 25 | m.Mutex.Unlock() 26 | } 27 | 28 | func (m *Mutex) String() string { 29 | if m.locked { 30 | return fmt.Sprint("lock from ", m.file, ":", m.line) 31 | } 32 | return "unlocked" 33 | //return fmt.Sprint("unlocked in ", m.file, ":", m.line) 34 | } 35 | -------------------------------------------------------------------------------- /lib/others/sys/stuff.go: -------------------------------------------------------------------------------- 1 | package sys 2 | 3 | import ( 4 | "os" 5 | "runtime" 6 | "io/ioutil" 7 | "crypto/rand" 8 | "encoding/hex" 9 | "runtime/debug" 10 | ) 11 | 12 | 13 | 14 | 15 | func BitcoinHome() (res string) { 16 | res = os.Getenv("APPDATA") 17 | if res!="" { 18 | res += "\\Bitcoin\\" 19 | return 20 | } 21 | res = os.Getenv("HOME") 22 | if res!="" { 23 | res += "/.bitcoin/" 24 | } 25 | return 26 | } 27 | 28 | 29 | func is_hex_string(s []byte) (string) { 30 | var res string 31 | for i := range s { 32 | c := byte(s[i]) 33 | if c<='9' && c>='0' || c<='f' && c>='a' || c<='F' && c>='A' { 34 | res += string(c) 35 | } else if c!=' ' && c!='\n' && c!='\r' && c!='\t' { 36 | return "" 37 | } 38 | } 39 | return res 40 | } 41 | 42 | // reads tx from the file or (if there is no such a file) decodes the text 43 | func GetRawData(fn string) (dat []byte) { 44 | d, er := ioutil.ReadFile(fn) 45 | if er == nil { 46 | hexdump := is_hex_string(d) 47 | if len(hexdump)>=2 || (len(hexdump)&1)==1 { 48 | dat, _ = hex.DecodeString(hexdump) 49 | } else { 50 | dat = d 51 | } 52 | } else { 53 | dat, _ = hex.DecodeString(fn) 54 | } 55 | return 56 | } 57 | 58 | 59 | func ClearBuffer(buf []byte) { 60 | rand.Read(buf[:]) 61 | } 62 | 63 | 64 | var secrespass func([]byte) int 65 | 66 | func getline(buf []byte) (n int) { 67 | n, er := os.Stdin.Read(buf[:]) 68 | if er != nil { 69 | ClearBuffer(buf) 70 | return -1 71 | } 72 | for n>0 && buf[n-1]<' ' { 73 | n-- 74 | buf[n] = 0 75 | } 76 | return n 77 | } 78 | 79 | // ReadPassword reads a password from console. 80 | // Returns -1 on error. 81 | func ReadPassword(buf []byte) (n int) { 82 | if secrespass != nil { 83 | return secrespass(buf) 84 | } 85 | return getline(buf) 86 | } 87 | 88 | // MemUsed returns Alloc and Sys (how much memory is used). 89 | func MemUsed() (uint64, uint64) { 90 | var ms runtime.MemStats 91 | runtime.ReadMemStats(&ms) 92 | return ms.Alloc, ms.Sys 93 | } 94 | 95 | // FreeMem runs the GC and frees as much memory as possible. 96 | func FreeMem() { 97 | //runtime.GC() <-- debug.FreeOSMemory() should execute the GC() 98 | debug.FreeOSMemory() 99 | } 100 | -------------------------------------------------------------------------------- /lib/others/utils/fetchbl.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "net/http" 7 | 8 | "github.com/piotrnar/gocoin/lib/btc" 9 | ) 10 | 11 | // GetBlockFromBlockstream downloads a raw block from blockstream 12 | func GetBlockFromBlockstream(hash *btc.Uint256, api_url string) (raw []byte) { 13 | url := api_url + hash.String() + "/raw" 14 | r, er := http.Get(url) 15 | if er == nil { 16 | if r.StatusCode == 200 { 17 | raw, _ = io.ReadAll(r.Body) 18 | r.Body.Close() 19 | } else { 20 | fmt.Println("blockstream block StatusCode=", r.StatusCode) 21 | } 22 | } 23 | if er != nil { 24 | fmt.Println("blockstream block:", er.Error()) 25 | } 26 | return 27 | } 28 | 29 | func IsBlockOK(raw []byte, hash *btc.Uint256) (bl *btc.Block) { 30 | var er error 31 | bl, er = btc.NewBlock(raw) 32 | if er != nil { 33 | return 34 | } 35 | if !bl.Hash.Equal(hash) { 36 | return nil 37 | } 38 | er = bl.BuildTxList() 39 | if er != nil { 40 | return nil 41 | } 42 | if !bl.MerkleRootMatch() { 43 | return nil 44 | } 45 | return 46 | } 47 | 48 | // GetBlockFromWeb downloads a raw block from a web server (try one after another). 49 | func GetBlockFromWeb(hash *btc.Uint256) (bl *btc.Block) { 50 | var raw []byte 51 | 52 | raw = GetBlockFromBlockstream(hash, "https://blockstream.info/api/block/") 53 | if bl = IsBlockOK(raw, hash); bl != nil { 54 | if Verbose { 55 | println("GetTxFromBlockstream - OK") 56 | } 57 | return 58 | } 59 | if Verbose { 60 | println("GetTxFromBlockstream error") 61 | } 62 | 63 | raw = GetBlockFromBlockstream(hash, "https://mempool.space/api/block/") 64 | if bl = IsBlockOK(raw, hash); bl != nil { 65 | if Verbose { 66 | println("GetBlockFromMempoolSpace - OK") 67 | } 68 | return 69 | } 70 | if Verbose { 71 | println("GetBlockFromMempoolSpace error") 72 | } 73 | 74 | return 75 | } 76 | -------------------------------------------------------------------------------- /lib/others/utils/verbose.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | var Verbose bool 4 | -------------------------------------------------------------------------------- /lib/script/dbg.go: -------------------------------------------------------------------------------- 1 | package script 2 | 3 | const ( 4 | DBG_WASTED = 1 << 0 5 | DBG_UNSPENT = 1 << 1 6 | DBG_BLOCKS = 1 << 2 7 | DBG_ORPHAS = 1 << 3 8 | DBG_TX = 1 << 4 9 | DBG_SCRIPT = 1 << 5 10 | DBG_VERIFY = 1 << 6 11 | DBG_SCRERR = 1 << 7 12 | ) 13 | 14 | var dbgmask uint32 = 0 15 | 16 | func don(b uint32) bool { 17 | return (dbgmask & b) != 0 18 | } 19 | 20 | func DbgSwitch(b uint32, on bool) { 21 | if on { 22 | dbgmask |= b 23 | } else { 24 | dbgmask ^= (b & dbgmask) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/secp256k1/.gitignore: -------------------------------------------------------------------------------- 1 | openssl 2 | -------------------------------------------------------------------------------- /lib/secp256k1/COPYING: -------------------------------------------------------------------------------- 1 | This single package (secp256k1) is distributed with the same license as 2 | the original C implementation by sipa: 3 | 4 | * https://github.com/bitcoin/secp256k1/blob/master/COPYING 5 | -------------------------------------------------------------------------------- /lib/secp256k1/README.md: -------------------------------------------------------------------------------- 1 | Implementation of this package has been based on source code created by Pieter Wuille. 2 | 3 | * https://github.com/bitcoin/secp256k1 4 | 5 | 6 | Use go compiler version 1.7 or higher, for significant performance boost. -------------------------------------------------------------------------------- /lib/secp256k1/ec.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | import ( 4 | //"encoding/hex" 5 | ) 6 | 7 | 8 | func ecdsa_verify(pubkey, sig, msg []byte) int { 9 | var m Number 10 | var s Signature 11 | m.SetBytes(msg) 12 | 13 | var q XY 14 | if !q.ParsePubkey(pubkey) { 15 | return -1 16 | } 17 | 18 | if s.ParseBytes(sig)<0 { 19 | return -2 20 | } 21 | 22 | if !s.Verify(&q, &m) { 23 | return 0 24 | } 25 | return 1 26 | } 27 | 28 | func Verify(k, s, m []byte) bool { 29 | return ecdsa_verify(k, s, m)==1 30 | } 31 | 32 | 33 | func DecompressPoint(X []byte, off bool, Y []byte) { 34 | var rx, ry, c, x2, x3 Field 35 | rx.SetB32(X) 36 | rx.Sqr(&x2) 37 | rx.Mul(&x3, &x2) 38 | c.SetInt(7) 39 | c.SetAdd(&x3) 40 | c.Sqrt(&ry) 41 | ry.Normalize() 42 | if ry.IsOdd() != off { 43 | ry.Negate(&ry, 1) 44 | } 45 | ry.Normalize() 46 | ry.GetB32(Y) 47 | return 48 | } 49 | 50 | 51 | func RecoverPublicKey(r, s, h []byte, recid int, pubkey *XY) bool { 52 | var sig Signature 53 | var msg Number 54 | sig.R.SetBytes(r) 55 | if sig.R.Sign()<=0 || sig.R.Cmp(&TheCurve.Order.Int)>=0 { 56 | return false 57 | } 58 | sig.S.SetBytes(s) 59 | if sig.S.Sign()<=0 || sig.S.Cmp(&TheCurve.Order.Int)>=0 { 60 | return false 61 | } 62 | msg.SetBytes(h) 63 | if !sig.recover(pubkey, &msg, recid) { 64 | return false 65 | } 66 | return true 67 | } 68 | 69 | 70 | // Multiply does standard EC multiplication k(xy). 71 | // xy - is the standarized public key format (33 or 65 bytes long). 72 | // out - should be the buffer for 33 bytes (1st byte will be set to either 02 or 03). 73 | func Multiply(xy, k, out []byte) bool { 74 | var pk XY 75 | var xyz XYZ 76 | var na, nzero Number 77 | if !pk.ParsePubkey(xy) { 78 | return false 79 | } 80 | xyz.SetXY(&pk) 81 | na.SetBytes(k) 82 | xyz.ECmult(&xyz, &na, &nzero) 83 | pk.SetXYZ(&xyz) 84 | pk.GetPublicKey(out) 85 | return true 86 | } 87 | 88 | // BaseMultiply multiplies k by G. 89 | // out - should be the buffer for 33 bytes (1st byte will be set to either 02 or 03). 90 | func BaseMultiply(k, out []byte) bool { 91 | var r XYZ 92 | var n Number 93 | var pk XY 94 | n.SetBytes(k) 95 | ECmultGen(&r, &n) 96 | pk.SetXYZ(&r) 97 | pk.GetPublicKey(out) 98 | return true 99 | } 100 | 101 | 102 | // out = G*k + xy 103 | func BaseMultiplyAdd(xy, k, out []byte) bool { 104 | var r XYZ 105 | var n Number 106 | var pk XY 107 | if !pk.ParsePubkey(xy) { 108 | return false 109 | } 110 | n.SetBytes(k) 111 | ECmultGen(&r, &n) 112 | r.AddXY(&r, &pk) 113 | pk.SetXYZ(&r) 114 | pk.GetPublicKey(out) 115 | return true 116 | } 117 | -------------------------------------------------------------------------------- /lib/secp256k1/field_test.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | import ( 4 | "testing" 5 | "crypto/rand" 6 | ) 7 | 8 | 9 | func TestFeInv(t *testing.T) { 10 | var in, out, exp Field 11 | in.SetHex("813925AF112AAB8243F8CCBADE4CC7F63DF387263028DE6E679232A73A7F3C31") 12 | exp.SetHex("7F586430EA30F914965770F6098E492699C62EE1DF6CAFFA77681C179FDF3117") 13 | in.Inv(&out) 14 | if !out.Equals(&exp) { 15 | t.Error("fe.Inv() failed") 16 | } 17 | } 18 | 19 | func BenchmarkFieldSqrt(b *testing.B) { 20 | var dat [32]byte 21 | var f, tmp Field 22 | rand.Read(dat[:]) 23 | f.SetB32(dat[:]) 24 | for i := 0; i < b.N; i++ { 25 | f.Sqrt(&tmp) 26 | } 27 | } 28 | 29 | 30 | func BenchmarkFieldInv(b *testing.B) { 31 | var dat [32]byte 32 | var f, tmp Field 33 | rand.Read(dat[:]) 34 | f.SetB32(dat[:]) 35 | for i := 0; i < b.N; i++ { 36 | f.Inv(&tmp) 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /lib/secp256k1/multi_test.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | import ( 4 | "encoding/hex" 5 | "math/rand" 6 | "testing" 7 | ) 8 | 9 | /* 10 | Test strings, that will cause failure 11 | */ 12 | 13 | //problem seckeys 14 | var _test_seckey []string = []string{ 15 | "08efb79385c9a8b0d1c6f5f6511be0c6f6c2902963d874a3a4bacc18802528d3", 16 | "78298d9ecdc0640c9ae6883201a53f4518055442642024d23c45858f45d0c3e6", 17 | "04e04fe65bfa6ded50a12769a3bd83d7351b2dbff08c9bac14662b23a3294b9e", 18 | "2f5141f1b75747996c5de77c911dae062d16ae48799052c04ead20ccd5afa113", 19 | } 20 | 21 | func RandBytes(n int) []byte { 22 | b := make([]byte, n, n) 23 | 24 | for i := 0; i < n; i++ { 25 | b[i] = byte(rand.Intn(256)) 26 | } 27 | return b 28 | } 29 | 30 | //tests some keys that should work 31 | func Test_Abnormal_Keys1(t *testing.T) { 32 | 33 | for i := 0; i < len(_test_seckey); i++ { 34 | 35 | seckey1, _ := hex.DecodeString(_test_seckey[i]) 36 | 37 | pubkey1 := make([]byte, 33) 38 | 39 | ret := BaseMultiply(seckey1, pubkey1) 40 | 41 | if ret == false { 42 | t.Errorf("base multiplication fail") 43 | } 44 | //func BaseMultiply(k, out []byte) bool { 45 | 46 | var pubkey2 XY 47 | ret = pubkey2.ParsePubkey(pubkey1) 48 | if ret == false { 49 | t.Errorf("pubkey parse fail") 50 | } 51 | 52 | if pubkey2.IsValid() == false { 53 | t.Errorf("pubkey is not valid") 54 | } 55 | 56 | } 57 | } 58 | 59 | //tests random keys 60 | func Test_Abnormal_Keys2(t *testing.T) { 61 | for i := 0; i < 64*1024; i++ { 62 | 63 | seckey1 := RandBytes(32) 64 | 65 | pubkey1 := make([]byte, 33) 66 | 67 | ret := BaseMultiply(seckey1, pubkey1) 68 | 69 | if ret == false { 70 | t.Error("base multiplication fail") 71 | } 72 | //func BaseMultiply(k, out []byte) bool { 73 | 74 | var pubkey2 XY 75 | ret = pubkey2.ParsePubkey(pubkey1) 76 | if ret == false { 77 | t.Error("pubkey parse fail") 78 | } 79 | 80 | if pubkey2.IsValid() == false { 81 | t.Error("pubkey is not valid for", hex.EncodeToString(seckey1)) 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /lib/secp256k1/num.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | "math/big" 7 | ) 8 | 9 | var ( 10 | BigInt1 *big.Int = new(big.Int).SetInt64(1) 11 | ) 12 | 13 | type Number struct { 14 | big.Int 15 | } 16 | 17 | func (a *Number) print(label string) { 18 | fmt.Println(label, hex.EncodeToString(a.Bytes())) 19 | } 20 | 21 | func (r *Number) mod_mul(a, b, m *Number) { 22 | r.Mul(&a.Int, &b.Int) 23 | r.Mod(&r.Int, &m.Int) 24 | return 25 | } 26 | 27 | func (r *Number) mod_inv(a, b *Number) { 28 | r.ModInverse(&a.Int, &b.Int) 29 | return 30 | } 31 | 32 | func (r *Number) mod(a *Number) { 33 | r.Mod(&r.Int, &a.Int) 34 | return 35 | } 36 | 37 | func (a *Number) set_hex(s string) { 38 | a.SetString(s, 16) 39 | } 40 | 41 | func (num *Number) mask_bits(bits uint) { 42 | mask := new(big.Int).Lsh(BigInt1, bits) 43 | mask.Sub(mask, BigInt1) 44 | num.Int.And(&num.Int, mask) 45 | } 46 | 47 | func (a *Number) split_exp(r1, r2 *Number) { 48 | var bnc1, bnc2, bnn2, bnt1, bnt2 Number 49 | 50 | bnn2.Int.Rsh(&TheCurve.Order.Int, 1) 51 | 52 | bnc1.Mul(&a.Int, &TheCurve.a1b2.Int) 53 | bnc1.Add(&bnc1.Int, &bnn2.Int) 54 | bnc1.Div(&bnc1.Int, &TheCurve.Order.Int) 55 | 56 | bnc2.Mul(&a.Int, &TheCurve.b1.Int) 57 | bnc2.Add(&bnc2.Int, &bnn2.Int) 58 | bnc2.Div(&bnc2.Int, &TheCurve.Order.Int) 59 | 60 | bnt1.Mul(&bnc1.Int, &TheCurve.a1b2.Int) 61 | bnt2.Mul(&bnc2.Int, &TheCurve.a2.Int) 62 | bnt1.Add(&bnt1.Int, &bnt2.Int) 63 | r1.Sub(&a.Int, &bnt1.Int) 64 | 65 | bnt1.Mul(&bnc1.Int, &TheCurve.b1.Int) 66 | bnt2.Mul(&bnc2.Int, &TheCurve.a1b2.Int) 67 | r2.Sub(&bnt1.Int, &bnt2.Int) 68 | } 69 | 70 | func (a *Number) split(rl, rh *Number, bits uint) { 71 | rl.Int.Set(&a.Int) 72 | rh.Int.Rsh(&rl.Int, bits) 73 | rl.mask_bits(bits) 74 | } 75 | 76 | func (num *Number) rsh(bits uint) { 77 | num.Rsh(&num.Int, bits) 78 | } 79 | 80 | func (num *Number) inc() { 81 | num.Add(&num.Int, BigInt1) 82 | } 83 | 84 | func (num *Number) rsh_x(bits uint) (res int) { 85 | res = int(new(big.Int).And(&num.Int, new(big.Int).SetUint64((1< le { 97 | panic("buffer too small") 98 | } 99 | if len(bts) == le { 100 | return bts 101 | } 102 | return append(make([]byte, le-len(bts)), bts...) 103 | } 104 | 105 | func (num *Number) sub(a, b *Number) { 106 | num.Sub(&a.Int, &b.Int) 107 | } 108 | 109 | func (num *Number) add(a, b *Number) { 110 | num.Add(&a.Int, &b.Int) 111 | } 112 | 113 | func (num *Number) mul(a, b *Number) { 114 | num.Mul(&a.Int, &b.Int) 115 | } 116 | 117 | func (num *Number) is_zero() bool { 118 | return num.Sign() == 0 119 | } 120 | 121 | func (num *Number) is_below(a *Number) bool { 122 | return num.Cmp(&a.Int) == -1 123 | } 124 | -------------------------------------------------------------------------------- /lib/secp256k1/schnorr_test.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | import ( 4 | "bytes" 5 | "encoding/csv" 6 | "encoding/hex" 7 | "os" 8 | "testing" 9 | ) 10 | 11 | func TestSchnorr(t *testing.T) { 12 | f, er := os.Open("../test/bip340_test_vectors.csv") 13 | if er != nil { 14 | t.Error(er.Error()) 15 | return 16 | } 17 | cf := csv.NewReader(f) 18 | tas, er := cf.ReadAll() 19 | f.Close() 20 | if er != nil { 21 | t.Error(er.Error()) 22 | return 23 | } 24 | for i := range tas { 25 | if i == 0 { 26 | continue // skip column names 27 | } 28 | priv, _ := hex.DecodeString(tas[i][1]) 29 | pkey, _ := hex.DecodeString(tas[i][2]) 30 | rand, _ := hex.DecodeString(tas[i][3]) 31 | hasz, _ := hex.DecodeString(tas[i][4]) 32 | sign, _ := hex.DecodeString(tas[i][5]) 33 | 34 | if len(priv) == 32 { 35 | _sig := SchnorrSign(hasz, priv, rand) 36 | if !bytes.Equal(sign, _sig) { 37 | println(hex.EncodeToString(_sig)) 38 | println(hex.EncodeToString(sign)) 39 | t.Error(i, "Generated signature mismatch") 40 | return 41 | } 42 | } 43 | 44 | if tas[i][6] == "FALSE" { 45 | res := SchnorrVerify(pkey, sign, hasz) 46 | if res { 47 | t.Error("SchnorrVerify not failed") 48 | } 49 | continue 50 | } 51 | 52 | res := SchnorrVerify(pkey, sign, hasz) 53 | if !res { 54 | t.Error("SchnorrVerify failed", i, tas[i][0]) 55 | } 56 | hasz[0]++ 57 | res = SchnorrVerify(pkey, sign, hasz) 58 | if res { 59 | t.Error("SchnorrVerify not failed while it should") 60 | } 61 | } 62 | } 63 | 64 | func BenchmarkSchnorrVerify(b *testing.B) { 65 | pkey, _ := hex.DecodeString("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659") 66 | hash, _ := hex.DecodeString("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89") 67 | sign, _ := hex.DecodeString("6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A") 68 | b.ResetTimer() 69 | for i := 0; i < b.N; i++ { 70 | if !SchnorrVerify(pkey, sign, hash) { 71 | b.Fatal("sig_verify failed") 72 | } 73 | } 74 | } 75 | 76 | func BenchmarkCheckPayToContract(b *testing.B) { 77 | pkey, _ := hex.DecodeString("afaf8a67be00186668f74740e34ffce748139c2b73c9fbd2c1f33e48a612a75d") 78 | base, _ := hex.DecodeString("f1cbd3f2430910916144d5d2bf63d48a6281e5b8e6ade31413adccff3d8839d4") 79 | hash, _ := hex.DecodeString("93a760e87123883022cbd462ac40571176cf09d9d2c6168759fee6c2b079fdd8") 80 | parity := true 81 | b.ResetTimer() 82 | for i := 0; i < b.N; i++ { 83 | if !CheckPayToContract(pkey, base, hash, parity) { 84 | b.Fatal("CheckPayToContract failed") 85 | } 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /lib/secp256k1/secp256k1.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | const WINDOW_A = 5 4 | const WINDOW_G = 14 5 | const FORCE_LOW_S = true // At the output of the Sign() function 6 | 7 | var TheCurve struct { 8 | Order Number 9 | HalfOrder Number 10 | lambda Number 11 | a1b2 Number 12 | b1 Number 13 | a2 Number 14 | p Number 15 | G XY 16 | beta Field 17 | } 18 | 19 | func init_contants() { 20 | TheCurve.Order.SetBytes([]byte{ 21 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 22 | 0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B, 0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x41}) 23 | 24 | TheCurve.HalfOrder.SetBytes([]byte{ 25 | 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 26 | 0x5D, 0x57, 0x6E, 0x73, 0x57, 0xA4, 0x50, 0x1D, 0xDF, 0xE9, 0x2F, 0x46, 0x68, 0x1B, 0x20, 0xA0}) 27 | 28 | TheCurve.p.SetBytes([]byte{ 29 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 30 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0x2F}) 31 | 32 | TheCurve.G.X.SetB32([]byte{ 33 | 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB, 0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B, 0x07, 34 | 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28, 0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17, 0x98}) 35 | 36 | TheCurve.G.Y.SetB32([]byte{ 37 | 0x48, 0x3A, 0xDA, 0x77, 0x26, 0xA3, 0xC4, 0x65, 0x5D, 0xA4, 0xFB, 0xFC, 0x0E, 0x11, 0x08, 0xA8, 38 | 0xFD, 0x17, 0xB4, 0x48, 0xA6, 0x85, 0x54, 0x19, 0x9C, 0x47, 0xD0, 0x8F, 0xFB, 0x10, 0xD4, 0xB8}) 39 | 40 | TheCurve.lambda.SetBytes([]byte{ 41 | 0x53, 0x63, 0xad, 0x4c, 0xc0, 0x5c, 0x30, 0xe0, 0xa5, 0x26, 0x1c, 0x02, 0x88, 0x12, 0x64, 0x5a, 42 | 0x12, 0x2e, 0x22, 0xea, 0x20, 0x81, 0x66, 0x78, 0xdf, 0x02, 0x96, 0x7c, 0x1b, 0x23, 0xbd, 0x72}) 43 | 44 | TheCurve.beta.SetB32([]byte{ 45 | 0x7a, 0xe9, 0x6a, 0x2b, 0x65, 0x7c, 0x07, 0x10, 0x6e, 0x64, 0x47, 0x9e, 0xac, 0x34, 0x34, 0xe9, 46 | 0x9c, 0xf0, 0x49, 0x75, 0x12, 0xf5, 0x89, 0x95, 0xc1, 0x39, 0x6c, 0x28, 0x71, 0x95, 0x01, 0xee}) 47 | 48 | TheCurve.a1b2.SetBytes([]byte{ 49 | 0x30, 0x86, 0xd2, 0x21, 0xa7, 0xd4, 0x6b, 0xcd, 0xe8, 0x6c, 0x90, 0xe4, 0x92, 0x84, 0xeb, 0x15}) 50 | 51 | TheCurve.b1.SetBytes([]byte{ 52 | 0xe4, 0x43, 0x7e, 0xd6, 0x01, 0x0e, 0x88, 0x28, 0x6f, 0x54, 0x7f, 0xa9, 0x0a, 0xbf, 0xe4, 0xc3}) 53 | 54 | TheCurve.a2.SetBytes([]byte{ 55 | 0x01, 0x14, 0xca, 0x50, 0xf7, 0xa8, 0xe2, 0xf3, 0xf6, 0x57, 0xc1, 0x10, 0x8d, 0x9d, 0x44, 0xcf, 0xd8}) 56 | } 57 | 58 | func init() { 59 | init_contants() 60 | } 61 | -------------------------------------------------------------------------------- /lib/secp256k1/xyz_test.go: -------------------------------------------------------------------------------- 1 | package secp256k1 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestGejDouble(t *testing.T) { 8 | var a, a_exp, r XYZ 9 | a.X.SetHex("79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798") 10 | a.Y.SetHex("483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8") 11 | a.Z.SetHex("01") 12 | a_exp.X.SetHex("7D152C041EA8E1DC2191843D1FA9DB55B68F88FEF695E2C791D40444B365AFC2") 13 | a_exp.Y.SetHex("56915849F52CC8F76F5FD7E4BF60DB4A43BF633E1B1383F85FE89164BFADCBDB") 14 | a_exp.Z.SetHex("9075B4EE4D4788CABB49F7F81C221151FA2F68914D0AA833388FA11FF621A970") 15 | 16 | a.Double(&r) 17 | if !r.Equals(&a_exp) { 18 | t.Error("gej.Double failed") 19 | } 20 | } 21 | 22 | func TestGejMulLambda(t *testing.T) { 23 | var a, a_exp XYZ 24 | a.X.SetHex("0eaebcd1df2df853d66ce0e1b0fda07f67d1cabefde98514aad795b86a6ea66d") 25 | a.Y.SetHex("beb26b67d7a00e2447baeccc8a4cef7cd3cad67376ac1c5785aeebb4f6441c16") 26 | a.Z.SetHex("01") 27 | a_exp.X.SetHex("a45720c272cfa1f77f64be8a404a7d3149bd5410f9a173353f6eb75a5085ba98") 28 | a_exp.Y.SetHex("beb26b67d7a00e2447baeccc8a4cef7cd3cad67376ac1c5785aeebb4f6441c16") 29 | a_exp.Z.SetHex("01") 30 | a_lam := a 31 | a_lam.mul_lambda(&a_lam) 32 | if !a_lam.Equals(&a_exp) { 33 | t.Error("mul_lambda failed") 34 | } 35 | } 36 | 37 | func TestGejGetX(t *testing.T) { 38 | var a XYZ 39 | var X, exp Field 40 | a.X.SetHex("EB6752420B6BDB40A760AC26ADD7E7BBD080BF1DF6C0B009A0D310E4511BDF49") 41 | a.Y.SetHex("8E8CEB84E1502FC536FFE67967BC44314270A0B38C79865FFED5A85D138DCA6B") 42 | a.Z.SetHex("813925AF112AAB8243F8CCBADE4CC7F63DF387263028DE6E679232A73A7F3C31") 43 | 44 | exp.SetHex("fe00e013c244062847045ae7eb73b03fca583e9aa5dbd030a8fd1c6dfcf11b10") 45 | a.get_x(&X) 46 | if !X.Equals(&exp) { 47 | t.Error("get.get_x() fail") 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /lib/test/README.md: -------------------------------------------------------------------------------- 1 | These test vector files come from the original bitcoin project: 2 | 3 | * https://github.com/bitcoin/bitcoin/tree/master/src/test/data 4 | -------------------------------------------------------------------------------- /lib/test/base58_encode_decode.json: -------------------------------------------------------------------------------- 1 | [ 2 | ["", ""], 3 | ["61", "2g"], 4 | ["626262", "a3gV"], 5 | ["636363", "aPEr"], 6 | ["73696d706c792061206c6f6e6720737472696e67", "2cFupjhnEsSn59qHXstmK2ffpLv2"], 7 | ["00eb15231dfceb60925886b67d065299925915aeb172c06647", "1NS17iag9jJgTHD1VXjvLCEnZuQ3rJDE9L"], 8 | ["516b6fcd0f", "ABnLTmg"], 9 | ["bf4f89001e670274dd", "3SEo3LWLoPntC"], 10 | ["572e4794", "3EFU7m"], 11 | ["ecac89cad93923c02321", "EJDM8drfXA6uyA"], 12 | ["10c8511e", "Rt5zm"], 13 | ["00000000000000000000", "1111111111"], 14 | ["000111d38e5fc9071ffcd20b4a763cc9ae4f252bb4e48fd66a835e252ada93ff480d6dd43dc62a641155a5", "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"], 15 | ["000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff", "1cWB5HCBdLjAuqGGReWE3R3CguuwSjw6RHn39s2yuDRTS5NsBgNiFpWgAnEx6VQi8csexkgYw3mdYrMHr8x9i7aEwP8kZ7vccXWqKDvGv3u1GxFKPuAkn8JCPPGDMf3vMMnbzm6Nh9zh1gcNsMvH3ZNLmP5fSG6DGbbi2tuwMWPthr4boWwCxf7ewSgNQeacyozhKDDQQ1qL5fQFUW52QKUZDZ5fw3KXNQJMcNTcaB723LchjeKun7MuGW5qyCBZYzA1KjofN1gYBV3NqyhQJ3Ns746GNuf9N2pQPmHz4xpnSrrfCvy6TVVz5d4PdrjeshsWQwpZsZGzvbdAdN8MKV5QsBDY"] 16 | ] 17 | -------------------------------------------------------------------------------- /lib/utxo/unspent.go: -------------------------------------------------------------------------------- 1 | package utxo 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | 7 | "github.com/piotrnar/gocoin/lib/btc" 8 | ) 9 | 10 | const ( 11 | UtxoIdxLen = 8 // Increase this value (maximum 32) for better security at a cost of memory usage 12 | ) 13 | 14 | type UtxoKeyType [UtxoIdxLen]byte 15 | 16 | type AllUnspentTx []*OneUnspentTx 17 | 18 | // OneUnspentTx is returned by GetUnspentFromPkScr. 19 | type OneUnspentTx struct { 20 | *btc.BtcAddr 21 | destString string 22 | Message []byte 23 | btc.TxPrevOut 24 | Value uint64 25 | MinedAt uint32 26 | Coinbase bool 27 | } 28 | 29 | func (x AllUnspentTx) Len() int { 30 | return len(x) 31 | } 32 | 33 | func (x AllUnspentTx) Less(i, j int) bool { 34 | if x[i].MinedAt == x[j].MinedAt { 35 | if x[i].TxPrevOut.Hash == x[j].TxPrevOut.Hash { 36 | return x[i].TxPrevOut.Vout < x[j].TxPrevOut.Vout 37 | } 38 | return binary.LittleEndian.Uint64(x[i].TxPrevOut.Hash[24:32]) < 39 | binary.LittleEndian.Uint64(x[j].TxPrevOut.Hash[24:32]) 40 | } 41 | return x[i].MinedAt < x[j].MinedAt 42 | } 43 | 44 | func (x AllUnspentTx) Swap(i, j int) { 45 | x[i], x[j] = x[j], x[i] 46 | } 47 | 48 | func (ou *OneUnspentTx) String() (s string) { 49 | s = fmt.Sprintf("%15s BTC %s", btc.UintToBtc(ou.Value), ou.TxPrevOut.String()) 50 | if ou.BtcAddr != nil { 51 | s += " " + ou.DestAddr() + ou.BtcAddr.Label() 52 | } 53 | if ou.MinedAt != 0 { 54 | s += fmt.Sprint(" ", ou.MinedAt) 55 | } 56 | if ou.Coinbase { 57 | s += " Coinbase" 58 | } 59 | if ou.Message != nil { 60 | s += " " 61 | for _, c := range ou.Message { 62 | if c < ' ' || c > 127 { 63 | s += fmt.Sprintf("\\x%02x", c) 64 | } else { 65 | s += string(c) 66 | } 67 | } 68 | } 69 | return 70 | } 71 | 72 | func (ou *OneUnspentTx) FixDestString() { 73 | ou.destString = ou.BtcAddr.String() 74 | } 75 | 76 | func (ou *OneUnspentTx) UnspentTextLine() (s string) { 77 | s = fmt.Sprintf("%s # %.8f BTC @ %s%s, block %d", ou.TxPrevOut.String(), 78 | float64(ou.Value)/1e8, ou.DestAddr(), ou.BtcAddr.Label(), ou.MinedAt) 79 | return 80 | } 81 | 82 | func (ou *OneUnspentTx) DestAddr() string { 83 | if ou.destString == "" { 84 | return ou.BtcAddr.String() 85 | } 86 | return ou.destString 87 | } 88 | -------------------------------------------------------------------------------- /todo.txt: -------------------------------------------------------------------------------- 1 | Global: 2 | * Add suport for multisig segwit 3 | 4 | Lib: 5 | * Check implemetation against this: https://bitslog.wordpress.com/2017/01/08/a-bitcoin-transaction-that-takes-5-hours-to-verify/ 6 | 7 | Client: 8 | * Do not ask peers without services bit 0 for old blocks (perhaps don't event connect to them during initial sync) 9 | * Force to create UTXO.db file once for awhile (when bootstraping) 10 | * Review and update WebUI's Help page 11 | * Monitor: at slow connections it gets stuck (new blocks stop being downloaded). Go to standby and come back. 12 | * Optionally use utils.GetBlockFromWeb() for initial blockchain download 13 | * Figure out a way to purge blocks that we got good headers for, but never managed to download the txs 14 | * Update mining API 15 | * Console + TextUI over WebUI functionality 16 | 17 | Wallet: 18 | * Implement "server mode", e.g. through TCP or serial connection 19 | * Write more automated tests 20 | 21 | Probably not to do: 22 | * Do not list unmatured coinbase outputs in the balance 23 | * Implement "mempool" network command 24 | * Try to make own (faster) implementation of sha256 and rimp160 25 | 26 | Tools: 27 | * txaddsig - make it to work with multisig and segwit 28 | -------------------------------------------------------------------------------- /tools/base58/base58.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | "flag" 7 | "strings" 8 | "io/ioutil" 9 | "encoding/hex" 10 | "github.com/piotrnar/gocoin/lib/btc" 11 | ) 12 | 13 | var ( 14 | decode = flag.Bool("d", false, "run base58 decode (instead of encode)") 15 | binary = flag.Bool("b", false, "binary (insted of hex) for decode output") 16 | help = flag.Bool("h", false, "print this help") 17 | ) 18 | 19 | func main() { 20 | flag.Parse() 21 | if *help { 22 | flag.PrintDefaults() 23 | return 24 | } 25 | 26 | msg, _ := ioutil.ReadAll(os.Stdin) 27 | if len(msg)==0 { 28 | return 29 | } 30 | 31 | if *decode { 32 | res := btc.Decodeb58(strings.Trim(string(msg), " \t\n\r")) 33 | if *binary { 34 | os.Stdout.Write(res) 35 | } else { 36 | fmt.Println(hex.EncodeToString(res)) 37 | } 38 | } else { 39 | fmt.Println(btc.Encodeb58(msg)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /tools/blockinfo/blockinfo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/binary" 5 | "encoding/hex" 6 | "fmt" 7 | "os" 8 | "time" 9 | 10 | "github.com/piotrnar/gocoin/lib/btc" 11 | ) 12 | 13 | func main() { 14 | if len(os.Args) != 2 { 15 | println("Specify filename with raw block data") 16 | return 17 | } 18 | d, er := os.ReadFile(os.Args[1]) 19 | if er != nil { 20 | println("Error opening file:", er.Error()) 21 | return 22 | } 23 | bl, er := btc.NewBlock(d) 24 | if er != nil { 25 | println("Error decoding block:", er.Error()) 26 | return 27 | } 28 | fmt.Println("Block Version:", bl.Version()) 29 | fmt.Println("Parent Hash:", btc.NewUint256(bl.ParentHash()).String()) 30 | fmt.Println("Merkle Root:", btc.NewUint256(bl.MerkleRoot()).String(), " OK:", bl.MerkleRootMatch()) 31 | fmt.Println("Time Stamp:", time.Unix(int64(bl.BlockTime()), 0).Format("2006-01-02 15:04:05")) 32 | fmt.Println("Nonce:", binary.LittleEndian.Uint32(bl.Raw[72:76])) 33 | bits := bl.Bits() 34 | var nul [32]byte 35 | target := btc.SetCompact(bits) 36 | bts := target.Bytes() 37 | fmt.Printf("Bits: 0x%08x => Diff:%.1f / Target:%s\n", bits, btc.GetDifficulty(bits), hex.EncodeToString(append(nul[:32-len(bts)], bts...))) 38 | 39 | bl.BuildTxList() 40 | fmt.Println("Transactions:", len(bl.Txs)) 41 | for _, tx := range bl.Txs { 42 | fmt.Println(tx.Hash.String(), "-", len(tx.TxOut), "outs") 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /tools/fetchblock/fetchblock.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/piotrnar/gocoin/lib/btc" 6 | "io/ioutil" 7 | "github.com/piotrnar/gocoin/lib/others/utils" 8 | "github.com/piotrnar/gocoin" 9 | "os" 10 | ) 11 | 12 | 13 | func main() { 14 | fmt.Println("Gocoin FetchBlock version", gocoin.Version) 15 | 16 | if len(os.Args) < 2 { 17 | fmt.Println("Specify block hash on the command line (MSB).") 18 | return 19 | } 20 | 21 | hash := btc.NewUint256FromString(os.Args[1]) 22 | bl := utils.GetBlockFromWeb(hash) 23 | if bl==nil { 24 | fmt.Println("Error fetching the block") 25 | } else { 26 | ioutil.WriteFile(bl.Hash.String()+".bin", bl.Raw, 0666) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tools/fetchtx/fetchtx.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/piotrnar/gocoin/lib/btc" 6 | "io/ioutil" 7 | "github.com/piotrnar/gocoin/lib/others/utils" 8 | "github.com/piotrnar/gocoin" 9 | "os" 10 | ) 11 | 12 | 13 | func main() { 14 | fmt.Println("Gocoin FetchTx version", gocoin.Version) 15 | 16 | if len(os.Args) < 2 { 17 | fmt.Println("Specify transaction id on the command line (MSB).") 18 | return 19 | } 20 | 21 | txid := btc.NewUint256FromString(os.Args[1]) 22 | if txid == nil { 23 | println("Incorrect transaction ID") 24 | return 25 | } 26 | 27 | rawtx := utils.GetTxFromWeb(txid) 28 | if rawtx==nil { 29 | fmt.Println("Error fetching the transaction") 30 | } else { 31 | ioutil.WriteFile(txid.String()+".tx", rawtx, 0666) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tools/hdwal/hdwal.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/hex" 5 | "fmt" 6 | 7 | "github.com/piotrnar/gocoin/lib/btc" 8 | ) 9 | 10 | // Use this tool with "Prnt" type of public master keys 11 | 12 | func main() { 13 | hdw, er := btc.StringWallet("xpub6CmoCa2ASDeVgaXeVkWXaJ5ZmeEAvYoZFnt3EXc2dhZEMVDW8noe3wMhWyQ4kPFUFGJdVAduv5JaugCndZNghtJicQqu76UywCWDKGTz5us") 14 | if er != nil { 15 | println(er.Error()) 16 | return 17 | } 18 | 19 | hdw.Prefix = btc.PublicZ // convert to bech32 format 20 | fmt.Println("Parent master public key:") 21 | fmt.Println("", hdw.String()) 22 | 23 | fmt.Println("1st deposit address (e.g. m/84'/0'/0'/0/0):") 24 | fmt.Println("", hdw.Child(0).Child(0).PubAddr().String()) 25 | fmt.Println("", hex.EncodeToString(hdw.Child(0).Child(0).Pub().Key)) 26 | 27 | fmt.Println("1st change address (e.g. m/84'/0'/0'/1/0):") 28 | fmt.Println("", hdw.Child(1).Child(0).PubAddr().String()) 29 | fmt.Println("", hex.EncodeToString(hdw.Child(1).Child(0).Pub().Key)) 30 | } 31 | -------------------------------------------------------------------------------- /tools/mkmulti/mkmulti.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | "bytes" 7 | "strconv" 8 | "io/ioutil" 9 | "encoding/hex" 10 | "github.com/piotrnar/gocoin/lib/btc" 11 | ) 12 | 13 | /* 14 | { 15 | "address" : "2NAHUDSC1EmbTBwQQp4VQ2FNzWDqHtmk1i6", 16 | "redeemScript" : "512102cdc4fff0ad031ea5f2d0d4337e2bf976b84334f8f80b08fe3f69886d58bc5a8a2102ebf54926d3edaae51bde71f2976948559a8d43fce52f5e7ed9ed85dbaa449d7f52ae" 17 | } 18 | */ 19 | func main() { 20 | var testnet bool 21 | if len(os.Args)<3 { 22 | fmt.Println("Specify one integer and at least one public key.") 23 | fmt.Println("For Testent, make the integer negative.") 24 | return 25 | } 26 | cnt, er := strconv.ParseInt(os.Args[1], 10, 32) 27 | if er!=nil { 28 | println("Count value:", er.Error()) 29 | return 30 | } 31 | if cnt<0 { 32 | testnet = true 33 | cnt = -cnt 34 | } 35 | if cnt<1 || cnt>16 { 36 | println("The integer (required number of keys) must be between 1 and 16") 37 | return 38 | } 39 | buf := new(bytes.Buffer) 40 | buf.WriteByte(byte(0x50+cnt)) 41 | fmt.Println("Trying to prepare multisig address for", cnt, "out of", len(os.Args)-2, "public keys ...") 42 | var pkeys byte 43 | var ads string 44 | for i:=2; i mp[j].Time 22 | } 23 | 24 | func (mp manyPeers) Swap(i, j int) { 25 | mp[i], mp[j] = mp[j], mp[i] 26 | } 27 | 28 | func main() { 29 | var dir string 30 | 31 | if len(os.Args) > 1 { 32 | dir = os.Args[1] 33 | } else { 34 | dir = sys.BitcoinHome() + "gocoin" + string(os.PathSeparator) + "btcnet" + string(os.PathSeparator) + "peers3" 35 | } 36 | 37 | db, er := qdb.NewDB(dir, true) 38 | 39 | if er != nil { 40 | println(er.Error()) 41 | os.Exit(1) 42 | } 43 | 44 | println(db.Count(), "peers in databse", dir) 45 | if db.Count() == 0 { 46 | return 47 | } 48 | 49 | tmp := make(manyPeers, db.Count()) 50 | cnt := 0 51 | db.Browse(func(k qdb.KeyType, v []byte) uint32 { 52 | np := peersdb.NewPeer(v) 53 | if !sys.ValidIp4(np.Ip4[:]) { 54 | return 0 55 | } 56 | if cnt < len(tmp) { 57 | tmp[cnt] = np 58 | cnt++ 59 | } 60 | return 0 61 | }) 62 | 63 | sort.Sort(tmp[:cnt]) 64 | for cnt = 0; cnt < len(tmp) && cnt < 2500; cnt++ { 65 | ad := tmp[cnt] 66 | fmt.Printf("%3d) %16s %5d - seen %5d min ago\n", cnt+1, 67 | fmt.Sprintf("%d.%d.%d.%d", ad.Ip4[0], ad.Ip4[1], ad.Ip4[2], ad.Ip4[3]), 68 | ad.Port, (time.Now().Unix()-int64(ad.Time))/60) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /tools/sipa_dll/secp256k1.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/tools/sipa_dll/secp256k1.dll -------------------------------------------------------------------------------- /tools/sipa_dll/sipadll.go: -------------------------------------------------------------------------------- 1 | package spiadll 2 | 3 | import ( 4 | "unsafe" 5 | "syscall" 6 | ) 7 | 8 | var ( 9 | dll = syscall.NewLazyDLL("secp256k1.dll") 10 | DLL_EC_Verify = dll.NewProc("EC_Verify") 11 | DLL_Schnorr_Verify = dll.NewProc("Schnorr_Verify") 12 | DLL_CheckPayToContract = dll.NewProc("CheckPayToContract") 13 | ) 14 | 15 | 16 | func EC_Verify(pkey, sign, hash []byte) int32 { 17 | r1, _, _ := syscall.Syscall6(DLL_EC_Verify.Addr(), 6, 18 | uintptr(unsafe.Pointer(&hash[0])), uintptr(32), 19 | uintptr(unsafe.Pointer(&sign[0])), uintptr(len(sign)), 20 | uintptr(unsafe.Pointer(&pkey[0])), uintptr(len(pkey))) 21 | return int32(r1) 22 | } 23 | 24 | 25 | func Schnorr_Verify(pkey, sign, msg []byte) int { 26 | r1, _, _ := syscall.Syscall(DLL_Schnorr_Verify.Addr(), 3, 27 | uintptr(unsafe.Pointer(&msg[0])), 28 | uintptr(unsafe.Pointer(&sign[0])), 29 | uintptr(unsafe.Pointer(&pkey[0]))) 30 | return int(r1) 31 | } 32 | 33 | func CheckPayToContract(kd, base, hash []byte, parity int) int { 34 | r1, _, _ := syscall.Syscall6(DLL_CheckPayToContract.Addr(), 4, 35 | uintptr(unsafe.Pointer(&kd[0])), 36 | uintptr(unsafe.Pointer(&base[0])), 37 | uintptr(unsafe.Pointer(&hash[0])), uintptr(parity), 0, 0) 38 | return int(r1) 39 | } 40 | -------------------------------------------------------------------------------- /tools/sipa_dll/sipadll_test.go: -------------------------------------------------------------------------------- 1 | package spiadll 2 | 3 | import ( 4 | "testing" 5 | "encoding/hex" 6 | ) 7 | 8 | func TestVerify(t *testing.T) { 9 | pkey, _ := hex.DecodeString("040eaebcd1df2df853d66ce0e1b0fda07f67d1cabefde98514aad795b86a6ea66dbeb26b67d7a00e2447baeccc8a4cef7cd3cad67376ac1c5785aeebb4f6441c16") 10 | hasz, _ := hex.DecodeString("3382219555ddbb5b00e0090f469e590ba1eae03c7f28ab937de330aa60294ed6") 11 | sign, _ := hex.DecodeString("3045022100fe00e013c244062847045ae7eb73b03fca583e9aa5dbd030a8fd1c6dfcf11b1002207d0d04fed8fa1e93007468d5a9e134b0a7023b6d31db4e50942d43a250f4d07c01") 12 | res := EC_Verify(pkey, sign, hasz) 13 | if res!=1 { 14 | t.Error("Verify failed") 15 | } 16 | hasz[0]++ 17 | res = EC_Verify(pkey, sign, hasz) 18 | if res!=0 { 19 | t.Error("Verify not failed while it should") 20 | } 21 | res = EC_Verify(pkey[:1], sign, hasz) 22 | if res>=0 { 23 | t.Error("Negative result expected", res) 24 | } 25 | res = EC_Verify(pkey, sign[:1], hasz) 26 | if res>=0 { 27 | t.Error("Yet negative result expected", res) 28 | } 29 | res = EC_Verify(pkey, sign, hasz[:1]) 30 | if res!=0 { 31 | t.Error("Zero expected", res) 32 | } 33 | } 34 | 35 | func TestSchnorr(t *testing.T) { 36 | key, _ := hex.DecodeString("DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659") 37 | sig, _ := hex.DecodeString("6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A") 38 | msg, _ := hex.DecodeString("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89") 39 | res := Schnorr_Verify(key, sig, msg) 40 | if res!=1 { 41 | t.Error("Schnorr Verify failed") 42 | } 43 | msg[0]++ 44 | res = Schnorr_Verify(key, sig, msg) 45 | if res!=0 { 46 | t.Error("Schnorr Verify not failed while it should") 47 | } 48 | } 49 | 50 | func TestPay2Scr(t *testing.T) { 51 | pkey, _ := hex.DecodeString("afaf8a67be00186668f74740e34ffce748139c2b73c9fbd2c1f33e48a612a75d") 52 | base, _ := hex.DecodeString("f1cbd3f2430910916144d5d2bf63d48a6281e5b8e6ade31413adccff3d8839d4") 53 | hash, _ := hex.DecodeString("93a760e87123883022cbd462ac40571176cf09d9d2c6168759fee6c2b079fdd8") 54 | var parity int = 1 55 | res := CheckPayToContract(pkey, base, hash, parity) 56 | if res!=1 { 57 | t.Error("CheckPayToContract failed") 58 | } 59 | hash[0]++ 60 | res = CheckPayToContract(pkey, base, hash, parity) 61 | if res!=0 { 62 | t.Error("CheckPayToContract not failed while it should") 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /tools/tap2old/tap2old.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | // Convert TAP-public-key address to the old P2KH address 4 | // Or 5 | // COnvert public key to all compatibe BTC deposit addresses 6 | 7 | import ( 8 | "encoding/hex" 9 | "fmt" 10 | "os" 11 | 12 | "github.com/piotrnar/gocoin/lib/btc" 13 | ) 14 | 15 | func dump_all_addrs(pk []byte, testnet bool) { 16 | ad := btc.NewAddrFromPubkey(pk, btc.AddrVerPubkey(testnet)) 17 | if ad == nil { 18 | println("Unexpected error returned by NewAddrFromPubkey()") 19 | return 20 | } 21 | hrp := btc.GetSegwitHRP(testnet) 22 | fmt.Println("", ad.String()) 23 | 24 | ad.Enc58str = "" 25 | ad.SegwitProg = &btc.SegwitProg{HRP: hrp, Version: 1, Program: pk[1:]} 26 | fmt.Println("", ad.String()) 27 | 28 | ad.Enc58str = "" 29 | ad.SegwitProg = &btc.SegwitProg{HRP: hrp, Version: 0, Program: ad.Hash160[:]} 30 | fmt.Println("", ad.String()) 31 | 32 | h160 := btc.Rimp160AfterSha256(append([]byte{0, 20}, ad.Hash160[:]...)) 33 | ad = btc.NewAddrFromHash160(h160[:], btc.AddrVerScript(testnet)) 34 | fmt.Println("", ad.String()) 35 | } 36 | 37 | func main() { 38 | if len(os.Args) < 2 { 39 | println("Specify bech32 encoded Taproot deposit address or hex encoded public key") 40 | return 41 | } 42 | 43 | // Try to decode public key first 44 | if len(os.Args[1]) == 66 && os.Args[1][0] == '0' && (os.Args[1][1] == '2' || os.Args[1][1] == '3') { 45 | pk, er := hex.DecodeString(os.Args[1]) 46 | if er != nil { 47 | println(er.Error()) 48 | return 49 | } 50 | fmt.Println("Mainnet:") 51 | dump_all_addrs(pk, false) 52 | 53 | fmt.Println("Testnet:") 54 | dump_all_addrs(pk, true) 55 | return 56 | } 57 | 58 | // if not public key, do the taproot bech32 encoded... 59 | ad, er := btc.NewAddrFromString(os.Args[1]) 60 | if er != nil { 61 | println(er.Error()) 62 | return 63 | } 64 | if ad.SegwitProg == nil { 65 | println("This is not a segwit type address") 66 | return 67 | } 68 | fmt.Println("Version:", ad.SegwitProg.Version) 69 | fmt.Println("Program:", hex.EncodeToString(ad.SegwitProg.Program)) 70 | if ad.SegwitProg.Version != 1 { 71 | println("This is not segwit version 1 address") 72 | return 73 | } 74 | if len(ad.SegwitProg.Program) != 32 { 75 | println("Program length must be 32 bytes") 76 | return 77 | } 78 | fmt.Println("Possible P2KH addresses:") 79 | fmt.Println("", btc.NewAddrFromPubkey(append([]byte{0x02}, ad.SegwitProg.Program...), btc.AddrVerPubkey(false))) 80 | fmt.Println("", btc.NewAddrFromPubkey(append([]byte{0x03}, ad.SegwitProg.Program...), btc.AddrVerPubkey(false))) 81 | } 82 | -------------------------------------------------------------------------------- /tools/trumpic/.gitignore: -------------------------------------------------------------------------------- 1 | blocks/*.bin 2 | out 3 | *.bin 4 | -------------------------------------------------------------------------------- /tools/trumpic/blocks/readme.txt: -------------------------------------------------------------------------------- 1 | Raw data of the blocks will be cached here -------------------------------------------------------------------------------- /tools/trumpic/fees.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/tools/trumpic/fees.zip -------------------------------------------------------------------------------- /tools/trumpic/getfees/getfees.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "encoding/json" 6 | "errors" 7 | "fmt" 8 | "io" 9 | "net/http" 10 | "os" 11 | 12 | "github.com/piotrnar/gocoin/lib/btc" 13 | ) 14 | 15 | func getfees(hash *btc.Uint256) (res []uint64, er error) { 16 | var r *http.Response 17 | var start_index int 18 | var url string 19 | var c []byte 20 | var result []struct { 21 | TxID string `json:"txid"` 22 | Fee uint64 `json:"fee"` 23 | Size uint64 `json:"size"` 24 | Weight uint64 `json:"weight"` 25 | } 26 | 27 | for { 28 | url = fmt.Sprint("https://mempool.space/api/block/"+hash.String()+"/txs/", start_index) 29 | //println(url) 30 | if r, er = http.Get(url); er != nil { 31 | println(er.Error()) 32 | return 33 | } 34 | if r.StatusCode != 200 { 35 | er = errors.New(fmt.Sprint("HTTP StatusCode ", r.StatusCode)) 36 | return 37 | } 38 | 39 | c, er = io.ReadAll(r.Body) 40 | r.Body.Close() 41 | if er != nil { 42 | return 43 | } 44 | println("got", len(c), "bytes") 45 | 46 | //os.WriteFile("resp.json", c, 0600) 47 | 48 | if er = json.Unmarshal(c, &result); er != nil { 49 | return 50 | } 51 | 52 | println("arrlen", len(result), "at index", start_index, len(res)) 53 | if len(result) == 0 { 54 | return 55 | } 56 | 57 | for _, r := range result { 58 | res = append(res, r.Fee) 59 | //res = append(res, 1000*r.Fee/r.Size) 60 | } 61 | if len(result) != 25 { 62 | return 63 | } 64 | start_index += 25 65 | } 66 | } 67 | 68 | func main() { 69 | if len(os.Args) < 2 { 70 | println("Specify the block hash") 71 | return 72 | } 73 | block_hash := btc.NewUint256FromString(os.Args[1]) 74 | if block_hash == nil { 75 | println("Incorrent block hash") 76 | return 77 | } 78 | 79 | fname := "../block_" + block_hash.String()[56:] + "_fees.go" 80 | f, er := os.Create(fname) 81 | if er != nil { 82 | println(er.Error()) 83 | return 84 | } 85 | defer f.Close() 86 | wr := bufio.NewWriter(f) 87 | 88 | block_fees, er := getfees(block_hash) 89 | if er != nil && len(block_fees) == 0 { 90 | println(er.Error()) 91 | return 92 | } 93 | 94 | fmt.Fprintln(wr, "package main") 95 | fmt.Fprintln(wr, "var block_hash = \""+block_hash.String()+"\"") 96 | fmt.Fprintln(wr, "var block_fees = []uint64{") 97 | 98 | for i, f := range block_fees { 99 | fmt.Fprint(wr, " ", f, ",") 100 | if (i & 7) == 7 { 101 | fmt.Fprintln(wr) 102 | } 103 | } 104 | fmt.Fprintln(wr, "\n}") 105 | 106 | wr.Flush() 107 | 108 | } 109 | -------------------------------------------------------------------------------- /tools/trumpic/working_blocks.txt: -------------------------------------------------------------------------------- 1 | 000000000000000000010c05038d08c742d28a7a248e9d0f94ebe5102f366c8e 879613 - trump 2 | 00000000000000000001c3fbc76a7efe7a320a8236ea6250bc15e4f7a67e727d 880512 - BTCAI 3 | -------------------------------------------------------------------------------- /tools/txaddsig/txaddsig.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "os" 5 | "fmt" 6 | "bytes" 7 | "strconv" 8 | "io/ioutil" 9 | "encoding/hex" 10 | "github.com/piotrnar/gocoin/lib/btc" 11 | ) 12 | 13 | 14 | func raw_tx_from_file(fn string) *btc.Tx { 15 | d, er := ioutil.ReadFile(fn) 16 | if er != nil { 17 | fmt.Println(er.Error()) 18 | return nil 19 | } 20 | 21 | dat, er := hex.DecodeString(string(d)) 22 | if er != nil { 23 | fmt.Println("hex.DecodeString failed - assume binary transaction file") 24 | dat = d 25 | } 26 | tx, txle := btc.NewTx(dat) 27 | 28 | if tx != nil && txle != len(dat) { 29 | fmt.Println("WARNING: Raw transaction length mismatch", txle, len(dat)) 30 | } 31 | 32 | return tx 33 | } 34 | 35 | 36 | func write_tx_file(tx *btc.Tx) { 37 | signedrawtx := tx.Serialize() 38 | tx.SetHash(signedrawtx) 39 | 40 | hs := tx.Hash.String() 41 | fmt.Println(hs) 42 | 43 | f, _ := os.Create(hs[:8]+".txt") 44 | if f != nil { 45 | f.Write([]byte(hex.EncodeToString(signedrawtx))) 46 | f.Close() 47 | fmt.Println("Transaction data stored in", hs[:8]+".txt") 48 | } 49 | } 50 | 51 | 52 | func main() { 53 | if len(os.Args)!=5 { 54 | fmt.Println("This tool needs to be executed with 4 arguments:") 55 | fmt.Println(" 1) Name of the unsigned transaction file") 56 | fmt.Println(" 2) Input index to add the key & signature to") 57 | fmt.Println(" 3) Hex dump of the canonical signature") 58 | fmt.Println(" 4) Hex dump of the public key") 59 | return 60 | } 61 | tx := raw_tx_from_file(os.Args[1]) 62 | if tx==nil { 63 | return 64 | } 65 | 66 | in, er := strconv.ParseUint(os.Args[2], 10, 32) 67 | if er != nil { 68 | println("Input index:", er.Error()) 69 | return 70 | } 71 | 72 | if int(in) >= len(tx.TxIn) { 73 | println("Input index too big:", int(in), "/", len(tx.TxIn)) 74 | return 75 | } 76 | 77 | sig, er := hex.DecodeString(os.Args[3]) 78 | if er != nil { 79 | println("Signature:", er.Error()) 80 | return 81 | } 82 | 83 | pk, er := hex.DecodeString(os.Args[4]) 84 | if er != nil { 85 | println("Public key:", er.Error()) 86 | return 87 | } 88 | 89 | buf := new(bytes.Buffer) 90 | btc.WriteVlen(buf, uint64(len(sig))) 91 | buf.Write(sig) 92 | btc.WriteVlen(buf, uint64(len(pk))) 93 | buf.Write(pk) 94 | 95 | tx.TxIn[in].ScriptSig = buf.Bytes() 96 | 97 | write_tx_file(tx) 98 | } 99 | -------------------------------------------------------------------------------- /tools/txmod/txmod.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/hex" 5 | "os" 6 | 7 | "github.com/piotrnar/gocoin/lib/btc" 8 | ) 9 | 10 | func main() { 11 | // modify transaciotn and save it back on disk (e.g. to change a fee) 12 | if len(os.Args) < 2 { 13 | println("Specify filename with the tranaction to modify") 14 | return 15 | } 16 | d, er := os.ReadFile(os.Args[1]) 17 | if er != nil { 18 | println(er.Error()) 19 | return 20 | } 21 | tx, _ := btc.NewTx(d) // assuming binary format 22 | if tx == nil { 23 | println("Not a valid tx file") 24 | return 25 | } 26 | println(len(tx.TxOut), tx.TxOut[1].Value) 27 | tx.TxOut[len(tx.TxOut)-1].Value -= 3000 // decrease value of the last output 28 | 29 | // store on tisk as hex-encoded 30 | os.WriteFile("newtx.txt", []byte(hex.EncodeToString(tx.Serialize())), 0700) 31 | } 32 | -------------------------------------------------------------------------------- /tools/type2determ/type2determ.go: -------------------------------------------------------------------------------- 1 | // This tool outpus Type-2 deterministic addresses, as described here: 2 | // https://bitcointalk.org/index.php?topic=19137.0 3 | // At input it takes "A_public_key" and "secret" - both values as hex encoded strings. 4 | // Optionally, you can add a third parameter - number of public keys you want to calculate. 5 | package main 6 | 7 | import ( 8 | "os" 9 | "fmt" 10 | "strconv" 11 | "encoding/hex" 12 | "github.com/piotrnar/gocoin/lib/btc" 13 | ) 14 | 15 | 16 | func main() { 17 | var testnet bool 18 | 19 | if len(os.Args) < 3 { 20 | fmt.Println("Specify secret, public_key and optionaly number of addresses you want.") 21 | fmt.Println("Use a negative value for number of addresses, to work with Testnet addresses.") 22 | return 23 | } 24 | public_key, er := hex.DecodeString(os.Args[2]) 25 | if er != nil { 26 | println("Error parsing public_key:", er.Error()) 27 | os.Exit(1) 28 | } 29 | 30 | if len(public_key)==33 && (public_key[0]==2 || public_key[0]==3) { 31 | fmt.Println("Compressed") 32 | } else if len(public_key)==65 && (public_key[0]==4) { 33 | fmt.Println("Uncompressed") 34 | } else { 35 | println("Incorrect public key") 36 | } 37 | 38 | secret, er := hex.DecodeString(os.Args[1]) 39 | if er != nil { 40 | println("Error parsing secret:", er.Error()) 41 | os.Exit(1) 42 | } 43 | 44 | n := int64(25) 45 | 46 | if len(os.Args) > 3 { 47 | n, er = strconv.ParseInt(os.Args[3], 10, 32) 48 | if er != nil { 49 | println("Error parsing number of keys value:", er.Error()) 50 | os.Exit(1) 51 | } 52 | if n == 0 { 53 | return 54 | } 55 | 56 | if n < 0 { 57 | n = -n 58 | testnet = true 59 | } 60 | } 61 | 62 | fmt.Println("# Type-2") 63 | fmt.Println("#", hex.EncodeToString(public_key)) 64 | fmt.Println("#", hex.EncodeToString(secret)) 65 | 66 | for i:=1; i<=int(n); i++ { 67 | fmt.Println(btc.NewAddrFromPubkey(public_key, btc.AddrVerPubkey(testnet)).String(), "TypB", i) 68 | if i >= int(n) { 69 | break 70 | } 71 | 72 | public_key = btc.DeriveNextPublic(public_key, secret) 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tools/type2next/type2next.go: -------------------------------------------------------------------------------- 1 | // This tool outpus Type-2 deterministic addresses, as described here: 2 | // https://bitcointalk.org/index.php?topic=19137.0 3 | // At input it takes "A_public_key" and "B_secret" - both values as hex encoded strings. 4 | // Optionally, you can add a third parameter - number of public keys you want to calculate. 5 | package main 6 | 7 | import ( 8 | "os" 9 | "fmt" 10 | "encoding/hex" 11 | "github.com/piotrnar/gocoin/lib/btc" 12 | ) 13 | 14 | 15 | func main() { 16 | if len(os.Args) < 3 { 17 | fmt.Println("Specify secret and public_key to get the next Type-2 deterministic address") 18 | fmt.Println("Add -t as the third argument to work with Testnet addresses.") 19 | return 20 | } 21 | public_key, er := hex.DecodeString(os.Args[2]) 22 | if er != nil { 23 | println("Error parsing public_key:", er.Error()) 24 | os.Exit(1) 25 | } 26 | 27 | if len(public_key)==33 && (public_key[0]==2 || public_key[0]==3) { 28 | fmt.Println("Compressed") 29 | } else if len(public_key)==65 && (public_key[0]==4) { 30 | fmt.Println("Uncompressed") 31 | } else { 32 | println("Incorrect public key") 33 | } 34 | 35 | secret, er := hex.DecodeString(os.Args[1]) 36 | if er != nil { 37 | println("Error parsing secret:", er.Error()) 38 | os.Exit(1) 39 | } 40 | 41 | testnet := len(os.Args) > 3 && os.Args[3]=="-t" 42 | 43 | // Old address 44 | public_key = btc.DeriveNextPublic(public_key, secret) 45 | 46 | // New address 47 | fmt.Println(btc.NewAddrFromPubkey(public_key, btc.AddrVerPubkey(testnet)).String()) 48 | // New key 49 | fmt.Println(hex.EncodeToString(public_key)) 50 | 51 | } 52 | -------------------------------------------------------------------------------- /tools/utxo/fileinfo.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/binary" 5 | "fmt" 6 | "io" 7 | "os" 8 | 9 | "github.com/piotrnar/gocoin/lib/btc" 10 | ) 11 | 12 | func decode_utxo_header(fn string) { 13 | var buf [48]byte 14 | f, er := os.Open(fn) 15 | if er != nil { 16 | fmt.Println(er.Error()) 17 | return 18 | } 19 | _, er = io.ReadFull(f, buf[:]) 20 | f.Close() 21 | if er != nil { 22 | fmt.Println(er.Error()) 23 | return 24 | } 25 | u64 := binary.LittleEndian.Uint64(buf[:8]) 26 | if (u64 & 0x8000000000000000) != 0 { 27 | fmt.Println("Records: Compressed") 28 | } else { 29 | fmt.Println("Records: Not compressed") 30 | } 31 | fmt.Println("Last Block Height:", uint32(u64)) 32 | fmt.Println("Last Block Hash:", btc.NewUint256(buf[8:40]).String()) 33 | fmt.Println("Number of UTXO records:", binary.LittleEndian.Uint64(buf[40:48])) 34 | os.Exit(0) 35 | } 36 | -------------------------------------------------------------------------------- /tools/verify_script/verify_script.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "unsafe" 6 | "syscall" 7 | "encoding/hex" 8 | "github.com/piotrnar/gocoin/lib/btc" 9 | "github.com/piotrnar/gocoin/lib/script" 10 | ) 11 | 12 | const ( 13 | DllName = "libbitcoinconsensus-0.dll" 14 | ProcName = "bitcoinconsensus_verify_script_with_amount" 15 | ) 16 | 17 | 18 | var ( 19 | bitcoinconsensus_verify_script_with_amount *syscall.Proc 20 | ) 21 | 22 | 23 | func call_consensus_lib(pkScr []byte, amount uint64, i int, tx *btc.Tx, ver_flags uint32) bool { 24 | var tmp []byte 25 | if len(pkScr)!=0 { 26 | tmp = make([]byte, len(pkScr)) 27 | copy(tmp, pkScr) 28 | } 29 | txTo := tx.Serialize() 30 | var pkscr_ptr, pkscr_len uintptr // default to 0/null 31 | if pkScr != nil { 32 | pkscr_ptr = uintptr(unsafe.Pointer(&pkScr[0])) 33 | pkscr_len = uintptr(len(pkScr)) 34 | } 35 | r1, _, _ := syscall.Syscall9(bitcoinconsensus_verify_script_with_amount.Addr(), 8, 36 | pkscr_ptr, pkscr_len, uintptr(amount), 37 | uintptr(unsafe.Pointer(&txTo[0])), uintptr(len(txTo)), 38 | uintptr(i), uintptr(ver_flags), 0, 0) 39 | 40 | return r1 == 1 41 | } 42 | 43 | 44 | func init() { 45 | dll, er := syscall.LoadDLL(DllName) 46 | if er!=nil { 47 | println(er.Error()) 48 | println("WARNING: Consensus verificatrion disabled") 49 | return 50 | } 51 | bitcoinconsensus_verify_script_with_amount, er = dll.FindProc(ProcName) 52 | if er!=nil { 53 | println(er.Error()) 54 | println("WARNING: Consensus verificatrion disabled") 55 | return 56 | } 57 | fmt.Println("Using", DllName, "to ensure consensus rules") 58 | } 59 | /* 60 | */ 61 | 62 | func main() { 63 | pkscript, _ := hex.DecodeString("a9143d98738ba9013a53acc34686cd8e8b2ebc3612e587") 64 | d, _ := hex.DecodeString("01000000010c3e18ff26e98ba39381c84d2fb9e8e198e63d0b3697f9bd57f63577c96da23f00000000d5483045022100fc4f7bfa3c536e743b02af8b7de5d4052f43db54f59692478b25c585b9df211a02203cfcfc0ed618fae6aa49b11e803ec4e5654551fb52fe2d026929f4a307fe2ef0012103d7c6052544bc42eb2bc0d27c884016adb933f15576a1a2d21cd4dd0f2de0c37d004c67635221025e37e03703f001de34123b513beaf0e4044a2dd39a1dd92ec1706f184920031a2103d7c6052544bc42eb2bc0d27c884016adb933f15576a1a2d21cd4dd0f2de0c37d52ae67010ab27576a914937fe2ee82229d282edec2606c70e755875334c088ac680f0000000130750000000000001976a914937fe2ee82229d282edec2606c70e755875334c088ac0f000000") 65 | tx, _ := btc.NewTx(d) 66 | tx.Hash.Calc(d) 67 | println("txid", tx.Hash.String()) 68 | i := 0 69 | flags := uint32(script.STANDARD_VERIFY_FLAGS) //& ^uint32(script.VER_MINDATA) 70 | amount := uint64(1000000) 71 | //script.DBG_SCR = true 72 | //script.DBG_ERR = true 73 | res := script.VerifyTxScript(pkscript, &script.SigChecker{Amount:amount, Idx:i, Tx:tx}, flags) 74 | if bitcoinconsensus_verify_script_with_amount!=nil { 75 | resc := call_consensus_lib(pkscript, amount, i, tx, flags) 76 | println(res, resc) 77 | } else { 78 | println(res) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /tools/verify_tx/verify_tx.go: -------------------------------------------------------------------------------- 1 | // +build windows 2 | 3 | // Make sure you have proper "libbitcoinconsensus-0.dll" in a folder where OS can find it. 4 | 5 | package main 6 | 7 | import ( 8 | "encoding/hex" 9 | "fmt" 10 | "github.com/piotrnar/gocoin/lib/btc" 11 | "github.com/piotrnar/gocoin/lib/script" 12 | "syscall" 13 | "unsafe" 14 | ) 15 | 16 | const ( 17 | DllName = "libbitcoinconsensus-0.dll" 18 | ProcName = "bitcoinconsensus_verify_script" 19 | ) 20 | 21 | 22 | var ( 23 | bitcoinconsensus_verify_script *syscall.Proc 24 | use_consensus_lib bool 25 | ) 26 | 27 | 28 | func consensus_verify_script(pkScr []byte, i int, tx *btc.Tx, ver_flags uint32) bool { 29 | txTo := tx.Serialize() 30 | 31 | var pkscr_ptr, pkscr_len uintptr // default to 0/null 32 | if pkScr != nil { 33 | pkscr_ptr = uintptr(unsafe.Pointer(&pkScr[0])) 34 | pkscr_len = uintptr(len(pkScr)) 35 | } 36 | r1, _, _ := syscall.Syscall9(bitcoinconsensus_verify_script.Addr(), 7, 37 | pkscr_ptr, pkscr_len, 38 | uintptr(unsafe.Pointer(&txTo[0])), uintptr(len(txTo)), 39 | uintptr(i), uintptr(ver_flags), 0, 0, 0) 40 | 41 | return r1 == 1 42 | } 43 | 44 | 45 | func load_dll() { 46 | dll, er := syscall.LoadDLL(DllName) 47 | if er!=nil { 48 | println(er.Error()) 49 | println("WARNING: Consensus verificatrion disabled") 50 | return 51 | } 52 | bitcoinconsensus_verify_script, er = dll.FindProc(ProcName) 53 | if er!=nil { 54 | println(er.Error()) 55 | println("WARNING: Consensus verificatrion disabled") 56 | return 57 | } 58 | fmt.Println("Using", DllName, "to ensure consensus rules") 59 | use_consensus_lib = true 60 | } 61 | 62 | func main() { 63 | load_dll() 64 | pkscript, _ := hex.DecodeString("76a9147d22f6c9cca35cb4071971fe442da58546aaeb5988ac") 65 | d, _ := hex.DecodeString("0100000002232e0afdd9bcad5e3ace8a19ab8ad0ed8cebd6213b098e36cdc8b25af1d5cd30010000006b483045022077768255f192427bd2841555cfc86fdb7332e18c5c530b3b6028cd034a339f9c022100b3876037f63559ca8a2766a86c8dc62d41c869abc539ab983ce8eccf448f117f012102a33ac1e78cd3ff49bde292da2efcf273509d0869fe81571dfb49528c8287a8fcffffffff2fc90cf473e6ce6177818f705f6e96c7ad42f921f23b660ea27f653346e6a8a9010000006a47304402206d5be8061f712fba560b9966e037f7c53cff377b0c15d8c62bd0a2bcb195048602200522601341cdf574e3a39ba0397d8fe5608e37fd46b3fda2684386207ca9bf69012102a33ac1e78cd3ff49bde292da2efcf273509d0869fe81571dfb49528c8287a8fcffffffff0200a86100000000001976a914ff8e92b694527dd77660f873eb3a86eda5ed459f88ac70110100000000001976a9147d22f6c9cca35cb4071971fe442da58546aaeb5988ac00000000") 66 | tx, _ := btc.NewTx(d) 67 | i := 0 68 | value := uint64(1000000) 69 | flags := uint32(script.STANDARD_VERIFY_FLAGS) 70 | println(flags) 71 | res := script.VerifyTxScript(pkscript, &script.SigChecker{Amount:value, Idx:i, Tx:tx}, flags) 72 | println("Gocoin:", res) 73 | if use_consensus_lib { 74 | res = consensus_verify_script(pkscript, i, tx, flags) 75 | println("Consen:", res) 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /version.go: -------------------------------------------------------------------------------- 1 | package gocoin 2 | 3 | import ( 4 | // This file use to be only to make "go get" working. 5 | ) 6 | 7 | const Version = "1.11.0pre" 8 | -------------------------------------------------------------------------------- /wallet/.gitignore: -------------------------------------------------------------------------------- 1 | wallet 2 | *.txt 3 | .others 4 | .secret 5 | balance/ 6 | -------------------------------------------------------------------------------- /wallet/encrypt.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "crypto/aes" 5 | "crypto/cipher" 6 | "crypto/rand" 7 | "io" 8 | "io/ioutil" 9 | "strings" 10 | ) 11 | 12 | func encrypt_file(fn string, key []byte) (outfn string) { 13 | dat, er := ioutil.ReadFile(fn) 14 | if er != nil { 15 | println(er.Error()) 16 | cleanExit(1) 17 | } 18 | 19 | cphr, er := aes.NewCipher(key) 20 | if er != nil { 21 | println(er.Error()) 22 | cleanExit(1) 23 | } 24 | 25 | gcm, er := cipher.NewGCM(cphr) 26 | if er != nil { 27 | println(er.Error()) 28 | cleanExit(1) 29 | } 30 | 31 | nonce := make([]byte, gcm.NonceSize()) 32 | if _, er = io.ReadFull(rand.Reader, nonce); er != nil { 33 | println(er.Error()) 34 | cleanExit(1) 35 | } 36 | 37 | outfn = fn + ".enc" 38 | 39 | if er = ioutil.WriteFile(outfn, gcm.Seal(nonce, nonce, dat, nil), 0600); er != nil { 40 | println(er.Error()) 41 | cleanExit(1) 42 | } 43 | 44 | return 45 | } 46 | 47 | func decrypt_file(fn string, key []byte) (outfn string) { 48 | ciphertext, er := ioutil.ReadFile(fn) 49 | if er != nil { 50 | println(er.Error()) 51 | cleanExit(1) 52 | } 53 | 54 | cphr, er := aes.NewCipher(key) 55 | if er != nil { 56 | println(er.Error()) 57 | cleanExit(1) 58 | } 59 | 60 | gcmDecrypt, er := cipher.NewGCM(cphr) 61 | if er != nil { 62 | println(er.Error()) 63 | cleanExit(1) 64 | } 65 | 66 | nonceSize := gcmDecrypt.NonceSize() 67 | if len(ciphertext) < nonceSize { 68 | println("ERROR: Encrypted message is shorter than the nonce size") 69 | cleanExit(1) 70 | } 71 | nonce, encryptedMessage := ciphertext[:nonceSize], ciphertext[nonceSize:] 72 | plaintext, er := gcmDecrypt.Open(nil, nonce, encryptedMessage, nil) 73 | if er != nil { 74 | println(er.Error()) 75 | cleanExit(1) 76 | } 77 | 78 | if strings.HasSuffix(fn, ".enc") { 79 | if len(fn) <= 4 { 80 | outfn = "out.tmp" 81 | } else { 82 | outfn = fn[:len(fn)-4] 83 | } 84 | } else { 85 | outfn = fn + ".dec" 86 | } 87 | 88 | if er = ioutil.WriteFile(outfn, plaintext, 0600); er != nil { 89 | println(er.Error()) 90 | cleanExit(1) 91 | } 92 | 93 | return 94 | } 95 | -------------------------------------------------------------------------------- /wallet/send.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "github.com/piotrnar/gocoin/lib/btc" 6 | "os" 7 | "strings" 8 | ) 9 | 10 | // oneSendTo is resolved while parsing "-send" parameter. 11 | type oneSendTo struct { 12 | addr *btc.BtcAddr 13 | amount uint64 14 | } 15 | 16 | var ( 17 | // set in parse_spend(): 18 | spendBtc, feeBtc, changeBtc uint64 19 | sendTo []oneSendTo 20 | ) 21 | 22 | // parse_spend parses the "-send ..." parameter. 23 | func parse_spend() { 24 | outs := strings.Split(*send, ",") 25 | 26 | for i := range outs { 27 | tmp := strings.Split(strings.Trim(outs[i], " "), "=") 28 | if len(tmp) != 2 { 29 | println("The outputs must be in a format address1=amount1[,addressN=amountN]") 30 | cleanExit(1) 31 | } 32 | 33 | a, e := btc.NewAddrFromString(tmp[0]) 34 | if e != nil { 35 | println("NewAddrFromString:", e.Error()) 36 | cleanExit(1) 37 | } 38 | assert_address_version(a) 39 | 40 | am, er := btc.StringToSatoshis(tmp[1]) 41 | if er != nil { 42 | println("Incorrect amount: ", tmp[1], er.Error()) 43 | cleanExit(1) 44 | } 45 | if *subfee && i == 0 { 46 | am -= curFee 47 | } 48 | 49 | sendTo = append(sendTo, oneSendTo{addr: a, amount: am}) 50 | spendBtc += am 51 | } 52 | } 53 | 54 | // parse_batch parses the "-batch ..." parameter. 55 | func parse_batch() { 56 | f, e := os.Open(*batch) 57 | if e == nil { 58 | defer f.Close() 59 | td := bufio.NewReader(f) 60 | var lcnt int 61 | for { 62 | li, _, _ := td.ReadLine() 63 | if li == nil { 64 | break 65 | } 66 | lcnt++ 67 | tmp := strings.SplitN(strings.Trim(string(li), " "), "=", 2) 68 | if len(tmp) < 2 { 69 | println("Error in the batch file line", lcnt) 70 | cleanExit(1) 71 | } 72 | if tmp[0][0] == '#' { 73 | continue // Just a comment-line 74 | } 75 | 76 | a, e := btc.NewAddrFromString(tmp[0]) 77 | if e != nil { 78 | println("NewAddrFromString:", e.Error()) 79 | cleanExit(1) 80 | } 81 | assert_address_version(a) 82 | 83 | am, e := btc.StringToSatoshis(tmp[1]) 84 | if e != nil { 85 | println("StringToSatoshis:", e.Error()) 86 | cleanExit(1) 87 | } 88 | 89 | sendTo = append(sendTo, oneSendTo{addr: a, amount: am}) 90 | spendBtc += am 91 | } 92 | } else { 93 | println(e.Error()) 94 | cleanExit(1) 95 | } 96 | } 97 | 98 | // send_request returns true if spend operation has been requested. 99 | func send_request() bool { 100 | feeBtc = curFee 101 | if *send != "" { 102 | parse_spend() 103 | } 104 | if *batch != "" { 105 | parse_batch() 106 | } 107 | return len(sendTo) > 0 108 | } 109 | -------------------------------------------------------------------------------- /wallet/signmsg.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "encoding/base64" 5 | "encoding/hex" 6 | "fmt" 7 | "io/ioutil" 8 | "os" 9 | 10 | "github.com/piotrnar/gocoin/lib/btc" 11 | "github.com/piotrnar/gocoin/lib/others/ltc" 12 | ) 13 | 14 | // sign_message signs either a message or a raw hash. 15 | func sign_message() { 16 | var hash []byte 17 | var signkey *btc.PrivateAddr = address_to_key(*signaddr) 18 | if signkey == nil { 19 | println("You do not have a private key for", *signaddr) 20 | return 21 | } 22 | 23 | if *signhash != "" { 24 | hash, er := hex.DecodeString(*signhash) 25 | if er != nil { 26 | println("Incorrect content of -hash parameter") 27 | println(er.Error()) 28 | return 29 | } else if len(hash) > 0 { 30 | txsig := new(btc.Signature) 31 | txsig.HashType = 0x01 32 | r, s, e := btc.EcdsaSign(signkey.Key, hash) 33 | if e != nil { 34 | println(e.Error()) 35 | return 36 | } 37 | txsig.R.Set(r) 38 | txsig.S.Set(s) 39 | fmt.Println("PublicKey:", hex.EncodeToString(signkey.BtcAddr.Pubkey)) 40 | fmt.Println(hex.EncodeToString(txsig.Bytes())) 41 | return 42 | } 43 | } 44 | 45 | var msg []byte 46 | if *message == "" { 47 | msg, _ = ioutil.ReadAll(os.Stdin) 48 | } else { 49 | msg = []byte(*message) 50 | } 51 | 52 | hash = make([]byte, 32) 53 | if litecoin { 54 | ltc.HashFromMessage(msg, hash) 55 | } else { 56 | btc.HashFromMessage(msg, hash) 57 | } 58 | 59 | btcsig := new(btc.Signature) 60 | var sb [65]byte 61 | sb[0] = 27 62 | if signkey.IsCompressed() { 63 | sb[0] += 4 64 | } 65 | 66 | r, s, e := btc.EcdsaSign(signkey.Key, hash) 67 | if e != nil { 68 | println(e.Error()) 69 | return 70 | } 71 | btcsig.R.Set(r) 72 | btcsig.S.Set(s) 73 | 74 | rd := btcsig.R.Bytes() 75 | sd := btcsig.S.Bytes() 76 | copy(sb[1+32-len(rd):], rd) 77 | copy(sb[1+64-len(sd):], sd) 78 | 79 | rpk := btcsig.RecoverPublicKey(hash[:], 0) 80 | sa := btc.NewAddrFromPubkey(rpk.Bytes(signkey.IsCompressed()), signkey.BtcAddr.Version) 81 | if sa.Hash160 == signkey.BtcAddr.Hash160 { 82 | fmt.Println(base64.StdEncoding.EncodeToString(sb[:])) 83 | return 84 | } 85 | 86 | rpk = btcsig.RecoverPublicKey(hash[:], 1) 87 | sa = btc.NewAddrFromPubkey(rpk.Bytes(signkey.IsCompressed()), signkey.BtcAddr.Version) 88 | if sa.Hash160 == signkey.BtcAddr.Hash160 { 89 | sb[0]++ 90 | fmt.Println(base64.StdEncoding.EncodeToString(sb[:])) 91 | return 92 | } 93 | println("Something went wrong. The message has not been signed.") 94 | } 95 | -------------------------------------------------------------------------------- /website/.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine on 2 | Options +FollowSymLinks 3 | 4 | RewriteRule ^gocoin_([a-z0-9_\-]+).html$ page.php\?id=$1 [L] 5 | 6 | RewriteRule ^$ page.php [L] 7 | RewriteRule ^/$ page.php [L] 8 | RewriteRule ^index.html$ page.php [L] 9 | RewriteRule ^index.php$ page.php [L] 10 | 11 | -------------------------------------------------------------------------------- /website/2503-fi-cod_effect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/2503-fi-cod_effect.png -------------------------------------------------------------------------------- /website/2503-fi-twaek_effect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/2503-fi-twaek_effect.png -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | This is the source code of [gocoin.pl](https://gocoin.pl) website 2 | -------------------------------------------------------------------------------- /website/d3_quick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/d3_quick.png -------------------------------------------------------------------------------- /website/d3_turbo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/d3_turbo.png -------------------------------------------------------------------------------- /website/dd_quick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/dd_quick.png -------------------------------------------------------------------------------- /website/de_gocoin_vs_core.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/de_gocoin_vs_core.png -------------------------------------------------------------------------------- /website/dw32_quick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/dw32_quick.png -------------------------------------------------------------------------------- /website/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/favicon.ico -------------------------------------------------------------------------------- /website/fin_quick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/fin_quick.png -------------------------------------------------------------------------------- /website/fin_turbo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/fin_turbo.png -------------------------------------------------------------------------------- /website/gocoin_index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Gocoin

7 | Gocoin is a full Bitcoin solution written in Go language (golang).
8 |
9 | The software's architecture is focused on maximum security and good performance.
10 |
11 | The client (p2p node) is an application independent from the wallet.
12 |
13 | The wallet is deterministic and password seeded. As long as you remember the password, you do not need any backups of your wallet.
14 |
15 | In addition there is also a set of more and less useful tools. They are all inside the tools/ folder. Each source file in that folder is a separate tool.
16 | 17 | -------------------------------------------------------------------------------- /website/gocoin_installation.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Installation

7 |

System requirements

8 | 9 | If you only want to use the wallet with the corresponding balio tool, 10 | you can run it on anything that your go compiler can build for.
11 | For instance, it will work on even the oldest Raspberry Pi model A with 256MB of RAM. 12 |

13 | 14 | However, in order to run the full node (client), you need a 64-bit OS with a decent amount of RAM.
15 | See the README.md file 16 | for the current RAM requirement.
17 |
18 | You also need a file system that supports large files (bigger than 4GB) and a decent size of a free space on it.
19 |
20 | Note that you can purge blocks from disk, allowing you to run the node with a limited storage (e.g. 30GB).
21 | See config file values: 22 | Memory.MaxDataFileMB and Memory.DataFilesKeep (set this one to non-zero, e.g. 10)
23 |
24 | The host OS is not important, as it runs equally well on Windows, Linux or Mac.
25 | To briefly assess a performance of a chosen platform, you can use the benchmark below (lower time = better performance).
26 |
27 | 
28 | 	package main
29 | 
30 | 	import (
31 | 		"fmt"
32 | 		"math/rand"
33 | 		"time"
34 | 	)
35 | 
36 | 	const (
37 | 		MAPSIZE = 8
38 | 		RECNT   = int(20e6)
39 | 	)
40 | 
41 | 	func main() {
42 | 		tm := make(map[[MAPSIZE]byte]bool, RECNT)
43 | 		var k [MAPSIZE]byte
44 | 		fmt.Println("Plase wait...")
45 | 		sta := time.Now()
46 | 		for i := 0; i < RECNT; i++ {
47 | 			rand.Read(k[:])
48 | 			tm[k] = true
49 | 		}
50 | 		fmt.Printf("All %d records loaded in %s\n", RECNT, time.Since(sta).String())
51 | 	}
52 | 
53 | 
54 |
55 |

Build from source

56 | 57 | You will need git and go commands installed in your system.
58 |
59 | Download the source code from github to a local folder of your choice, e.g. by executing: 60 | git clone https://github.com/piotrnar/gocoin.git 61 |
62 | Then go to gocoin/client/ and execute go build there. 63 | Do the same in gocoin/wallet/, to build the wallet.
64 |
65 | 66 | The process is also described in the main README.md file of the github repo 67 | piotrnar/gocoin
68 |
69 | 70 |

Binaries

71 | The binaries (usually not the latest version) for Windows and Linux can be downloaded from 72 | sourceforge.net 73 | 74 | -------------------------------------------------------------------------------- /website/gocoin_manual.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

User Manual

7 |

Client and wallet

8 | The two basic components of the software are: 9 |
  • client - online component: original implementation of a full bitcoin node
  • 10 |
  • wallet - application designed to be used offline as a cold storage wallet
  • 11 |
12 | 13 |

Wallet without client

14 | It is also possible to use the wallet without the client. 15 | For such purpose there is a tool called balio.
16 | The tool can download the balance data from popular block explorers and save it on disk in a format recognized by the wallet.
17 | 18 |

User interface

19 | The applications are console only (no GUI window), although the client node has a fairly functional and quite convenient web interface 20 | (to be used with a web browser). 21 | 22 | 23 |
24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /website/gocoin_manual_client.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |

Client node

7 | Run client -h to see all available command line switches. Some example ones are: 8 |
9 |
10 | -t - use Testnet (instead of regular bitcoin network)
11 | -ul=NN - set maximum upload speed to NN kilobytes per second
12 | -dl=NN - set maximum download speed to NN kilobytes per second
13 |
14 |
15 | To run the client on a remote Linux server (via ssh connection), you probably want to get adventage of screen command. 16 |
17 |

TextUI

18 | When the client is already running you have an interactive, text command based interface, on the console.
19 | Type help to see the possible commands. 20 |
21 | 22 |

WebUI

23 | There is also a web interface that you can operate with a web browser.
24 |
25 | 26 | Make sure to have the www/ folder in the location where you execute the client from.
27 | The folder contains files that are an essencial part of the WebUI application.
28 |
29 | WebUI application is tested with Google Chrome, but should be compatible with any modern web browser.
30 |
31 | By default (for security reasons) WebUI is available only from a local host, via http://127.0.0.1:8833/
32 |
33 |

Remote server

34 | In order to use WebUI securely on a remote server, set up ssh tunneling to port 8833.
35 |
36 |

Local network

37 | If you run the node on a local network and want to have access to its WebUI from different computers:
38 |
  • Open gocoin.conf file in a text editor (or edit it at the Home page of the WebUI).
  • 39 |
  • Change Interface value in the config file to :8833 (Note: this binds the web service to all network interfaces).
  • 40 |
  • Change AllowedIP value to allow access from all the addresses you need - e.g. 127.0.0.1,192.168.0.0/16 (Note: 0.0.0.0/0 allows to connect from anywhere).
  • 41 |
  • Remember to save the new config and then restart your node.
42 |
43 | Read more about the config file at the config file page. 44 | 45 | -------------------------------------------------------------------------------- /website/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Gocoin 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /website/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/logo.png -------------------------------------------------------------------------------- /website/menu.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /website/page.php: -------------------------------------------------------------------------------- 1 | "); 11 | if ($beg!==FALSE) { 12 | $beg += strlen($tag)+2; 13 | } 14 | $end = strpos($content, ""); 15 | if ($end===FALSE) { 16 | $end = strlen($content); 17 | } 18 | return substr($content, $beg, $end-$beg); 19 | } 20 | 21 | 22 | function get_body($fn) { 23 | $content = file_get_contents($fn); 24 | return get_between_tags($content, "body"); 25 | } 26 | 27 | $menu = get_body("menu.html"); 28 | $fielname = "gocoin_$page.html"; 29 | 30 | // add class="selected" to the main menu 31 | $apos = strpos($menu, 'href="' . $fielname); 32 | if ($apos!==FALSE) { 33 | $menu = substr($menu, 0, $apos) . 'class="selected" ' . substr($menu, $apos); 34 | } 35 | 36 | $content = get_body($fielname); 37 | $title = get_between_tags($content, "h1"); 38 | 39 | 40 | echo ' 41 | 42 | 43 | Gocoin: '.$title.' 44 | 45 | 46 | 47 | 48 | 51 |
'; 49 | echo $menu; 50 | echo ''; 52 | echo $content; 53 | echo 54 | '
55 | 56 | '; 57 | 58 | ?> -------------------------------------------------------------------------------- /website/quick_sync_gocoin_vs_core.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/quick_sync_gocoin_vs_core.png -------------------------------------------------------------------------------- /website/quick_sync_gocoin_vs_core_mar25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/quick_sync_gocoin_vs_core_mar25.png -------------------------------------------------------------------------------- /website/rep_quick.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/piotrnar/gocoin/3d9458514f7770744fd9e4e4fa60ff4ff2fdeafa/website/rep_quick.png -------------------------------------------------------------------------------- /website/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | //font-family: Arial, Verdana, sans-serif; 3 | line-height:1.5; 4 | } 5 | 6 | td { 7 | line-height:1.5; 8 | } 9 | 10 | a { 11 | color:blue; 12 | text-decoration:none; 13 | } 14 | 15 | a:visited { 16 | color:blue; 17 | text-decoration:none; 18 | } 19 | 20 | a:hover { 21 | background-color:yellow; 22 | } 23 | 24 | a.selected { 25 | background-color:pink; 26 | } 27 | 28 | code { 29 | color: #006000; 30 | background-color: #eeeeee; 31 | } 32 | 33 | ul { 34 | padding-left:20px; 35 | margin-top:0px; 36 | margin-bottom:0px; 37 | } 38 | 39 | .cfg_name { 40 | font-family: monospace; 41 | font-weight: bold; 42 | } 43 | 44 | .cfg_type { 45 | font-weight: bold; 46 | } 47 | 48 | .cfg_info { 49 | font-style: italic; 50 | } 51 | 52 | pre { 53 | background-color:#d0d0d0; 54 | font-size:80%; 55 | } 56 | 57 | .bigger { 58 | font-size:120%; 59 | } 60 | 61 | tr.even { 62 | background-color:#fcfff8; 63 | } 64 | tr.odd { 65 | background-color:#f8f8ff; 66 | } 67 | --------------------------------------------------------------------------------