test client: factor out wallet sync API into class
In preparation for adding the LBRY SDK api class
This commit is contained in:
parent
66e5cf7fe7
commit
d467559dcd
4 changed files with 159 additions and 107 deletions
|
@ -103,7 +103,7 @@ func getPostData(w http.ResponseWriter, req *http.Request, reqStruct PostRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.NewDecoder(req.Body).Decode(&reqStruct); err != nil {
|
if err := json.NewDecoder(req.Body).Decode(&reqStruct); err != nil {
|
||||||
errorJson(w, http.StatusBadRequest, "Malformed request body JSON")
|
errorJson(w, http.StatusBadRequest, "Request body JSON malformed or structure mismatch")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,9 +25,9 @@ Now that the account exists, grab an auth token with both clients.
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c1.get_auth_token()
|
>>> c1.get_auth_token()
|
||||||
Got auth token: a489d5cacc0a3db4811c34d203683482d90c605b03ae007fa5ae32ef17252bd9
|
Got auth token: b646a357038d394ef7b70f350c666aeb29e24072c7eeaaad4fb6759c1fca281a
|
||||||
>>> c2.get_auth_token()
|
>>> c2.get_auth_token()
|
||||||
Got auth token: 1fe687db8ab493ed260f499b674cfa49edefd3c03a718905c62d3f850dc50567
|
Got auth token: bd24ae67cb1bde2da8a27f2c2e5ec8ff1f9bebccb11e16dd35aea31bf422133c
|
||||||
```
|
```
|
||||||
|
|
||||||
## Syncing
|
## Syncing
|
||||||
|
@ -38,7 +38,7 @@ Note that after POSTing, it says it "got" a new wallet. This is because the POST
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c1.new_wallet_state()
|
>>> c1.new_wallet_state()
|
||||||
>>> c1.post_wallet()
|
>>> c1.update_wallet()
|
||||||
Successfully updated wallet state on server
|
Successfully updated wallet state on server
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=1, encrypted_wallet='-')
|
WalletState(sequence=1, encrypted_wallet='-')
|
||||||
|
@ -57,7 +57,7 @@ WalletState(sequence=1, encrypted_wallet='-')
|
||||||
Push a new version, GET it with the other client. Even though we haven't edited the encrypted wallet yet, we can still increment the sequence number.
|
Push a new version, GET it with the other client. Even though we haven't edited the encrypted wallet yet, we can still increment the sequence number.
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c2.post_wallet()
|
>>> c2.update_wallet()
|
||||||
Successfully updated wallet state on server
|
Successfully updated wallet state on server
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=2, encrypted_wallet='-')
|
WalletState(sequence=2, encrypted_wallet='-')
|
||||||
|
@ -75,21 +75,21 @@ For demo purposes, this test client represents each change to the wallet by appe
|
||||||
'-'
|
'-'
|
||||||
>>> c1.change_encrypted_wallet()
|
>>> c1.change_encrypted_wallet()
|
||||||
>>> c1.cur_encrypted_wallet()
|
>>> c1.cur_encrypted_wallet()
|
||||||
'-:cfF6'
|
'-:a776'
|
||||||
```
|
```
|
||||||
|
|
||||||
The wallet is synced between the clients.
|
The wallet is synced between the clients.
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c1.post_wallet()
|
>>> c1.update_wallet()
|
||||||
Successfully updated wallet state on server
|
Successfully updated wallet state on server
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=3, encrypted_wallet='-:cfF6')
|
WalletState(sequence=3, encrypted_wallet='-:a776')
|
||||||
>>> c2.get_wallet()
|
>>> c2.get_wallet()
|
||||||
Got latest walletState:
|
Got latest walletState:
|
||||||
WalletState(sequence=3, encrypted_wallet='-:cfF6')
|
WalletState(sequence=3, encrypted_wallet='-:a776')
|
||||||
>>> c2.cur_encrypted_wallet()
|
>>> c2.cur_encrypted_wallet()
|
||||||
'-:cfF6'
|
'-:a776'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Merging Changes
|
## Merging Changes
|
||||||
|
@ -100,44 +100,44 @@ Both clients create changes. They now have diverging wallets.
|
||||||
>>> c1.change_encrypted_wallet()
|
>>> c1.change_encrypted_wallet()
|
||||||
>>> c2.change_encrypted_wallet()
|
>>> c2.change_encrypted_wallet()
|
||||||
>>> c1.cur_encrypted_wallet()
|
>>> c1.cur_encrypted_wallet()
|
||||||
'-:cfF6:565b'
|
'-:a776:8fc8'
|
||||||
>>> c2.cur_encrypted_wallet()
|
>>> c2.cur_encrypted_wallet()
|
||||||
'-:cfF6:6De1'
|
'-:a776:2433'
|
||||||
```
|
```
|
||||||
|
|
||||||
One client POSTs its change first.
|
One client POSTs its change first.
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c1.post_wallet()
|
>>> c1.update_wallet()
|
||||||
Successfully updated wallet state on server
|
Successfully updated wallet state on server
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=4, encrypted_wallet='-:cfF6:565b')
|
WalletState(sequence=4, encrypted_wallet='-:a776:8fc8')
|
||||||
```
|
```
|
||||||
|
|
||||||
The other client pulls that change, and _merges_ those changes on top of the changes it had saved locally.
|
The other client pulls that change, and _merges_ those changes on top of the changes it had saved locally.
|
||||||
|
|
||||||
The _merge base_ that a given client uses is the last version that it successfully got from or POSTed to the server. You can see the merge base here: `"-:cfF6"`, the first part of the wallet which both clients had in common before the merge.
|
The _merge base_ that a given client uses is the last version that it successfully got from or POSTed to the server. You can see the merge base here: `"-:a776"`, the first part of the wallet which both clients had in common before the merge.
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c2.get_wallet()
|
>>> c2.get_wallet()
|
||||||
Got latest walletState:
|
Got latest walletState:
|
||||||
WalletState(sequence=4, encrypted_wallet='-:cfF6:565b')
|
WalletState(sequence=4, encrypted_wallet='-:a776:8fc8')
|
||||||
>>> c2.cur_encrypted_wallet()
|
>>> c2.cur_encrypted_wallet()
|
||||||
'-:cfF6:565b:6De1'
|
'-:a776:8fc8:2433'
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, the client with the merged wallet pushes it to the server, and the other client GETs the update.
|
Finally, the client with the merged wallet pushes it to the server, and the other client GETs the update.
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c2.post_wallet()
|
>>> c2.update_wallet()
|
||||||
Successfully updated wallet state on server
|
Successfully updated wallet state on server
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=5, encrypted_wallet='-:cfF6:565b:6De1')
|
WalletState(sequence=5, encrypted_wallet='-:a776:8fc8:2433')
|
||||||
>>> c1.get_wallet()
|
>>> c1.get_wallet()
|
||||||
Got latest walletState:
|
Got latest walletState:
|
||||||
WalletState(sequence=5, encrypted_wallet='-:cfF6:565b:6De1')
|
WalletState(sequence=5, encrypted_wallet='-:a776:8fc8:2433')
|
||||||
>>> c1.cur_encrypted_wallet()
|
>>> c1.cur_encrypted_wallet()
|
||||||
'-:cfF6:565b:6De1'
|
'-:a776:8fc8:2433'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Conflicts
|
## Conflicts
|
||||||
|
@ -148,22 +148,22 @@ A client cannot POST if it is not up to date. It needs to merge in any new chang
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c2.change_encrypted_wallet()
|
>>> c2.change_encrypted_wallet()
|
||||||
>>> c2.post_wallet()
|
>>> c2.update_wallet()
|
||||||
Successfully updated wallet state on server
|
Successfully updated wallet state on server
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=6, encrypted_wallet='-:cfF6:565b:6De1:053a')
|
WalletState(sequence=6, encrypted_wallet='-:a776:8fc8:2433:0FdD')
|
||||||
>>> c1.change_encrypted_wallet()
|
>>> c1.change_encrypted_wallet()
|
||||||
>>> c1.post_wallet()
|
>>> c1.update_wallet()
|
||||||
Wallet state out of date. Getting updated wallet state. Try posting again after this.
|
Wallet state out of date. Getting updated wallet state. Try posting again after this.
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=6, encrypted_wallet='-:cfF6:565b:6De1:053a')
|
WalletState(sequence=6, encrypted_wallet='-:a776:8fc8:2433:0FdD')
|
||||||
```
|
```
|
||||||
|
|
||||||
Now the merge is complete, and the client can make a second POST request containing the merged wallet.
|
Now the merge is complete, and the client can make a second POST request containing the merged wallet.
|
||||||
|
|
||||||
```
|
```
|
||||||
>>> c1.post_wallet()
|
>>> c1.update_wallet()
|
||||||
Successfully updated wallet state on server
|
Successfully updated wallet state on server
|
||||||
Got new walletState:
|
Got new walletState:
|
||||||
WalletState(sequence=7, encrypted_wallet='-:cfF6:565b:6De1:053a:6774')
|
WalletState(sequence=7, encrypted_wallet='-:a776:8fc8:2433:0FdD:BA43')
|
||||||
```
|
```
|
||||||
|
|
|
@ -59,7 +59,7 @@ Note that after POSTing, it says it "got" a new wallet. This is because the POST
|
||||||
|
|
||||||
code_block("""
|
code_block("""
|
||||||
c1.new_wallet_state()
|
c1.new_wallet_state()
|
||||||
c1.post_wallet()
|
c1.update_wallet()
|
||||||
""")
|
""")
|
||||||
|
|
||||||
print("""
|
print("""
|
||||||
|
@ -77,7 +77,7 @@ Push a new version, GET it with the other client. Even though we haven't edited
|
||||||
""")
|
""")
|
||||||
|
|
||||||
code_block("""
|
code_block("""
|
||||||
c2.post_wallet()
|
c2.update_wallet()
|
||||||
c1.get_wallet()
|
c1.get_wallet()
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
@ -98,7 +98,7 @@ The wallet is synced between the clients.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
code_block("""
|
code_block("""
|
||||||
c1.post_wallet()
|
c1.update_wallet()
|
||||||
c2.get_wallet()
|
c2.get_wallet()
|
||||||
c2.cur_encrypted_wallet()
|
c2.cur_encrypted_wallet()
|
||||||
""")
|
""")
|
||||||
|
@ -123,7 +123,7 @@ One client POSTs its change first.
|
||||||
""")
|
""")
|
||||||
|
|
||||||
code_block("""
|
code_block("""
|
||||||
c1.post_wallet()
|
c1.update_wallet()
|
||||||
""")
|
""")
|
||||||
|
|
||||||
print("""
|
print("""
|
||||||
|
@ -142,7 +142,7 @@ Finally, the client with the merged wallet pushes it to the server, and the othe
|
||||||
""")
|
""")
|
||||||
|
|
||||||
code_block("""
|
code_block("""
|
||||||
c2.post_wallet()
|
c2.update_wallet()
|
||||||
c1.get_wallet()
|
c1.get_wallet()
|
||||||
c1.cur_encrypted_wallet()
|
c1.cur_encrypted_wallet()
|
||||||
""")
|
""")
|
||||||
|
@ -157,9 +157,9 @@ A client cannot POST if it is not up to date. It needs to merge in any new chang
|
||||||
|
|
||||||
code_block("""
|
code_block("""
|
||||||
c2.change_encrypted_wallet()
|
c2.change_encrypted_wallet()
|
||||||
c2.post_wallet()
|
c2.update_wallet()
|
||||||
c1.change_encrypted_wallet()
|
c1.change_encrypted_wallet()
|
||||||
c1.post_wallet()
|
c1.update_wallet()
|
||||||
""")
|
""")
|
||||||
|
|
||||||
print("""
|
print("""
|
||||||
|
@ -167,5 +167,5 @@ Now the merge is complete, and the client can make a second POST request contain
|
||||||
""")
|
""")
|
||||||
|
|
||||||
code_block("""
|
code_block("""
|
||||||
c1.post_wallet()
|
c1.update_wallet()
|
||||||
""")
|
""")
|
||||||
|
|
|
@ -5,18 +5,101 @@ from pprint import pprint
|
||||||
|
|
||||||
CURRENT_VERSION = 1
|
CURRENT_VERSION = 1
|
||||||
|
|
||||||
|
WalletState = namedtuple('WalletState', ['sequence', 'encrypted_wallet'])
|
||||||
|
|
||||||
|
class WalletSync():
|
||||||
BASE_URL = 'http://localhost:8090'
|
BASE_URL = 'http://localhost:8090'
|
||||||
AUTH_URL = BASE_URL + '/auth/full'
|
AUTH_URL = BASE_URL + '/auth/full'
|
||||||
REGISTER_URL = BASE_URL + '/signup'
|
REGISTER_URL = BASE_URL + '/signup'
|
||||||
WALLET_URL = BASE_URL + '/wallet'
|
WALLET_URL = BASE_URL + '/wallet'
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def register(cls, email, password):
|
||||||
|
body = json.dumps({
|
||||||
|
'email': email,
|
||||||
|
'password': password,
|
||||||
|
})
|
||||||
|
response = requests.post(cls.REGISTER_URL, body)
|
||||||
|
if response.status_code != 201:
|
||||||
|
print ('Error', response.status_code)
|
||||||
|
print (response.content)
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_auth_token(cls, email, password, device_id):
|
||||||
|
body = json.dumps({
|
||||||
|
'email': email,
|
||||||
|
'password': password,
|
||||||
|
'deviceId': device_id,
|
||||||
|
})
|
||||||
|
response = requests.post(cls.AUTH_URL, body)
|
||||||
|
if response.status_code != 200:
|
||||||
|
print ('Error', response.status_code)
|
||||||
|
print (response.content)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return response.json()['token']
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_wallet(cls, token):
|
||||||
|
params = {
|
||||||
|
'token': token,
|
||||||
|
}
|
||||||
|
response = requests.get(cls.WALLET_URL, params=params)
|
||||||
|
|
||||||
|
# TODO check response version on client side now
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
print ('Error', response.status_code)
|
||||||
|
print (response.content)
|
||||||
|
return None, None
|
||||||
|
|
||||||
|
wallet_state = WalletState(
|
||||||
|
encrypted_wallet=response.json()['encryptedWallet'],
|
||||||
|
sequence=response.json()['sequence'],
|
||||||
|
)
|
||||||
|
hmac = response.json()['hmac']
|
||||||
|
return wallet_state, hmac
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def update_wallet(cls, wallet_state, hmac, token):
|
||||||
|
body = json.dumps({
|
||||||
|
'version': CURRENT_VERSION,
|
||||||
|
'token': token,
|
||||||
|
"encryptedWallet": wallet_state.encrypted_wallet,
|
||||||
|
"sequence": wallet_state.sequence,
|
||||||
|
"hmac": hmac,
|
||||||
|
})
|
||||||
|
|
||||||
|
response = requests.post(cls.WALLET_URL, body)
|
||||||
|
|
||||||
|
# TODO check that response.json().version == CURRENT_VERSION
|
||||||
|
|
||||||
|
if response.status_code == 200:
|
||||||
|
conflict = False
|
||||||
|
print ('Successfully updated wallet state on server')
|
||||||
|
elif response.status_code == 409:
|
||||||
|
conflict = True
|
||||||
|
print ('Wallet state out of date. Getting updated wallet state. Try posting again after this.')
|
||||||
|
# Not an error! We still want to merge in the returned wallet.
|
||||||
|
else:
|
||||||
|
print ('Error', response.status_code)
|
||||||
|
print (response.content)
|
||||||
|
return None, None, None
|
||||||
|
|
||||||
|
wallet_state = WalletState(
|
||||||
|
encrypted_wallet=response.json()['encryptedWallet'],
|
||||||
|
sequence=response.json()['sequence'],
|
||||||
|
)
|
||||||
|
hmac = response.json()['hmac']
|
||||||
|
return wallet_state, hmac, conflict
|
||||||
|
|
||||||
# TODO - We should have:
|
# TODO - We should have:
|
||||||
# * self.last_synced_wallet_state - as described
|
# * self.last_synced_wallet_state - as described
|
||||||
# * self.current_wallet_state - WalletState(cur_encrypted_wallet(), sequence + 1) - and current_wallet_state
|
# * self.current_wallet_state - WalletState(cur_encrypted_wallet(), sequence + 1) - and current_wallet_state
|
||||||
# We don't need it yet but we'd be avoiding the entire point of the syncing system. At least keep it around in this demo.
|
# We don't need it yet but we'd be avoiding the entire point of the syncing system. At least keep it around in this demo.
|
||||||
|
|
||||||
WalletState = namedtuple('WalletState', ['sequence', 'encrypted_wallet'])
|
|
||||||
|
|
||||||
# TODO - do this correctly. This is a hack example.
|
# TODO - do this correctly. This is a hack example.
|
||||||
def derive_login_password(root_password):
|
def derive_login_password(root_password):
|
||||||
return hashlib.sha256(root_password.encode('utf-8')).hexdigest()[:10]
|
return hashlib.sha256(root_password.encode('utf-8')).hexdigest()[:10]
|
||||||
|
@ -88,29 +171,22 @@ class Client():
|
||||||
self.root_password = root_password
|
self.root_password = root_password
|
||||||
|
|
||||||
def register(self):
|
def register(self):
|
||||||
body = json.dumps({
|
success = WalletSync.register(
|
||||||
'email': self.email,
|
self.email,
|
||||||
'password': derive_login_password(self.root_password),
|
derive_login_password(self.root_password),
|
||||||
})
|
)
|
||||||
response = requests.post(REGISTER_URL, body)
|
if success:
|
||||||
if response.status_code != 201:
|
|
||||||
print ('Error', response.status_code)
|
|
||||||
print (response.content)
|
|
||||||
return
|
|
||||||
print ("Registered")
|
print ("Registered")
|
||||||
|
|
||||||
def get_auth_token(self):
|
def get_auth_token(self):
|
||||||
body = json.dumps({
|
token = WalletSync.get_auth_token(
|
||||||
'email': self.email,
|
self.email,
|
||||||
'password': derive_login_password(self.root_password),
|
derive_login_password(self.root_password),
|
||||||
'deviceId': self.device_id,
|
self.device_id,
|
||||||
})
|
)
|
||||||
response = requests.post(AUTH_URL, body)
|
if not token:
|
||||||
if response.status_code != 200:
|
|
||||||
print ('Error', response.status_code)
|
|
||||||
print (response.content)
|
|
||||||
return
|
return
|
||||||
self.auth_token = json.loads(response.content)['token']
|
self.auth_token = token
|
||||||
print ("Got auth token: ", self.auth_token)
|
print ("Got auth token: ", self.auth_token)
|
||||||
|
|
||||||
# TODO - What about cases where we are managing multiple different wallets?
|
# TODO - What about cases where we are managing multiple different wallets?
|
||||||
|
@ -119,31 +195,22 @@ class Client():
|
||||||
# want to annotate them with which account we're talking about. Again, we
|
# want to annotate them with which account we're talking about. Again, we
|
||||||
# should see how LBRY Desktop/SDK deal with it.
|
# should see how LBRY Desktop/SDK deal with it.
|
||||||
def get_wallet(self):
|
def get_wallet(self):
|
||||||
params = {
|
new_wallet_state, hmac = WalletSync.get_wallet(self.auth_token)
|
||||||
'token': self.auth_token,
|
|
||||||
}
|
# If there was a failure
|
||||||
response = requests.get(WALLET_URL, params=params)
|
if not new_wallet_state:
|
||||||
if response.status_code != 200:
|
|
||||||
# TODO check response version on client side now
|
|
||||||
print ('Error', response.status_code)
|
|
||||||
print (response.content)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
hmac_key = derive_hmac_key(self.root_password)
|
hmac_key = derive_hmac_key(self.root_password)
|
||||||
|
|
||||||
new_wallet_state = WalletState(
|
|
||||||
encrypted_wallet=response.json()['encryptedWallet'],
|
|
||||||
sequence=response.json()['sequence'],
|
|
||||||
)
|
|
||||||
hmac = response.json()['hmac']
|
|
||||||
if not check_hmac(new_wallet_state, hmac_key, hmac):
|
if not check_hmac(new_wallet_state, hmac_key, hmac):
|
||||||
print ('Error - bad hmac on new wallet')
|
print ('Error - bad hmac on new wallet')
|
||||||
print (response.content)
|
print (new_wallet_state, hmac)
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.wallet_state != new_wallet_state and not self._validate_new_wallet_state(new_wallet_state):
|
if self.wallet_state != new_wallet_state and not self._validate_new_wallet_state(new_wallet_state):
|
||||||
print ('Error - new wallet does not validate')
|
print ('Error - new wallet does not validate')
|
||||||
print (response.content)
|
print ('current:', self.wallet_state)
|
||||||
|
print ('got:', new_wallet_state)
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.wallet_state is None:
|
if self.wallet_state is None:
|
||||||
|
@ -156,7 +223,7 @@ class Client():
|
||||||
print ("Got latest walletState:")
|
print ("Got latest walletState:")
|
||||||
pprint(self.wallet_state)
|
pprint(self.wallet_state)
|
||||||
|
|
||||||
def post_wallet(self):
|
def update_wallet(self):
|
||||||
# Create a *new* wallet state, indicating that it was last updated by this
|
# Create a *new* wallet state, indicating that it was last updated by this
|
||||||
# device, with the updated sequence, and include our local encrypted wallet changes.
|
# device, with the updated sequence, and include our local encrypted wallet changes.
|
||||||
# Don't set self.wallet_state to this until we know that it's accepted by
|
# Don't set self.wallet_state to this until we know that it's accepted by
|
||||||
|
@ -171,45 +238,30 @@ class Client():
|
||||||
encrypted_wallet=self.cur_encrypted_wallet(),
|
encrypted_wallet=self.cur_encrypted_wallet(),
|
||||||
sequence=self.wallet_state.sequence + 1
|
sequence=self.wallet_state.sequence + 1
|
||||||
)
|
)
|
||||||
wallet_request = {
|
hmac = create_hmac(submitted_wallet_state, hmac_key)
|
||||||
'version': CURRENT_VERSION,
|
|
||||||
'token': self.auth_token,
|
|
||||||
"encryptedWallet": submitted_wallet_state.encrypted_wallet,
|
|
||||||
"sequence": submitted_wallet_state.sequence,
|
|
||||||
"hmac": create_hmac(submitted_wallet_state, hmac_key),
|
|
||||||
}
|
|
||||||
|
|
||||||
response = requests.post(WALLET_URL, json.dumps(wallet_request))
|
# Submit our wallet, get the latest wallet back as a response
|
||||||
|
new_wallet_state, new_hmac, conflict = WalletSync.update_wallet(submitted_wallet_state, hmac, self.auth_token)
|
||||||
|
|
||||||
if response.status_code == 200:
|
# If there was a failure (not just a conflict)
|
||||||
# TODO check response version on client side now
|
if not new_wallet_state:
|
||||||
# Our local changes are no longer local, so we reset them
|
|
||||||
self._encrypted_wallet_local_changes = ''
|
|
||||||
print ('Successfully updated wallet state on server')
|
|
||||||
elif response.status_code == 409:
|
|
||||||
print ('Wallet state out of date. Getting updated wallet state. Try posting again after this.')
|
|
||||||
# Don't return yet! We got the updated state here, so we still process it below.
|
|
||||||
else:
|
|
||||||
print ('Error', response.status_code)
|
|
||||||
print (response.content)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# Now we get a new wallet back as a response
|
# If there's not a conflict, we submitted successfully and should reset our previously local changes
|
||||||
# TODO - factor this code into the same thing as the get_wallet function
|
if not conflict:
|
||||||
|
self._encrypted_wallet_local_changes = ''
|
||||||
|
|
||||||
new_wallet_state = WalletState(
|
# TODO - there's some code in common here with the get_wallet function. factor it out.
|
||||||
encrypted_wallet=response.json()['encryptedWallet'],
|
|
||||||
sequence=response.json()['sequence'],
|
if not check_hmac(new_wallet_state, hmac_key, new_hmac):
|
||||||
)
|
|
||||||
hmac = response.json()['hmac']
|
|
||||||
if not check_hmac(new_wallet_state, hmac_key, hmac):
|
|
||||||
print ('Error - bad hmac on new wallet')
|
print ('Error - bad hmac on new wallet')
|
||||||
print (response.content)
|
print (new_wallet_state, hmac)
|
||||||
return
|
return
|
||||||
|
|
||||||
if submitted_wallet_state != new_wallet_state and not self._validate_new_wallet_state(new_wallet_state):
|
if submitted_wallet_state != new_wallet_state and not self._validate_new_wallet_state(new_wallet_state):
|
||||||
print ('Error - new wallet does not validate')
|
print ('Error - new wallet does not validate')
|
||||||
print (response.content)
|
print ('current:', self.wallet_state)
|
||||||
|
print ('got:', new_wallet_state)
|
||||||
return
|
return
|
||||||
|
|
||||||
self.wallet_state = new_wallet_state
|
self.wallet_state = new_wallet_state
|
||||||
|
|
Loading…
Reference in a new issue