Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support zero amount transfer with any ringsize #146

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 77 additions & 58 deletions walletapi/daemon_communication.go
Original file line number Diff line number Diff line change
Expand Up @@ -868,8 +868,31 @@ func (w *Wallet_Memory) synchistory_block(scid crypto.Hash, topo int64) (err err

switch {
case previous_balance == changed_balance: //ring member/* handle 0 value tx but fees is deducted */
//fmt.Printf("Anon Ring Member in TX %s\n", bl.Tx_hashes[i].String())
ring_member = true
// Ringsize is 2 we are obviously not a ring member
if tx.Payloads[t].Statement.RingSize == 2 {
w.handle_incoming_tx(&entry, &tx, t, j, previous_balance, changed_balance)
} else {
set_ring_member := true
// let's brute force to check if we didn't received a payload
shared_key := crypto.GenerateSharedSecret(w.account.Keys.Secret.BigInt(), tx.Payloads[t].Statement.D)
if entry.Amount == entry.Burn && tx.Payloads[t].RPCType == transaction.ENCRYPTED_DEFAULT_PAYLOAD_CBOR {
var data_copy []byte
data_copy = append(data_copy, tx.Payloads[t].RPCPayload...)
our_key := w.GetAddress().PublicKey.EncodeCompressed()
crypto.EncryptDecryptUserData(crypto.Keccak256(shared_key[:], our_key), data_copy)

var args rpc.Arguments
if err = args.UnmarshalBinary(data_copy[1:]); err == nil {
// we are not a ring member
w.handle_incoming_tx(&entry, &tx, t, j, previous_balance, changed_balance)
set_ring_member = false
}
}

if set_ring_member {
ring_member = true
}
}
case previous_balance > changed_balance: // we generated this tx
entry.Burn = tx.Payloads[t].BurnValue
entry.Amount = previous_balance - changed_balance - (tx.Payloads[t].Statement.Fees)
Expand Down Expand Up @@ -971,62 +994,7 @@ func (w *Wallet_Memory) synchistory_block(scid crypto.Hash, topo int64) (err err
}

case previous_balance < changed_balance: // someone sentus this amount
entry.Amount = changed_balance - previous_balance
entry.Incoming = true

// we should decode the payment id
var x bn256.G1
x.ScalarMult(crypto.G, new(big.Int).SetInt64(0-int64(entry.Amount))) // decrease amounts
x.Add(new(bn256.G1).Set(&x), tx.Payloads[t].Statement.C[j]) // get the blinder

blinder := &x

shared_key := crypto.GenerateSharedSecret(w.account.Keys.Secret.BigInt(), tx.Payloads[t].Statement.D)

// enable receiver side proofs
proof := rpc.NewAddressFromKeys((*crypto.Point)(blinder))
proof.Proof = true
proof.Arguments = rpc.Arguments{{Name: "H", DataType: rpc.DataHash, Value: crypto.Hash(shared_key)}, {Name: rpc.RPC_VALUE_TRANSFER, DataType: rpc.DataUint64, Value: uint64(entry.Amount)}}
entry.Proof = proof.String()

entry.PayloadType = tx.Payloads[t].RPCType
switch tx.Payloads[t].RPCType {

case 0:

//fmt.Printf("decoding encrypted payload %x\n",tx.Payloads[t].RPCPayload)
crypto.EncryptDecryptUserData(crypto.Keccak256(shared_key[:], w.GetAddress().PublicKey.EncodeCompressed()), tx.Payloads[t].RPCPayload)
//fmt.Printf("decoded plaintext payload %x\n",tx.Payloads[t].RPCPayload)
sender_idx := uint(tx.Payloads[t].RPCPayload[0])
// if ring size is 2, the other party is the sender so mark it so
if uint(tx.Payloads[t].Statement.RingSize) == 2 {
sender_idx = 0
if j == 0 {
sender_idx = 1
}
}

if sender_idx <= uint(tx.Payloads[t].Statement.RingSize) {
addr := rpc.NewAddressFromKeys((*crypto.Point)(tx.Payloads[t].Statement.Publickeylist[sender_idx]))
addr.Mainnet = w.GetNetwork()
entry.Sender = addr.String()
}

entry.Payload = append(entry.Payload, tx.Payloads[t].RPCPayload[1:]...)
entry.Data = append(entry.Data, tx.Payloads[t].RPCPayload[:]...)

args, _ := entry.ProcessPayload()
_ = args

// fmt.Printf("data received %s idx %d arguments %s\n", string(entry.Payload), sender_idx, args)

default:
entry.PayloadError = fmt.Sprintf("unknown payload type %d", tx.Payloads[t].RPCType)
entry.Payload = tx.Payloads[t].RPCPayload
}

//fmt.Printf("Received %s amount in TX(%d) %s payment id %x Src_ID %s data %s\n", globals.FormatMoney(changed_balance-previous_balance), tx.Height, bl.Tx_hashes[i].String(), entry.PaymentID, tx.Src_ID, tx.Data)
//fmt.Printf("Received amount in TX(%d) %s payment id %x Src_ID %s data %s\n", tx.Height, bl.Tx_hashes[i].String(), entry.PaymentID, tx.SrcID, tx.Data)
w.handle_incoming_tx(&entry, &tx, t, j, previous_balance, changed_balance)
total_received += (changed_balance - previous_balance)
}

Expand Down Expand Up @@ -1072,3 +1040,54 @@ func (w *Wallet_Memory) synchistory_block(scid crypto.Hash, topo int64) (err err
return nil

}

func (w *Wallet_Memory) handle_incoming_tx(entry *rpc.Entry, tx *transaction.Transaction, t int, j int, previous_balance uint64, changed_balance uint64) {
entry.Amount = changed_balance - previous_balance
entry.Incoming = true

// we should decode the payment id
var x bn256.G1
x.ScalarMult(crypto.G, new(big.Int).SetInt64(0-int64(entry.Amount))) // decrease amounts
x.Add(new(bn256.G1).Set(&x), tx.Payloads[t].Statement.C[j]) // get the blinder

blinder := &x

shared_key := crypto.GenerateSharedSecret(w.account.Keys.Secret.BigInt(), tx.Payloads[t].Statement.D)

// enable receiver side proofs
proof := rpc.NewAddressFromKeys((*crypto.Point)(blinder))
proof.Proof = true
proof.Arguments = rpc.Arguments{{Name: "H", DataType: rpc.DataHash, Value: crypto.Hash(shared_key)}, {Name: rpc.RPC_VALUE_TRANSFER, DataType: rpc.DataUint64, Value: uint64(entry.Amount)}}
entry.Proof = proof.String()

entry.PayloadType = tx.Payloads[t].RPCType
switch tx.Payloads[t].RPCType {
case 0:
crypto.EncryptDecryptUserData(crypto.Keccak256(shared_key[:], w.GetAddress().PublicKey.EncodeCompressed()), tx.Payloads[t].RPCPayload)
sender_idx := uint(tx.Payloads[t].RPCPayload[0])
// if ring size is 2, the other party is the sender so mark it so
// Because before this function, we check current ring member is equal to our address
// So if j is 0, then sender_idx is 1 and vice versa
if uint(tx.Payloads[t].Statement.RingSize) == 2 {
sender_idx = 0
if j == 0 {
sender_idx = 1
}
}

if sender_idx <= uint(tx.Payloads[t].Statement.RingSize) {
addr := rpc.NewAddressFromKeys((*crypto.Point)(tx.Payloads[t].Statement.Publickeylist[sender_idx]))
addr.Mainnet = w.GetNetwork()
entry.Sender = addr.String()
}

entry.Payload = append(entry.Payload, tx.Payloads[t].RPCPayload[1:]...)
entry.Data = append(entry.Data, tx.Payloads[t].RPCPayload[:]...)

args, _ := entry.ProcessPayload()
_ = args
default:
entry.PayloadError = fmt.Sprintf("unknown payload type %d", tx.Payloads[t].RPCType)
entry.Payload = tx.Payloads[t].RPCPayload
}
}