Repository navigation
Expand file tree
/
Copy pathproof_bundle_service_test.go
More file actions
129 lines (112 loc) · 8.47 KB
/
Copy pathproof_bundle_service_test.go
File metadata and controls
129 lines (112 loc) · 8.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package main
import (
"encoding/json"
"strings"
"testing"
)
// Same mainnet vector derohe's proof package tests against: a real transaction,
// its completed ring, and a proof opening one payload worth 100000.
const (
tbProof = "deroproof1qyzlkv8x5cp7tgh3eeqjuu6nenaf0vfjcpm3fl784tkaa6tqpz2jsqdzvfyyskpq0kjaju7h2lw6h48g7fjsmgamxex0szh65f59tk7k82g3f39yt46ky4j4rgqqrp4q0wqa3c"
tbRing1 = "deto1qyx7qyvrtrhvaszeej487k2g689fav7h38ay37fja9qf40ycgl0m2qg8ap2y9"
tbRing2 = "deto1qyre7td6x9r88y4cavdgpv6k7lvx6j39lfsx420hpvh3ydpcrtxrxqg8v8e3z"
tbRing3 = "deto1qysmp3ws28pkvas04cenrgmcjth8cavhd4z0x3xf0x0sl4033vlm6qgwhjz05"
tbRing4 = "deto1qypytjjcdzuqq05flnnlvcvja87672g0444rywvqvfq7szyv63ly7qgrkv0xg"
tbTxHex = "01000003519b9e874a9dd7fcbfb7802268123dcf970c336891101a3a0705855b72b9eb08c80100000000000000000000000000000000000000000000000000000000000000000000f394d06566a81b024fd8624b4c8592f8b9344e58f227261eb08d821bd190b4ac9c7df0660038ddcf881602a14fe5ad8eebff83d3ce3541a1f232fe61acf71109e417160936863e8c0597c798b73ef08e76b8eeebcaf20260ba91fcdef5f626361f824dc6197b02c599d4511c624a933226d8fccc125611ec80d8ad5acea4baf2f1c77e4c5525d9859b40f43daaf3d4e4450203d80419dcb026b9adbd7d6912284ee9ce20f3721076947f16e1faefd9b8c35116f4cf0044ead0a12fda3f3bcf2ed91627b922c02c10d112df9e782d3750cda151f6ba2ebe6495065141f32800894566011198c4055458005a31d3e285037446ba14bac54420bcab87cbebeaccab1f158b011e90132b7310e6c866e348cab68d21bad1d9f811b4d667a1e40bdef1a19259d3000b972ae06da958658b12ca4a45c2c6ea50d305be86f7e979fc962c687eb012f401a2c4bf0beb6c713343b94d65ee6d937660480daf670ab5b0ed421a9103e8a25119c836dd799600e67e4ec66ef680833398a99b16956aed2ee5bd9e6c8e68009a01145636e5e448d6c8ab902db394aa9c5aeee92dd150e1150d5b8f6674f330c279010912df27232ae126525a130ed8a9b4dee62eb57ce1d8a42ae9bcef867b10ce94012f94aa78846fcdda504243f83f3122aee5dc38dd32fa2a90224b3a40b4cf79c301129028709e39591c55e6e477a36cc26dc2efd7183fb59f51635dbd114dfed9d5010d66f31b781fa181c2114600ee1f03d55439355265700fb9d35ac684a19db398001e12558cc17e59fb85fb825481dee6fef3612c043bb38ca4833183da5381364600077a99d4d2df2f06067359f178a40f98a3e0943309c5ce3ce5398b9909174254012aa49cfc78ebec51c00e7824db0d8d41ef43fbb0396824d2c31b7db64124cc61000a8b51bd6c94a502f7aea3e5001f00d76b165ad580e48f8aa72813da8240286e00055f3480aa7cdb68a20d4b1e567d42389b44cf4e345da9e5a5655a80418695bc012c8f1e1ef8af646b4fb08afaeb3febde17c4c0d04b30dfd22d96a32ced9c9439010c40484e1547d307ad56b79bb7450e4eaaed7ed79bd5392dffd7449043f8783a0015104264f8d80356176ca6fdf4777e4ebc8edcbab50f8b6c366ac75ebd6bb5c701078d55053d2d41f21f51d5e617f282ba9dfa2576f0231048dd73998ceaa699fd0105821b61addd6935c7d80e65c706f0f2aa2d73ad22c5548c9c8b92cd82689dc40115f576c413a37014b9ee5377b121c69ad6e0f00f2b4f6c99d1f68b00a5d923370119b29fe6e9cf35f1344e24d52ee1fdb6521de3176f3d2b2a2b9327ae6e6cfbb10017198369a6ff180253700361c40e7f378c8e7ead6e04f01dbf5b4c47e7e1e4ff001abaf84628764eccbc5d0f66dc0a99505bb0e598362c45312470526afad11caf00242c6a902c564b3b363eb4ae08f643f18571779428358bfbdaf9856b0ebf229f0100000000000000000000000000000000000000000000000000000000000000001b7a78b6f573d4ac5d3a8d7d10dafac0dbc92604474417b29d40448d9fbc821d0fe3f73da41b27752d5db0658fcc0bff7da21112417ac719e491fdd43c8e5d0b07bcca22c27367a276e6a4e0cfb1bfbc772842898356ad4723101d4ada5137f409bb3b290d7519da3af15feb09e183e2be809690099551f1cb984deb1295b7611dd0cfd9000482314a388512d278fc22b2f6e3fc6e95023b4bd228e22626b7440119fa2c6f45a33b008ef5b23a5522ebbf0bf5f26d8263613a7f9b5ad9a192357600107a023453f7f79f413756dfba0096ae5d13158bbbb147089a020e819ef6640728acf01c811b967d1a14d767ac20088c5ca1613aa5d94ebe7fe2840b6431d8d002137dae183071d12cd9fb14c4b4738ef750ff514ce26257d1245eaedfea625516bfcb075a33a8910dc4e40742bfaa70d95591711e9db33d0db0be06cc819817072c22a9c81f4369f68bb1ef71c7f7458671d647caef18b30cca91da4f1b201d082a03306b4a07d1f0e1a8cc8844038fc524201a6c3a346a971203fd45458d292987d44049eecdac25c5622465a8d683a43621612d2fb283724b17a7bfa3bad2266a6fb1cf669eef21c90e24e85d6ab48e8b237355e964407dde00d65fb442dd210ce0378349f533c0e8ab65293de5319e246a044ed22b1e6db28add1508dd6f0da22954eea8a431b211a8b54147e32fec6593f9fb731389f62f94d5047e0f3301216576c71a79629bc3879325280e216d59cf7e6ff2d6a0babe418f8f2ed603ce010e16785f8c855043221ed5a603d4ed4e8e90059669543738ceb2a04dc996079c01264e9beaf4bb82e1b8f47bb0c239167064001e306eeef2b5495ec42754806b65012357f738543b13594ff081a070dbc0575645ac5ce8e0f89d3afdeb3d49e9ddae012a17d5095b9cef08f6eee2ce733dbf2cfcdb8c23e39410ed973e68cf8505266d00280c52b45752dd12ba84499618898111a8f9b19f2b76c06917e57eef221f3387011cc3360b478d144118a82a3c4391814f34aac2fb0f2d043394304bed179689e501292ca5631820f5f465242b4cc517f06c153c176a43f77daca463b7e2d3e2d7ba001aa0b2c90c3172cd2556137d78748f47924432449210d8b2f5e27adb6210bc77012c92a12526a5b0b1ef60994eb4d08e9bb5a3ea330d417838a52ad8636d37fa9e00131153c9affeefd6b98ecb6a80f5e6ea97417376030325182c064e12dd353c32011f4e25c49eea09adaa46d56642e2ea0afced2d75036acd3839435863f1ec3bf1002e19fe8456a7236c8fb77a15f87164debaad865e85c3468152a5deaffde3da6a01"
)
// buildTestBundle assembles a receipt by hand, exactly as ExportProofBundle
// would after its daemon fetch -- so the verify path can be exercised without
// any daemon at all.
func buildTestBundle(t *testing.T) string {
t.Helper()
b := map[string]interface{}{
"version": 1,
"network": "mainnet",
"tx_hex": tbTxHex,
"ring": [][]string{{tbRing1, tbRing2, tbRing3, tbRing4}},
"proof": tbProof,
}
data, err := json.Marshal(b)
if err != nil {
t.Fatalf("could not build test bundle: %s", err)
}
return string(data)
}
// THE LOAD-BEARING TEST. The App is constructed with a nil daemonClient, so any
// network call would panic. If this passes, verification provably touched no
// daemon -- the offline claim is measured, not asserted.
func TestVerifyProofBundleTouchesNoDaemon(t *testing.T) {
a := &App{daemonClient: nil, settings: map[string]interface{}{"network": "mainnet"}}
res := a.VerifyProofBundle(buildTestBundle(t))
if res["success"] != true {
t.Fatalf("expected success, got %v (error: %v)", res["success"], res["error"])
}
if res["valid"] != true {
t.Fatalf("expected a valid receipt, got valid=%v error=%v", res["valid"], res["error"])
}
if res["offline"] != true {
t.Fatalf("result is not flagged offline")
}
receivers, ok := res["receivers"].([]map[string]interface{})
if !ok || len(receivers) != 1 {
t.Fatalf("expected 1 receiver, got %v", res["receivers"])
}
if amt, ok := receivers[0]["amount"].(uint64); !ok || amt != 100000 {
t.Fatalf("expected amount 100000, got %v", receivers[0]["amount"])
}
if txid, ok := res["txid"].(string); !ok || txid == "" {
t.Fatalf("verified result carries no txid")
}
}
// A tampered receipt must be reported invalid rather than crashing the app --
// derohe's transaction parser panics on some malformed bytes, and a receipt is
// untrusted input by construction.
func TestVerifyProofBundleRejectsTampered(t *testing.T) {
a := &App{daemonClient: nil, settings: map[string]interface{}{"network": "mainnet"}}
runes := []rune(tbTxHex)
i := len(runes) / 2
if runes[i] == '0' {
runes[i] = '1'
} else {
runes[i] = '0'
}
tampered := strings.Replace(buildTestBundle(t), tbTxHex, string(runes), 1)
res := a.VerifyProofBundle(tampered)
if res["valid"] == true {
t.Fatalf("a tampered receipt was reported valid")
}
}
func TestVerifyProofBundleRejectsGarbage(t *testing.T) {
a := &App{daemonClient: nil, settings: map[string]interface{}{"network": "mainnet"}}
for name, input := range map[string]string{
"empty": "",
"not json": "hello",
"empty object": "{}",
} {
res := a.VerifyProofBundle(input)
if res["valid"] == true {
t.Fatalf("%s: reported valid", name)
}
}
}
// The network field must not be decorative: a mainnet receipt relabelled as
// testnet must be refused, since derohe's Prove() does not enforce this itself.
func TestVerifyProofBundleEnforcesNetwork(t *testing.T) {
a := &App{daemonClient: nil, settings: map[string]interface{}{"network": "mainnet"}}
mislabelled := strings.Replace(buildTestBundle(t), `"network":"mainnet"`, `"network":"testnet"`, 1)
res := a.VerifyProofBundle(mislabelled)
if res["valid"] == true {
t.Fatalf("a mainnet receipt relabelled testnet was reported valid")
}
}
// ExportProofBundle refuses obviously-incomplete input before any daemon call,
// so a nil client is safe here too.
func TestExportProofBundleValidatesInput(t *testing.T) {
a := &App{daemonClient: nil, settings: map[string]interface{}{"network": "mainnet"}}
if res := a.ExportProofBundle("", "abc"); res["success"] != false {
t.Fatalf("expected refusal on empty proof")
}
if res := a.ExportProofBundle(tbProof, ""); res["success"] != false {
t.Fatalf("expected refusal on empty txid")
}
}