protocol optimization: verify hash that derives view key in contract, instead of the public key, saving on *lots* of gas
I propose an update to the existing swap protocol that will dramatically reduce the gas costs to deploy the contract and call Claim/Refund.

the current protocol verifies that the secret passed to the contract (either `s_a` or `s_b`) corresponds to the public key of either Alice or Bob (that was set when the contract was deployed) by performing an ed25519 scalar base multiplication and checking that the resulting point == the public key. this is expensive (around 1mil gas currently)

however, this can be replaced by only verifying a keccak256 hash (30 gas!!)

for background, a monero private view key is derived from the private spend key as follows:
```
func (k *PrivateSpendKey) View() (*PrivateViewKey, error) {
	h := Keccak256(k.key.Bytes())
	vk, err := ed25519.NewScalar().SetBytesWithClamping(h[:])
	if err != nil {
		return nil, err
	}

	return &PrivateViewKey{
		key: vk,
	}, nil
}
```

first, the spend key is hashed using keccak256 and then set to a point on the ed25519 curve using clamping. the resulting scalar is the view key.

the updated protocol is as follows:
1. in the key exchange step, Alice and Bob exchange public spend keys (`P_a` and `P_b`) and private view keys (`v_a` and `v_b`), and additionally the keccak256-hashes of their private spend keys (`h_a` and `h_b`) that are used to derive their private view keys. when each party receives the other party's keys, they verify that the hash they receive corresponds to the view key.
2. Alice deploys a Swap contract storing the keccak256 hashes `h_a` and `h_b` in the contract. Claim can be called by revealing the pre-image to `h_b` (ie. `s_b`) and Refund can be called by revealing the pre-image to `h_a` (ie. `s_a`)
3. the rest of the protocol proceeds as usual - Bob locks his XMR in the account `P_a + P_b`, which is viewable with `v_a + v_b` and spendable with `s_a + s_b`. either Claim or Refund will be called on the contract, and thus one party will end up with the spend key to the account at completion of the protocol.

note: we don't verify in step 1 that the view key corresponds to the public spend key, as it's impossible to do so. however, if the public spend key does not correspond to the view key, then the funds cannot be viewed. before Bob locks his XMR, he can check that he can generate a view-only wallet using the summation of the two view keys. if he cannot, he should abort the protocol as the view keys and public keys do not correspond. or, on Alice's side, if she cannot view the funds after they are locked (as the view keys are wrong), she should abort.

implications:
- the only drawback I see to this method is that both Alice and Bob now have the secret view key to the account with the locked XMR, so at the end of the protocol, now both Alice and Bob can view when the funds are transferred out. I don't see this being an issue, as Alice can just transfer the funds to another account once the swap is done if she wishes. either way, both parties know of the amount being swapped to begin with, so it doesn't really reduce privacy imo.
- actually, as the libp2p messages aren't encrypted, there's a chance *anyone* can get the secret view keys and create a view-only wallet for the account. however if someone intercepts the messages between Alice and Bob, they also already know of the amounts transferred and where. so, as long as Alice transfers her funds out after the swap (if she cares about someone viewing the account), I think this is ok.

I'll work on updating the contract/code for this and reply with the benchmark updates. and of course, let me know if there are security issuse with this proposed update.