aboutsummaryrefslogtreecommitdiffstats
path: root/common/natspec/natspec_e2e_test.go.orig
blob: 601a9edbd23130ec416b14fbee70b9abd7c5f295 (plain) (blame)
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
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
package natspec

import (
  "fmt"
  "io/ioutil"
  "os"
  "strings"
  "testing"

  "github.com/ethereum/go-ethereum/accounts"
  "github.com/ethereum/go-ethereum/common"
  "github.com/ethereum/go-ethereum/common/docserver"
  "github.com/ethereum/go-ethereum/common/registrar"
  "github.com/ethereum/go-ethereum/core"
  "github.com/ethereum/go-ethereum/core/state"
  "github.com/ethereum/go-ethereum/crypto"
  "github.com/ethereum/go-ethereum/eth"
  xe "github.com/ethereum/go-ethereum/xeth"
)

const (
  testBalance = "10000000000000000000"

  testFileName = "long_file_name_for_testing_registration_of_URLs_longer_than_32_bytes.content"

  testNotice = "Register key `utils.toHex(_key)` <- content `utils.toHex(_content)`"

  testExpNotice = "Register key 0xadd1a7d961cff0242089674ec2ef6fca671ab15e1fe80e38859fc815b98d88ab <- content 0xb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7"

  testExpNotice2 = `About to submit transaction (NatSpec notice error: abi key does not match any method): {"params":[{"to":"%s","data": "0x31e12c20"}]}`

  testExpNotice3 = `About to submit transaction (no NatSpec info found for contract: content hash not found for '0x1392c62d05b2d149e22a339c531157ae06b44d39a674cce500064b12b9aeb019'): {"params":[{"to":"%s","data": "0x300a3bbfb3a2dea218de5d8bbe6c4645aadbf67b5ab00ecb1a9ec95dbdad6a0eed3e41a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000066696c653a2f2f2f746573742e636f6e74656e74"}]}`
)

const (
  testUserDoc = `
{
  "methods": {
    "register(uint256,uint256)": {
      "notice":  "` + testNotice + `"
    }
  },
  "invariants": [
    { "notice": "" }
  ],
  "construction": [
    { "notice": "" }
  ]
}
`
  testAbiDefinition = `
[{
  "name": "register",
  "constant": false,
  "type": "function",
  "inputs": [{
    "name": "_key",
    "type": "uint256"
  }, {
    "name": "_content",
    "type": "uint256"
  }],
  "outputs": []
}]
`

  testContractInfo = `
{
  "userDoc": ` + testUserDoc + `,
  "abiDefinition": ` + testAbiDefinition + `
}
`
)

type testFrontend struct {
  t           *testing.T
  ethereum    *eth.Ethereum
  xeth        *xe.XEth
  coinbase    common.Address
  stateDb     *state.StateDB
  txc         uint64
  lastConfirm string
  wantNatSpec bool
}

func (self *testFrontend) UnlockAccount(acc []byte) bool {
  self.ethereum.AccountManager().Unlock(common.BytesToAddress(acc), "password")
  return true
}

func (self *testFrontend) ConfirmTransaction(tx string) bool {
  if self.wantNatSpec {
    ds := docserver.New("/tmp/")
    self.lastConfirm = GetNotice(self.xeth, tx, ds)
  }
  return true
}

func testEth(t *testing.T) (ethereum *eth.Ethereum, err error) {

  os.RemoveAll("/tmp/eth-natspec/")

  err = os.MkdirAll("/tmp/eth-natspec/keystore", os.ModePerm)
  if err != nil {
    panic(err)
  }

  // create a testAddress
  ks := crypto.NewKeyStorePassphrase("/tmp/eth-natspec/keystore", crypto.LightScryptN, crypto.LightScryptP)
  am := accounts.NewManager(ks)
  testAccount, err := am.NewAccount("password")
  if err != nil {
    panic(err)
  }
  testAddress := strings.TrimPrefix(testAccount.Address.Hex(), "0x")

  // set up mock genesis with balance on the testAddress
  core.GenesisAccounts = []byte(`{
  "` + testAddress + `": {"balance": "` + testBalance + `"}
  }`)

  // only use minimalistic stack with no networking
  ethereum, err = eth.New(&eth.Config{
    DataDir:        "/tmp/eth-natspec",
    AccountManager: am,
    MaxPeers:       0,
  })

  if err != nil {
    panic(err)
  }

  return
}

