diff --git a/.gitignore b/.gitignore index fb777b06e..5b2f87a93 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dcrwallet vendor *~ .vscode +.idea diff --git a/chain/go.sum b/chain/go.sum index 5dbc2c13d..bdfe7710c 100644 --- a/chain/go.sum +++ b/chain/go.sum @@ -78,6 +78,8 @@ github.com/decred/dcrd/wire v1.0.1 h1:yhLSapj1ZF3LT/7cu7Ur9+chEuIV8gnrf6DqWDrFaV github.com/decred/dcrd/wire v1.0.1/go.mod h1:zpKZnBiN59CrzfXFigwgXmUDVYf34OLbEr8xwAwriHc= github.com/decred/dcrd/wire v1.1.0 h1:G+3CugtxNbToUN8RKWqm74yLfzJJ2BKMOr2RgWc4TyY= github.com/decred/dcrd/wire v1.1.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/EqcffvU8fJHM= +github.com/decred/dcrwallet/pgpwordlist v1.0.0/go.mod h1:Fek3uYn+9DnEFIreA/8PnTIXUl2lBO64JpEBkL9BXtk= +github.com/decred/dcrwallet/walletseed v1.0.0/go.mod h1:xSF6hZW+5Xhm0jJFsI5jQSfViuZUQJoDXa/cQxtgncs= github.com/decred/slog v1.0.0 h1:Dl+W8O6/JH6n2xIFN2p3DNjCmjYwvrXsjlSJTQQ4MhE= github.com/decred/slog v1.0.0/go.mod h1:zR98rEZHSnbZ4WHZtO0iqmSZjDLKhkXfrPTZQKtAonQ= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/spv/go.mod b/spv/go.mod index 03c04ad11..e46638227 100644 --- a/spv/go.mod +++ b/spv/go.mod @@ -5,7 +5,7 @@ require ( github.com/decred/dcrd/blockchain/stake v1.0.1 github.com/decred/dcrd/chaincfg/chainhash v1.0.1 github.com/decred/dcrd/dcrutil v1.1.1 - github.com/decred/dcrd/gcs v1.0.1 + github.com/decred/dcrd/gcs v1.0.2 github.com/decred/dcrd/txscript v1.0.1 github.com/decred/dcrd/wire v1.1.0 github.com/decred/dcrwallet/errors v1.0.0 diff --git a/spv/go.sum b/spv/go.sum index d6f337af9..2589a2729 100644 --- a/spv/go.sum +++ b/spv/go.sum @@ -17,6 +17,7 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= +github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/decred/base58 v1.0.0 h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w= github.com/decred/base58 v1.0.0/go.mod h1:LLY1p5e3g91byL/UO1eiZaYd+uRoVRarybgcoymu9Ks= github.com/decred/dcrd v1.2.1-0.20180801202239-0761de129164 h1:wYjHNfbzWlLpFuqlVVNtXRmqrEETEDv7KWEf7psUWnc= @@ -28,6 +29,7 @@ github.com/decred/dcrd/addrmgr v1.0.2/go.mod h1:gNnmTuf/Xkg8ZX3j5GXbajzPrSdf5bA7 github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1 h1:7cviDS26sZ9ZyTFka3aC9C/EChXBslmAvse+4nF5d60= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1 h1:IYGsNZRyMUsoFtVAUjd7XIccrIQ4YIqDeNzQJCjyS8A= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= @@ -70,6 +72,7 @@ github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhlu github.com/decred/dcrd/gcs v1.0.0/go.mod h1:5uHIPAzn4SdGP2/FhVBK2YdAoKmufds3ZI8yNzojUCM= github.com/decred/dcrd/gcs v1.0.1 h1:MpJXLskT41+JDaD3RLdlSlF2vlu1sxPpZgiRI7FVTWw= github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19TPo1i9g= +github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/hdkeychain v1.0.0 h1:YZPNvvFYME29nnjLl1c4v+Wusrx4BzUCYdRYmUdRnPI= github.com/decred/dcrd/hdkeychain v1.0.0/go.mod h1:ZLzIMYN4rLNQPdy2I5FYtdYevIKwmUVo1Sz9x909kYc= github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= @@ -89,6 +92,8 @@ github.com/decred/dcrd/wire v1.0.1 h1:yhLSapj1ZF3LT/7cu7Ur9+chEuIV8gnrf6DqWDrFaV github.com/decred/dcrd/wire v1.0.1/go.mod h1:zpKZnBiN59CrzfXFigwgXmUDVYf34OLbEr8xwAwriHc= github.com/decred/dcrd/wire v1.1.0 h1:G+3CugtxNbToUN8RKWqm74yLfzJJ2BKMOr2RgWc4TyY= github.com/decred/dcrd/wire v1.1.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/EqcffvU8fJHM= +github.com/decred/dcrwallet/pgpwordlist v1.0.0/go.mod h1:Fek3uYn+9DnEFIreA/8PnTIXUl2lBO64JpEBkL9BXtk= +github.com/decred/dcrwallet/walletseed v1.0.0/go.mod h1:xSF6hZW+5Xhm0jJFsI5jQSfViuZUQJoDXa/cQxtgncs= github.com/decred/slog v1.0.0 h1:Dl+W8O6/JH6n2xIFN2p3DNjCmjYwvrXsjlSJTQQ4MhE= github.com/decred/slog v1.0.0/go.mod h1:zR98rEZHSnbZ4WHZtO0iqmSZjDLKhkXfrPTZQKtAonQ= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/ticketbuyer/go.mod b/ticketbuyer/go.mod index 388b29cdc..ce8a78ad9 100644 --- a/ticketbuyer/go.mod +++ b/ticketbuyer/go.mod @@ -1,7 +1,7 @@ module github.com/decred/dcrwallet/ticketbuyer require ( - github.com/decred/dcrd/blockchain v1.0.1 + github.com/decred/dcrd/blockchain v1.0.2 github.com/decred/dcrd/chaincfg v1.1.1 github.com/decred/dcrd/dcrjson v1.0.0 github.com/decred/dcrd/dcrutil v1.1.1 diff --git a/ticketbuyer/go.sum b/ticketbuyer/go.sum index 29cc4e80b..2492ea3a4 100644 --- a/ticketbuyer/go.sum +++ b/ticketbuyer/go.sum @@ -14,11 +14,13 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= +github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/decred/base58 v1.0.0 h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w= github.com/decred/base58 v1.0.0/go.mod h1:LLY1p5e3g91byL/UO1eiZaYd+uRoVRarybgcoymu9Ks= github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1 h1:7cviDS26sZ9ZyTFka3aC9C/EChXBslmAvse+4nF5d60= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1 h1:IYGsNZRyMUsoFtVAUjd7XIccrIQ4YIqDeNzQJCjyS8A= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= @@ -55,6 +57,7 @@ github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhlu github.com/decred/dcrd/gcs v1.0.0/go.mod h1:5uHIPAzn4SdGP2/FhVBK2YdAoKmufds3ZI8yNzojUCM= github.com/decred/dcrd/gcs v1.0.1 h1:MpJXLskT41+JDaD3RLdlSlF2vlu1sxPpZgiRI7FVTWw= github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19TPo1i9g= +github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= github.com/decred/dcrd/hdkeychain v1.1.0/go.mod h1:zyUZtZ3PdnTPHt2XUr1x76b8ZuiM+9aVkP8Rq8Scp1k= github.com/decred/dcrd/mempool v1.0.1 h1:xZOfwGmVbWfKDNztVgsVO/GkMmiZn3MMfDDVE07ZKKs= @@ -72,6 +75,8 @@ github.com/decred/dcrd/wire v1.0.1 h1:yhLSapj1ZF3LT/7cu7Ur9+chEuIV8gnrf6DqWDrFaV github.com/decred/dcrd/wire v1.0.1/go.mod h1:zpKZnBiN59CrzfXFigwgXmUDVYf34OLbEr8xwAwriHc= github.com/decred/dcrd/wire v1.1.0 h1:G+3CugtxNbToUN8RKWqm74yLfzJJ2BKMOr2RgWc4TyY= github.com/decred/dcrd/wire v1.1.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/EqcffvU8fJHM= +github.com/decred/dcrwallet/pgpwordlist v1.0.0/go.mod h1:Fek3uYn+9DnEFIreA/8PnTIXUl2lBO64JpEBkL9BXtk= +github.com/decred/dcrwallet/walletseed v1.0.0/go.mod h1:xSF6hZW+5Xhm0jJFsI5jQSfViuZUQJoDXa/cQxtgncs= github.com/decred/slog v1.0.0 h1:Dl+W8O6/JH6n2xIFN2p3DNjCmjYwvrXsjlSJTQQ4MhE= github.com/decred/slog v1.0.0/go.mod h1:zR98rEZHSnbZ4WHZtO0iqmSZjDLKhkXfrPTZQKtAonQ= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/ticketbuyer/v2/go.sum b/ticketbuyer/v2/go.sum index 29cc4e80b..2492ea3a4 100644 --- a/ticketbuyer/v2/go.sum +++ b/ticketbuyer/v2/go.sum @@ -14,11 +14,13 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dchest/blake256 v1.0.0 h1:6gUgI5MHdz9g0TdrgKqXsoDX+Zjxmm1Sc6OsoGru50I= github.com/dchest/blake256 v1.0.0/go.mod h1:xXNWCE1jsAP8DAjP+rKw2MbeqLczjI3TRx2VK+9OEYY= +github.com/dchest/siphash v1.2.0/go.mod h1:q+IRvb2gOSrUnYoPqHiyHXS0FOBBOdl6tONBlVnOnt4= github.com/decred/base58 v1.0.0 h1:BVi1FQCThIjZ0ehG+I99NJ51o0xcc9A/fDKhmJxY6+w= github.com/decred/base58 v1.0.0/go.mod h1:LLY1p5e3g91byL/UO1eiZaYd+uRoVRarybgcoymu9Ks= github.com/decred/dcrd/blockchain v1.0.0/go.mod h1:nNMgOz12wlasmEJDCuSuMWYSnjDdmB4l38GKuQ/Yd+8= github.com/decred/dcrd/blockchain v1.0.1 h1:7cviDS26sZ9ZyTFka3aC9C/EChXBslmAvse+4nF5d60= github.com/decred/dcrd/blockchain v1.0.1/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= +github.com/decred/dcrd/blockchain v1.0.2/go.mod h1:R/4XnwNOTj5IP8jQIUzrJ8zhr/7EOk09IMODwBamZoI= github.com/decred/dcrd/blockchain/stake v1.0.0/go.mod h1:opuzF8UouYyQyRJVF00Rdd7OgWb1WKyy1pyU0QYaxz0= github.com/decred/dcrd/blockchain/stake v1.0.1 h1:IYGsNZRyMUsoFtVAUjd7XIccrIQ4YIqDeNzQJCjyS8A= github.com/decred/dcrd/blockchain/stake v1.0.1/go.mod h1:hgoGmWMIu2LLApBbcguVpzCEEfX7M2YhuMrQdpohJzc= @@ -55,6 +57,7 @@ github.com/decred/dcrd/dcrutil v1.1.1/go.mod h1:Jsttr0pEvzPAw+qay1kS1/PsbZYPyhlu github.com/decred/dcrd/gcs v1.0.0/go.mod h1:5uHIPAzn4SdGP2/FhVBK2YdAoKmufds3ZI8yNzojUCM= github.com/decred/dcrd/gcs v1.0.1 h1:MpJXLskT41+JDaD3RLdlSlF2vlu1sxPpZgiRI7FVTWw= github.com/decred/dcrd/gcs v1.0.1/go.mod h1:YwutGzusSdJM79CJtxCo9t7WRCvnkLtWSD19TPo1i9g= +github.com/decred/dcrd/gcs v1.0.2/go.mod h1:eLCvrzUsWro48TlTyrmFcZAZqnllYFz0vEv5VZtufF4= github.com/decred/dcrd/hdkeychain v1.1.0 h1:6bFdL672dCmtg/JEzb3Jw0dTRO2jLxcA7BK2J+JaoUM= github.com/decred/dcrd/hdkeychain v1.1.0/go.mod h1:zyUZtZ3PdnTPHt2XUr1x76b8ZuiM+9aVkP8Rq8Scp1k= github.com/decred/dcrd/mempool v1.0.1 h1:xZOfwGmVbWfKDNztVgsVO/GkMmiZn3MMfDDVE07ZKKs= @@ -72,6 +75,8 @@ github.com/decred/dcrd/wire v1.0.1 h1:yhLSapj1ZF3LT/7cu7Ur9+chEuIV8gnrf6DqWDrFaV github.com/decred/dcrd/wire v1.0.1/go.mod h1:zpKZnBiN59CrzfXFigwgXmUDVYf34OLbEr8xwAwriHc= github.com/decred/dcrd/wire v1.1.0 h1:G+3CugtxNbToUN8RKWqm74yLfzJJ2BKMOr2RgWc4TyY= github.com/decred/dcrd/wire v1.1.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/EqcffvU8fJHM= +github.com/decred/dcrwallet/pgpwordlist v1.0.0/go.mod h1:Fek3uYn+9DnEFIreA/8PnTIXUl2lBO64JpEBkL9BXtk= +github.com/decred/dcrwallet/walletseed v1.0.0/go.mod h1:xSF6hZW+5Xhm0jJFsI5jQSfViuZUQJoDXa/cQxtgncs= github.com/decred/slog v1.0.0 h1:Dl+W8O6/JH6n2xIFN2p3DNjCmjYwvrXsjlSJTQQ4MhE= github.com/decred/slog v1.0.0/go.mod h1:zR98rEZHSnbZ4WHZtO0iqmSZjDLKhkXfrPTZQKtAonQ= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/wallet/go.mod b/wallet/go.mod index 58af8d146..2f401fc51 100644 --- a/wallet/go.mod +++ b/wallet/go.mod @@ -22,6 +22,7 @@ require ( github.com/decred/dcrwallet/internal/helpers v1.0.0 github.com/decred/dcrwallet/internal/zero v1.0.0 github.com/decred/dcrwallet/validate v1.0.0 + github.com/decred/dcrwallet/walletseed v1.0.0 // indirect github.com/decred/slog v1.0.0 github.com/jrick/bitset v1.0.0 golang.org/x/crypto v0.0.0-20180808211826-de0752318171 diff --git a/wallet/go.sum b/wallet/go.sum index 9171913a7..148c3f5ee 100644 --- a/wallet/go.sum +++ b/wallet/go.sum @@ -79,6 +79,11 @@ github.com/decred/dcrd/wire v1.0.1 h1:yhLSapj1ZF3LT/7cu7Ur9+chEuIV8gnrf6DqWDrFaV github.com/decred/dcrd/wire v1.0.1/go.mod h1:zpKZnBiN59CrzfXFigwgXmUDVYf34OLbEr8xwAwriHc= github.com/decred/dcrd/wire v1.1.0 h1:G+3CugtxNbToUN8RKWqm74yLfzJJ2BKMOr2RgWc4TyY= github.com/decred/dcrd/wire v1.1.0/go.mod h1:/JKOsLInOJu6InN+/zH5AyCq3YDIOW/EqcffvU8fJHM= +github.com/decred/dcrwallet v1.2.2 h1:NdI13wxP+OsWKXPqjWQQ9VSGAl4VoSLBfAunzFreeJg= +github.com/decred/dcrwallet/pgpwordlist v1.0.0 h1:H7Y3+yRZq7PXMPfpKLMnY5TKTjTWhc0oJmyN7v8tC/M= +github.com/decred/dcrwallet/pgpwordlist v1.0.0/go.mod h1:Fek3uYn+9DnEFIreA/8PnTIXUl2lBO64JpEBkL9BXtk= +github.com/decred/dcrwallet/walletseed v1.0.0 h1:WmHtbdKdap8nfrfkftm6o63NsuQo4gg2Fwkteuwzc1g= +github.com/decred/dcrwallet/walletseed v1.0.0/go.mod h1:xSF6hZW+5Xhm0jJFsI5jQSfViuZUQJoDXa/cQxtgncs= github.com/decred/slog v1.0.0 h1:Dl+W8O6/JH6n2xIFN2p3DNjCmjYwvrXsjlSJTQQ4MhE= github.com/decred/slog v1.0.0/go.mod h1:zR98rEZHSnbZ4WHZtO0iqmSZjDLKhkXfrPTZQKtAonQ= github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= diff --git a/wallet/udb/testdata/v11.db.gz b/wallet/udb/testdata/v11.db.gz new file mode 100644 index 000000000..a9c3bff95 Binary files /dev/null and b/wallet/udb/testdata/v11.db.gz differ diff --git a/wallet/udb/testdata/v11.go b/wallet/udb/testdata/v11.go new file mode 100644 index 000000000..ff0b45a57 --- /dev/null +++ b/wallet/udb/testdata/v11.go @@ -0,0 +1,309 @@ +// Copyright (c) 2017 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +// This file should compiled from the commit the file was introduced, otherwise +// it may not compile due to API changes, or may not create the database with +// the correct old version. This file should not be updated for API changes. + +package main + +import ( + "bytes" + "compress/gzip" + "encoding/binary" + "fmt" + "io" + "os" + "time" + + "github.com/decred/dcrd/chaincfg" + "github.com/decred/dcrd/chaincfg/chainhash" + "github.com/decred/dcrd/dcrec/secp256k1" + "github.com/decred/dcrd/dcrutil" + "github.com/decred/dcrd/gcs" + "github.com/decred/dcrd/gcs/blockcf" + "github.com/decred/dcrd/hdkeychain" + "github.com/decred/dcrd/txscript" + "github.com/decred/dcrd/wire" + "github.com/decred/dcrwallet/errors" + "github.com/decred/dcrwallet/wallet/internal/walletdb" + _ "github.com/decred/dcrwallet/wallet/internal/walletdb/bdb" + "github.com/decred/dcrwallet/wallet/udb" + "github.com/decred/dcrwallet/walletseed" + "golang.org/x/crypto/ripemd160" +) + +const dbname = "v11.db" + +var ( + epoch time.Time + pubPass = []byte("public") + privPass = []byte("private") + privKey = []byte{31: 1} + byteOrder = binary.BigEndian + bucketMultisig = []byte("ms") + bucketTxRecords = []byte("t") +) + +func main() { + err := setup() + if err != nil { + fmt.Fprintf(os.Stderr, "setup: %v\n", err) + os.Exit(1) + } + err = compress() + if err != nil { + fmt.Fprintf(os.Stderr, "compress: %v\n", err) + os.Exit(1) + } +} + +func setup() error { + const op errors.Op = "udb.V11DatabaseSetup" + + var chainParams = &chaincfg.TestNet3Params + os.Remove(dbname) + db, err := walletdb.Create("bdb", dbname) + if err != nil { + return err + } + defer db.Close() + seed, err := walletseed.GenerateRandomSeed(hdkeychain.RecommendedSeedLen) + if err != nil { + return err + } + err = udb.Initialize(db, chainParams, seed, pubPass, privPass) + if err != nil { + return err + } + + amgr, txmgr, _, err := udb.Open(db, chainParams, pubPass) + if err != nil { + return err + } + + return walletdb.Update(db, func(dbtx walletdb.ReadWriteTx) error { + amgrns := dbtx.ReadWriteBucket([]byte("waddrmgr")) + txmgrns := dbtx.ReadWriteBucket([]byte("wtxmgr")) + + err := amgr.Unlock(amgrns, privPass) + if err != nil { + return err + } + + _, pk := secp256k1.PrivKeyFromBytes(privKey) + + // Add a block + prevBlock := chainParams.GenesisHash + buf := bytes.Buffer{} + err = (&wire.BlockHeader{ + Version: 1, + PrevBlock: *prevBlock, + StakeVersion: 1, + VoteBits: 1, + Height: uint32(1), + }).Serialize(&buf) + if err != nil { + return err + } + + headerData := udb.BlockHeaderData{ + BlockHash: chainhash.Hash{31: byte(1)}, + } + copy(headerData.SerializedHeader[:], buf.Bytes()) + + filters := emptyFilters(1) + header := new(wire.BlockHeader) + err = header.Deserialize(bytes.NewReader(headerData.SerializedHeader[:])) + if err != nil { + return err + } + err = txmgr.ExtendMainChain(txmgrns, header, filters[0]) + if err != nil { + return err + } + + // Add 2 mso with TX and 4 without + for count := 1; count <= 6; count++ { + msgTx := wire.NewMsgTx() + + address1, err := dcrutil.NewAddressSecpPubKeyCompressed(pk, chainParams) + + msScript, err := txscript.MultiSigScript([]*dcrutil.AddressSecpPubKey{address1}, 1) + if err != nil { + return err + } + + _, err = amgr.ImportScript(amgrns, msScript) + if err != nil { + // We don't care if we've already used this address. + if err != nil && !errors.Is(errors.Exist, err) { + return errors.E(op, err) + } + } + err = txmgr.InsertTxScript(txmgrns, msScript) + if err != nil { + return err + } + scAddr, err := dcrutil.NewAddressScriptHash(msScript, chainParams) + if err != nil { + return err + } + p2shScript, err := txscript.PayToAddrScript(scAddr) + if err != nil { + return err + } + + msgTx.AddTxOut(wire.NewTxOut(int64(dcrutil.Amount(1*count)), p2shScript)) + msgTx.Expiry = wire.NoExpiryValue + rec, err := udb.NewTxRecordFromMsgTx(msgTx, epoch) + if err != nil { + return err + } + + // put 2 tx records + if count <= 2 { + err = putTxRecord(txmgrns, rec, &udb.Block{ + Hash: headerData.BlockHash, + Height: 1, + }) + if err != nil { + return err + } + } + + var p2shScriptHash [ripemd160.Size]byte + key := keyMultisigOut(rec.Hash, 0) + val := valueMultisigOut(p2shScriptHash, 1, 1, false, 0, headerData.BlockHash, + 1, dcrutil.Amount(0), chainhash.Hash{}, 0xFFFFFFFF, rec.Hash) + + err = putMultisigOutRawValues(txmgrns, key, val) + if err != nil { + return err + } + } + + return nil + }) + +} + +func compress() error { + db, err := os.Open(dbname) + if err != nil { + return err + } + defer os.Remove(dbname) + defer db.Close() + dbgz, err := os.Create(dbname + ".gz") + if err != nil { + return err + } + defer dbgz.Close() + gz := gzip.NewWriter(dbgz) + _, err = io.Copy(gz, db) + if err != nil { + return err + } + return gz.Close() +} + +func emptyFilters(n int) []*gcs.Filter { + f := make([]*gcs.Filter, n) + for i := range f { + f[i], _ = gcs.FromBytes(0, blockcf.P, nil) + } + return f +} + +func keyMultisigOut(hash chainhash.Hash, index uint32) []byte { + return canonicalOutPoint(&hash, index) +} + +func valueMultisigOut(sh [ripemd160.Size]byte, m uint8, n uint8, + spent bool, tree int8, blockHash chainhash.Hash, + blockHeight uint32, amount dcrutil.Amount, spentBy chainhash.Hash, + sbi uint32, txHash chainhash.Hash) []byte { + v := make([]byte, 135) + + copy(v[0:20], sh[0:20]) + v[20] = m + v[21] = n + v[22] = uint8(0) + + if spent { + v[22] |= 1 << 0 + } + + if tree == wire.TxTreeStake { + v[22] |= 1 << 1 + } + + copy(v[23:55], blockHash[:]) + byteOrder.PutUint32(v[55:59], blockHeight) + byteOrder.PutUint64(v[59:67], uint64(amount)) + + copy(v[67:99], spentBy[:]) + byteOrder.PutUint32(v[99:103], sbi) + + copy(v[103:135], txHash[:]) + + return v +} + +func canonicalOutPoint(txHash *chainhash.Hash, index uint32) []byte { + k := make([]byte, 36) + copy(k, txHash[:]) + byteOrder.PutUint32(k[32:36], index) + return k +} + +func putMultisigOutRawValues(ns walletdb.ReadWriteBucket, k []byte, v []byte) error { + err := ns.NestedReadWriteBucket(bucketMultisig).Put(k, v) + if err != nil { + return err + } + return nil +} + +func keyTxRecord(txHash *chainhash.Hash, block *udb.Block) []byte { + k := make([]byte, 68) + copy(k, txHash[:]) + byteOrder.PutUint32(k[32:36], uint32(block.Height)) + copy(k[36:68], block.Hash[:]) + return k +} + +func putTxRecord(ns walletdb.ReadWriteBucket, rec *udb.TxRecord, block *udb.Block) error { + k := keyTxRecord(&rec.Hash, block) + v, err := valueTxRecord(rec) + if err != nil { + return err + } + err = ns.NestedReadWriteBucket(bucketTxRecords).Put(k, v) + if err != nil { + str := fmt.Sprintf("%s: put failed for %v", bucketTxRecords, rec.Hash) + return errors.New(str) + } + return nil +} + +func valueTxRecord(rec *udb.TxRecord) ([]byte, error) { + var v []byte + if rec.SerializedTx == nil { + txSize := rec.MsgTx.SerializeSize() + v = make([]byte, 8, 8+txSize) + err := rec.MsgTx.Serialize(bytes.NewBuffer(v[8:])) + if err != nil { + str := fmt.Sprintf("unable to serialize transaction %v", rec.Hash) + return nil, errors.New(str) + } + v = v[:cap(v)] + } else { + v = make([]byte, 8+len(rec.SerializedTx)) + copy(v[8:], rec.SerializedTx) + } + byteOrder.PutUint64(v, uint64(rec.Received.Unix())) + return v, nil +} diff --git a/wallet/udb/upgrades.go b/wallet/udb/upgrades.go index 1e44bc8b3..dfbf2e76d 100644 --- a/wallet/udb/upgrades.go +++ b/wallet/udb/upgrades.go @@ -99,26 +99,32 @@ const ( // from properly-synced wallets. lastProcessedTxsBlockVersion = 11 + // removeMultisigOutsWithoutTransactions is the twelfth version of the database. + // It fixes issue with MultisigOuts without related transactions. Simply find all + // detached MultisigOutputs and remove + removeMultisigOutsWithoutTransactionsVersion = 12 + // DBVersion is the latest version of the database that is understood by the // program. Databases with recorded versions higher than this will fail to // open (meaning any upgrades prevent reverting to older software). - DBVersion = lastProcessedTxsBlockVersion + DBVersion = removeMultisigOutsWithoutTransactionsVersion ) // upgrades maps between old database versions and the upgrade function to // upgrade the database to the next version. Note that there was never a // version zero so upgrades[0] is nil. var upgrades = [...]func(walletdb.ReadWriteTx, []byte, *chaincfg.Params) error{ - lastUsedAddressIndexVersion - 1: lastUsedAddressIndexUpgrade, - votingPreferencesVersion - 1: votingPreferencesUpgrade, - noEncryptedSeedVersion - 1: noEncryptedSeedUpgrade, - lastReturnedAddressVersion - 1: lastReturnedAddressUpgrade, - ticketBucketVersion - 1: ticketBucketUpgrade, - slip0044CoinTypeVersion - 1: slip0044CoinTypeUpgrade, - hasExpiryVersion - 1: hasExpiryUpgrade, - hasExpiryFixedVersion - 1: hasExpiryFixedUpgrade, - cfVersion - 1: cfUpgrade, - lastProcessedTxsBlockVersion - 1: lastProcessedTxsBlockUpgrade, + lastUsedAddressIndexVersion - 1: lastUsedAddressIndexUpgrade, + votingPreferencesVersion - 1: votingPreferencesUpgrade, + noEncryptedSeedVersion - 1: noEncryptedSeedUpgrade, + lastReturnedAddressVersion - 1: lastReturnedAddressUpgrade, + ticketBucketVersion - 1: ticketBucketUpgrade, + slip0044CoinTypeVersion - 1: slip0044CoinTypeUpgrade, + hasExpiryVersion - 1: hasExpiryUpgrade, + hasExpiryFixedVersion - 1: hasExpiryFixedUpgrade, + cfVersion - 1: cfUpgrade, + lastProcessedTxsBlockVersion - 1: lastProcessedTxsBlockUpgrade, + removeMultisigOutsWithoutTransactionsVersion - 1: removeMultisigOutsWithoutTransactions, } func lastUsedAddressIndexUpgrade(tx walletdb.ReadWriteTx, publicPassphrase []byte, params *chaincfg.Params) error { @@ -782,6 +788,54 @@ func lastProcessedTxsBlockUpgrade(tx walletdb.ReadWriteTx, publicPassphrase []by return unifiedDBMetadata{}.putVersion(metadataBucket, newVersion) } +func removeMultisigOutsWithoutTransactions(tx walletdb.ReadWriteTx, publicPassphrase []byte, params *chaincfg.Params) error { + const oldVersion = 11 + const newVersion = 12 + + metadataBucket := tx.ReadWriteBucket(unifiedDBMetadata{}.rootBucketKey()) + txmgrBucket := tx.ReadWriteBucket(wtxmgrBucketKey) + + // Assert this function is only called on version 9 databases. + dbVersion, err := unifiedDBMetadata{}.getVersion(metadataBucket) + if err != nil { + return err + } + if dbVersion != oldVersion { + const str = "removeExtraMultisigOutsUpgrade inappropriately called" + return errors.E(errors.Invalid, str, nil) + } + + var multisigOutsMarkedForDelete [][]byte + multisigOutBucket := txmgrBucket.NestedReadWriteBucket([]byte("ms")) + + c := multisigOutBucket.ReadCursor() + for k, v := c.First(); k != nil; k, v = c.Next() { + kCpy := make([]byte, len(k)) + copy(kCpy[:], k) + + mso, err := fetchMultisigOut(kCpy, v) + if err != nil { + str := "failed to fetch multisig from bucket" + return errors.E(errors.IO, str, nil) + } + + _, txVal := existsTxRecord(txmgrBucket, &mso.TxHash, &Block{ + Hash: mso.BlockHash, + Height: int32(mso.BlockHeight), + }) + if txVal == nil { + multisigOutsMarkedForDelete = append(multisigOutsMarkedForDelete, kCpy) + } + } + + for _, msoKey := range multisigOutsMarkedForDelete { + multisigOutBucket.Delete(msoKey) + } + + // Write the new database version. + return unifiedDBMetadata{}.putVersion(metadataBucket, newVersion) +} + // Upgrade checks whether the any upgrades are necessary before the database is // ready for application usage. If any are, they are performed. func Upgrade(db walletdb.DB, publicPassphrase []byte, params *chaincfg.Params) error { diff --git a/wallet/udb/upgrades_test.go b/wallet/udb/upgrades_test.go index d7fe878a3..e5366b675 100644 --- a/wallet/udb/upgrades_test.go +++ b/wallet/udb/upgrades_test.go @@ -18,7 +18,7 @@ import ( "github.com/decred/dcrd/chaincfg" "github.com/decred/dcrd/chaincfg/chainhash" "github.com/decred/dcrd/wire" - _ "github.com/decred/dcrwallet/wallet/drivers/bdb" + _ "github.com/decred/dcrwallet/errors" "github.com/decred/dcrwallet/wallet/internal/walletdb" ) @@ -35,6 +35,7 @@ var dbUpgradeTests = [...]struct { {verifyV8Upgrade, "v7.db.gz"}, // No upgrade test for V9, it is a fix for V8 and the previous test still applies // TODO: V10 upgrade test + {verifyV12Upgrade, "v11.db.gz"}, } var pubPass = []byte("public") @@ -408,6 +409,49 @@ func verifyV8Upgrade(t *testing.T, db walletdb.DB) { } return err }) + + if err != nil { + t.Error(err) + } +} + +func verifyV12Upgrade(t *testing.T, db walletdb.DB) { + err := walletdb.View(db, func(tx walletdb.ReadTx) error { + txmgrBucket := tx.ReadBucket(wtxmgrBucketKey) + + var multisigOutsMarkedForDelete [][]byte + multisigOutBucket := txmgrBucket.NestedReadBucket([]byte("ms")) + c := multisigOutBucket.ReadCursor() + var msoWithTX int + for k, v := c.First(); k != nil; k, v = c.Next() { + mso, err := fetchMultisigOut(k, v) + if err != nil { + str := "failed to fetch multisig from bucket" + t.Errorf("Error during fetch mso: %s, %s", str, err) + } + + _, txVal := existsTxRecord(txmgrBucket, &mso.TxHash, &Block{ + Hash: mso.BlockHash, + Height: int32(mso.BlockHeight), + }) + if txVal == nil { + multisigOutsMarkedForDelete = append(multisigOutsMarkedForDelete, k) + } else { + msoWithTX++ + } + } + + // should exist 2 multisigOuts with valid TX + if msoWithTX != 2 { + t.Error("expected to have 2 valid transactions for MSOs") + } + + if len(multisigOutsMarkedForDelete) > 0 { + t.Error("expected to have 0 MSOs marked for delete") + } + + return nil + }) if err != nil { t.Error(err) }