Skip to content

Commit

Permalink
Implemented js-tests for new redemption connectors, and fixed errors
Browse files Browse the repository at this point in the history
  • Loading branch information
vsubhuman committed Jan 22, 2019
1 parent 42d26d2 commit 94606ad
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 12 deletions.
4 changes: 3 additions & 1 deletion js/Redemption.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export const redemptionKeyToAddress = (module, redemptionKey, magic) => {
if (redemptionKey.length !== REDEMPTION_PRIVATE_KEY_SIZE) {
return false;
}
const bufkey = newArray(module, seed);
const bufkey = newArray(module, redemptionKey);
const bufaddr = newArray0(module, 1024);
const rs = module.redemption_private_to_address(bufkey, magic, bufaddr);
let result = copyArray(module, bufaddr, rs);
Expand All @@ -37,6 +37,8 @@ export const createRedemptionTransaction = (module, redemptionKey, input, output
if (redemptionKey.length !== REDEMPTION_PRIVATE_KEY_SIZE) {
return false;
}
redemptionKey = [...Buffer.from(redemptionKey)];
input.id = Buffer.from(input.id).toString('hex');
const input_obj = { protocol_magic: magic, redemption_key: redemptionKey, input, output };
const input_str = JSON.stringify(input_obj);
const input_array = iconv.encode(input_str, 'utf8');
Expand Down
82 changes: 82 additions & 0 deletions js/tests/redemption.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
const expect = require('chai').expect;
const CardanoCrypto = require('../../dist/index.js');
const bs58 = require('bs58');
const cbor = require('cbor');
const crc = require('crc');

const TEST_VECTORS = [
{
redemptionKey: Buffer.from('qXQWDxI3JrlFRtC4SeQjeGzLbVXWBomYPbNO1Vfm1T4=', 'base64'),
expectedAddress: 'Ae2tdPwUPEZ1xZTLczMGYL5PhADi1nbFmESqS9vUuLkyUe1isQ77TRUE9NS',
txId: new Uint8Array([0xaa,0xd7,0x8a,0x13,0xb5,0x0a,0x01,0x4a,0x24,0x63,0x3c,0x7d,0x44,0xfd,0x8f,0x8d,0x18,0xf6,0x7b,0xbb,0x3f,0xa9,0xcb,0xce,0xdf,0x83,0x4a,0xc8,0x99,0x75,0x9d,0xcd]),
txOutIndex: 1,
coinValue: 12345678
}
];

let mkTest = (i) => {
const { redemptionKey, expectedAddress, txId, txOutIndex, coinValue } = TEST_VECTORS[i];
const cfg = CardanoCrypto.Config.defaultConfig();

describe('Test ' + i, function() {
before(async () => {
await CardanoCrypto.loadRustModule()
});

it('generates valid address', function() {
const a = CardanoCrypto.Redemption.redemptionKeyToAddress(redemptionKey, cfg.protocol_magic);
const [tagged, checksum] = cbor.decode(Buffer.from(a));
expect(crc.crc32(tagged.value)).equal(checksum);
});

it('creates address matching expected', function() {
const a = CardanoCrypto.Redemption.redemptionKeyToAddress(redemptionKey, cfg.protocol_magic);
expect(bs58.encode(Buffer.from(a))).equal(expectedAddress)
});

it('generates valid transaction', function () {
const address = CardanoCrypto.Redemption.redemptionKeyToAddress(redemptionKey, cfg.protocol_magic);
const input = { id: txId, index: txOutIndex };
const output = { address: bs58.encode(Buffer.from(address)), value: JSON.stringify(coinValue) };
const { result: { cbor_encoded_tx } } = CardanoCrypto.Redemption.createRedemptionTransaction(redemptionKey, input, output, cfg.protocol_magic);

// destruct result transaction
const [[resultInputs, resultOutputs, attributes], resultWitnesses] = cbor.decode(Buffer.from(cbor_encoded_tx));

// validate inputs
expect(resultInputs.length).equal(1);
expect(resultInputs[0].length).equal(2);
const [[intputType, inputTagged]] = resultInputs;
expect(intputType).equal(0);
const [inputId, inputIndex] = cbor.decode(inputTagged.value);
expect(inputIndex).equal(txOutIndex);
expect(inputId).deep.equal(txId);

// validate outputs
expect(resultInputs.length).equal(1);
expect(resultInputs[0].length).equal(2);
const [[outputAddress, outputValue]] = resultOutputs;
expect(cbor.encode(outputAddress)).deep.equal(address);
expect(outputValue).equal(coinValue);

// validate witness
expect(resultWitnesses.length).equal(1);
expect(resultWitnesses[0].length).equal(2);
const [[witnessType, witnessTagged]] = resultWitnesses;
expect(witnessType).equal(2);
const [witnessPub, witnessSign] = cbor.decode(witnessTagged.value);

// TODO: expecting fake witness data - fix after implementing signing in Rust
expect(witnessPub.toString('hex'))
.equal('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
expect(witnessSign.toString('hex'))
.equal('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff');
});
});
};

describe('Test redemption', function() {
for (let i = 0; i < TEST_VECTORS.length; i++) {
mkTest(i);
}
});
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@
"mocha": "5.0.2",
"nodemon": "1.17.1",
"wasm-loader": "1.3.0",
"webpack": "^3.11.0"
"webpack": "^3.11.0",
"bs58": "4.0.1",
"cbor": "4.1.4",
"crc": "3.8.0"
},
"peerDependencies": {
"bip39": "2.3.0"
Expand Down
39 changes: 29 additions & 10 deletions wallet-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1269,9 +1269,9 @@ pub extern "C" fn redemption_private_to_address(
let pub_key = priv_key.public();
let addr_type = address::AddrType::ATRedeem;
let addr_data = address::SpendingData::RedeemASD(pub_key.clone());
let magic = cardano::config::ProtocolMagic::new(protocol_magic);
let magic = cardano::config::ProtocolMagic::from(protocol_magic);
let addr_attr = address::Attributes::new_bootstrap_era(None,magic.into());
let address = address::ExtendedAddr::new(addr_type, addr_data, addr_attr));
let address = address::ExtendedAddr::new(addr_type, addr_data, addr_attr);
let address_bytes = cbor!(address).unwrap();
unsafe { write_data(&address_bytes, out) }
return address_bytes.len() as u32;
Expand All @@ -1280,7 +1280,7 @@ pub extern "C" fn redemption_private_to_address(
#[derive(Serialize, Deserialize, Debug)]
struct WalletRedeemInput {
protocol_magic: cardano::config::ProtocolMagic,
redemption_key: redeem::PrivateKey,
redemption_key: [u8; redeem::PRIVATEKEY_SIZE], // hex
input: TxIn,
output: TxOut,
}
Expand All @@ -1297,29 +1297,48 @@ pub extern "C" fn xwallet_redeem(
output_ptr: *mut c_uchar,
) -> i32 {
let data: WalletRedeemInput = input_json!(output_ptr, input_ptr, input_sz);
let &mut txbuilder = txbuild::TxBuilder::new();
let mut txbuilder = txbuild::TxBuilder::new();
txbuilder.add_input(&data.input.convert(), data.output.value.0);
txbuilder.add_output_value(&data.output.convert());
let tx: tx::Tx = jrpc_try!(
output_ptr,
txbuilder.make_tx()
.map_err(|e| JsValue::from_str(&format! {"{:?}", e}))
);
let witness = tx::TxInWitness::redeem(
data.protocol_magic, &data.redemption_key, &tx.0.id());
let &mut finalized = txbuild::TxFinalized::new(tx);
print!("Tx: {}", tx);
let redemption_key = jrpc_try!(
output_ptr,
redeem::PrivateKey::from_slice(&data.redemption_key)
);
print!("Key: {}", redemption_key);
let witness = jrpc_try!(
output_ptr,
create_redemption_witness(data.protocol_magic, &redemption_key, &tx.id())
);
let mut finalized = txbuild::TxFinalized::new(tx);
jrpc_try!(
output_ptr,
finalized.add_witness(witness)
.map_err(|e| JsValue::from_str(&format! {"{:?}", e}))
);
let txaux: tx::TxAux = jrpc_try!(
output_ptr,
finalized.make_txaux()
.map_err(|e| JsValue::from_str(&format! {"{:?}", e}))
);
let cbor = jrpc_try!(output_ptr, cbor!(&txaux));
jrpc_ok!(output_ptr, WalletRedeemOutput {
cbor_encoded_tx: cbor
})
}

fn create_redemption_witness(
protocol_magic: cardano::config::ProtocolMagic,
key: &redeem::PrivateKey,
txid: &tx::TxId,
) -> redeem::Result<tx::TxInWitness> {
// TODO: actual implementation
let s32 = (0..64).map(|_| "f").collect::<String>();
let s64 = (0..128).map(|_| "f").collect::<String>();
let pk = redeem::PublicKey::from_hex(&s32);
let sg = redeem::Signature::from_hex(&s64);
return pk.and_then(|k| sg.map(|s| (k, s)))
.map(|(k,s)| tx::TxInWitness::RedeemWitness(k, s));
}

0 comments on commit 94606ad

Please sign in to comment.