func testInit(t *testing.T) (self *testFrontend) {
  // initialise and start minimal ethereum stack
  ethereum, err := testEth(t)
  if err != nil {
    t.Errorf("error creating ethereum: %v", err)
    return
  }
  err = ethereum.Start()
  if err != nil {
    t.Errorf("error starting ethereum: %v", err)
    return
  }

  // mock frontend
  self = &testFrontend{t: t, ethereum: ethereum}
  self.xeth = xe.New(ethereum, self)

  addr, _ := ethereum.Etherbase()
  self.coinbase = addr
  self.stateDb = self.ethereum.ChainManager().State().Copy()

  // initialise the registry contracts
  reg := registrar.New(self.xeth)
  err = reg.SetHashReg("", addr)
  if err != nil {
    t.Errorf("error creating HashReg: %v", err)
  }
  err = reg.SetUrlHint("", addr)
  if err != nil {
    t.Errorf("error creating UrlHint: %v", err)
  }
  self.applyTxs()

  return

}

// this is needed for transaction to be applied to the state in testing
// the heavy lifing is done in XEth.ApplyTestTxs
// this is fragile,
// and does process leaking since xeth loops cannot quit safely
// should be replaced by proper mining with testDAG for easy full integration tests
func (self *testFrontend) applyTxs() {
  self.txc, self.xeth = self.xeth.ApplyTestTxs(self.stateDb, self.coinbase, self.txc)
  return
}

// end to end test
func TestNatspecE2E(t *testing.T) {
  t.Skip()

  tf := testInit(t)
  defer tf.ethereum.Stop()

  // create a contractInfo file (mock cloud-deployed contract metadocs)
  // incidentally this is the info for the registry contract itself
  ioutil.WriteFile("/tmp/"+testFileName, []byte(testContractInfo), os.ModePerm)
  dochash := common.BytesToHash(crypto.Sha3([]byte(testContractInfo)))

  // take the codehash for the contract we wanna test
  // codehex := tf.xeth.CodeAt(registar.HashRegAddr)
  codeb := tf.xeth.CodeAtBytes(registrar.HashRegAddr)
  codehash := common.BytesToHash(crypto.Sha3(codeb))

  // use resolver to register codehash->dochash->url
  // test if globalregistry works
  // registrar.HashRefAddr = "0x0"
  // registrar.UrlHintAddr = "0x0"
  reg := registrar.New(tf.xeth)
  _, err := reg.SetHashToHash(tf.coinbase, codehash, dochash)
  if err != nil {
    t.Errorf("error registering: %v", err)
  }
  _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///"+testFileName)
  if err != nil {
    t.Errorf("error registering: %v", err)
  }
  // apply txs to the state
  tf.applyTxs()

  // NatSpec info for register method of HashReg contract installed
  // now using the same transactions to check confirm messages

  tf.wantNatSpec = true // this is set so now the backend uses natspec confirmation
  _, err = reg.SetHashToHash(tf.coinbase, codehash, dochash)
  if err != nil {
    t.Errorf("error calling contract registry: %v", err)
  }

  fmt.Printf("GlobalRegistrar: %v, HashReg: %v, UrlHint: %v\n", registrar.GlobalRegistrarAddr, registrar.HashRegAddr, registrar.UrlHintAddr)
  if tf.lastConfirm != testExpNotice {
    t.Errorf("Wrong confirm message. expected '%v', got '%v'", testExpNotice, tf.lastConfirm)
  }

  // test unknown method
  exp := fmt.Sprintf(testExpNotice2, registrar.HashRegAddr)
  _, err = reg.SetOwner(tf.coinbase)
  if err != nil {
    t.Errorf("error setting owner: %v", err)
  }

  if tf.lastConfirm != exp {
    t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm)
  }

  // test unknown contract
  exp = fmt.Sprintf(testExpNotice3, registrar.UrlHintAddr)

  _, err = reg.SetUrlToHash(tf.coinbase, dochash, "file:///test.content")
  if err != nil {
    t.Errorf("error registering: %v", err)
  }

  if tf.lastConfirm != exp {
    t.Errorf("Wrong confirm message, expected '%v', got '%v'", exp, tf.lastConfirm)
  }

}