public JSInput()
        {
            byte[] random_byte256 = new byte[32];
            using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(random_byte256);
            }
            key = new SpendingKey(new UInt256(random_byte256));

            note = new Note(key.address().a_pk, new Fixed8(0), UInt256.Random(), UInt256.Random(), UInt256.Random());

            witness = new byte[0];
            AssetID = new UInt256();
        }
        public virtual QrsProof prove(
            List <JSInput> inputs,
            List <JSOutput> outputs,
            List <Note> out_notes,
            List <byte[]> out_ciphertexts,
            UInt256 out_ephemeralKey,
            UInt256 pubKeyHash,
            UInt256 out_randomSeed,
            List <UInt256> out_macs,
            List <UInt256> out_nullifiers,
            List <UInt256> out_commitments,
            Fixed8 vpub_old,
            Fixed8 vpub_new,
            UInt256 rt,
            bool computeProof = true,
            // For paymentdisclosure, we need to retrieve the esk.
            // Reference as non-const parameter with default value leads to compile error.
            // So use pointer for simplicity.
            UInt256 out_esk = null
            )
        {
            Fixed8 lhs_value = vpub_old;
            Fixed8 rhs_value = vpub_new;

            for (int i = 0; i < inputs.Count; i++)
            {
                lhs_value += inputs[i].note.value;
                out_nullifiers.Add(inputs[i].Nullifier());
            }

            out_randomSeed = UInt256.Random();

            UInt256 h_sig = QrsJoinSplit.h_sig(out_randomSeed, out_nullifiers, pubKeyHash);

            UInt252 phi = new UInt252(UInt256.Random());

            for (int i = 0; i < outputs.Count; i++)
            {
                rhs_value += outputs[i].value;

                UInt256 r = UInt256.Random();

                out_notes.Add(outputs[i].note(phi, r, new Fixed8(i), h_sig));
            }

            if (lhs_value != rhs_value)
            {
                throw new ArgumentException();
            }

            for (int i = 0; i < outputs.Count; i++)
            {
                out_commitments.Add(out_notes[i].CM());
            }

            {
                NoteEncryption encryptor = new NoteEncryption(h_sig);

                for (int i = 0; i < outputs.Count; i++)
                {
                    NotePlaintext pt = new NotePlaintext(out_notes[i], outputs[i].memo);
                    out_ciphertexts.Add(pt.encrypt(encryptor, outputs[i].addr.pk_enc));
                }

                out_ephemeralKey = encryptor.get_epk();

                out_esk = encryptor.get_esk();
            }

            for (int i = 0; i < inputs.Count; i++)
            {
                out_macs.Add(PRFClass.PRF_pk(inputs[i].key, new Fixed8(i), h_sig));
            }



            return(null);
        }