add licenses and readmes to some packages

This commit is contained in:
2023-09-03 21:35:24 -06:00
parent 1a9b12b27c
commit bcdb71624e
18 changed files with 108 additions and 723 deletions
+2 -1
View File
@@ -1,6 +1,7 @@
ISC License ISC License
Copyright (c) 2022-2023 Peter Harpending Copyright (c) 2022 Peter Harpending
Copyright (c) 2022-2023 Aeternity Foundation
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
+1
View File
@@ -1,4 +1,5 @@
Copyright (c) 2022 Blakejs contributors Copyright (c) 2022 Blakejs contributors
Copyright (c) 2023 Aeternity Foundation
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+1
View File
@@ -1,6 +1,7 @@
ISC License ISC License
Copyright (c) 2022 Peter Harpending Copyright (c) 2022 Peter Harpending
Copyright (c) 2022-2023 Aeternity Foundation
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
+2
View File
@@ -2,6 +2,8 @@
This is a jex port of [TweetNaCl](https://github.com/dchest/tweetnacl-js) This is a jex port of [TweetNaCl](https://github.com/dchest/tweetnacl-js)
Public Domain
## building ## building
``` ```
+16
View File
@@ -0,0 +1,16 @@
ISC License
Copyright (c) 2023 Aeternity Foundation
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+9
View File
@@ -0,0 +1,9 @@
# `vdk_aecrypt`
Aeternity-specific cryptography helper functions
## building
```
jex install
```
+1 -1
View File
@@ -1,6 +1,6 @@
{type, library}. {type, library}.
{realm, local}. {realm, local}.
{name, vdk_aecrypt}. {name, vdk_aecrypt}.
{version, "0.1.0"}. {version, "0.1.1"}.
{deps, ["local-blakejs-1.2.1", {deps, ["local-blakejs-1.2.1",
"local-vdk_binary-0.1.0"]}. "local-vdk_binary-0.1.0"]}.
+16
View File
@@ -0,0 +1,16 @@
ISC License
Copyright (c) 2023 Aeternity Foundation
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+9
View File
@@ -0,0 +1,9 @@
# `vdk_aertext`: AE Recovery Text
Seed phrases bad. AE Recovery Text good
## building
```
jex install
```
+16
View File
@@ -0,0 +1,16 @@
ISC License
Copyright (c) 2023 Aeternity Foundation
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+10
View File
@@ -0,0 +1,10 @@
# `vdk_aeser`
Serialization/deserialization routines for AE data. For instance, read a
`tx_...` string and figure out what the sender, recipient, payload, etc are
## building
```
jex install
```
+16
View File
@@ -0,0 +1,16 @@
ISC License
Copyright (c) 2023 Aeternity Foundation
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
+9
View File
@@ -0,0 +1,9 @@
# `vdk_base58`
Base58 encode/decode routines. See <https://zxq9.com/archives/2688>
## building
```
jex install
```
-24
View File
@@ -1,24 +0,0 @@
done:
- base64/base58 encoding/decoding
- rlp
today:
- pull apart data
tomorrow:
- basic easy serialization/deserialization
- serialize/deserialize examples
- (maybe) pull in awcp/sidekick
- sidekick: sign/propagate and sign/noprop
later:
- general node querying with parasite (think about autogeneration)
- simple aetto/ae/etc unit converter
- ghetto sophia ide
- general "send money to someone" page
GUI:
- simple testnet explorer
- contract ide
-403
View File
@@ -1,403 +0,0 @@
/**
* Node API constructor/deconstructor
*
* This is similar to serialization/deserialization, but not quite the same
* thing. It converts back and forth between different forms of
* "api-serialized" data.
*
* References:
* 1. https://github.com/aeternity/protocol/blob/master/serializations.md
* 2. https://github.com/aeternity/protocol/blob/master/node/api/api_encoding.md
*
* ## General type rules
*
* ```
* ERLANG TYPE | JS TYPE
* -------------------------------
* integer | bigint
* list | Array
* binary | Uint8Array
* ```
*
* # Example
*
* We start with the string `tx_+FgMAaEByWN+RgDnqzvC5n/GQOgjdkRE9DBV2l1VeKSaN1r6GNyhAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAACYdoYWluYW5hA7ZC1w==`.
*
* We can tell by the `tx_` prefix that this represents transaction data of
* some sort. But the rest of the data is totally opaque. The task of this
* module is to "humanize" that `tx_...` string and show what data is contained
* in the rest of it.
*
* The remainder of the string is a base64-encoded bytestring
*
* ```erlang
* 3> io:format("~tw~n", [base64:decode(<<"+FgMAaEByWN+RgDnqzvC5n/GQOgjdkRE9DBV2l1VeKSaN1r6GNyhAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAACYdoYWluYW5hA7ZC1w==">>)]).
* <<248,88,12,1,161,1,201,99,126,70,0,231,171,59,194,230,127,198,64,232,35,118,68,68,244,48,85,218,93,85,120,164,154,55,90,250,24,220,161,1,123,102,230,195,5,7,8,54,228,233,121,32,82,61,195,234,89,203,191,216,108,88,186,7,3,234,139,205,10,184,167,108,10,134,15,38,245,97,200,0,0,9,135,104,97,105,110,97,110,97,3,182,66,215>>
* ```
*
* That bytestring contains data encoded using Ethereum's RLP codec. Luckily, I
* wrote an RLP decoder. RLP has two types of data: binaries, and
* arbitrary-depth (possibly empty) lists of binaries.
*
* ```erlang
* -type decoded_data() :: binary() | [decoded_data()].
*
* -spec decode(RLP) -> {Data, Rest}
* when RLP :: binary(),
* Data :: decoded_data(),
* Rest :: binary().
* ```
*
* ```erlang
* 2> rlp:decode(base64:decode(<<"+FgMAaEByWN+RgDnqzvC5n/GQOgjdkRE9DBV2l1VeKSaN1r6GNyhAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAACYdoYWluYW5hA7ZC1w==">>)).
* {[<<"\f">>,
* <<1>>,
* <<1,201,99,126,70,0,231,171,59,194,230,127,198,64,232,35,
* 118,68,68,244,48,85,218,93,85,...>>,
* <<1,123,102,230,195,5,7,8,54,228,233,121,32,82,61,195,234,
* 89,203,191,216,108,88,186,...>>,
* <<"\n">>,
* <<15,38,245,97,200,0>>,
* <<0>>,
* <<"\t">>,<<"hainana">>],
* <<3,182,66,215>>}
* ```
*
* As expected, we get back the return tuple `{Data, Rest}`. `Rest` is the double-sha256 of the beginning
*
* ```erlang
* 3> X = base64:decode(<<"+FgMAaEByWN+RgDnqzvC5n/GQOgjdkRE9DBV2l1VeKSaN1r6GNyhAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAACYdoYWluYW5hA7ZC1w==">>).
* <<248,88,12,1,161,1,201,99,126,70,0,231,171,59,194,230,
* 127,198,64,232,35,118,68,68,244,48,85,218,93,...>>
* 4> SizeX = byte_size(X).
* 94
* 6> <<RLPEncodedData:(SizeX - 4)/binary, Hash/binary>> = X.
* <<248,88,12,1,161,1,201,99,126,70,0,231,171,59,194,230,
* 127,198,64,232,35,118,68,68,244,48,85,218,93,...>>
* 10> <<Check:4/binary, _/binary>> = crypto:hash(sha256, crypto:hash(sha256, RLPEncodedData)).
* <<3,182,66,215,195,99,112,99,25,7,84,31,151,188,149,81,
* 189,184,82,207,164,68,128,43,11,174,236,59,77,...>>
* 11> Hash.
* <<3,182,66,215>>
* 12> Check.
* <<3,182,66,215>>
* ```
*
* What we're really interested in is `Data`
*
* ```erlang
* 14> {Data, _} = rlp:decode(X).
* {[<<"\f">>,
* <<1>>,
* <<1,201,99,126,70,0,231,171,59,194,230,127,198,64,232,35,
* 118,68,68,244,48,85,218,93,85,...>>,
* <<1,123,102,230,195,5,7,8,54,228,233,121,32,82,61,195,234,
* 89,203,191,216,108,88,186,...>>,
* <<"\n">>,
* <<15,38,245,97,200,0>>,
* <<0>>,
* <<"\t">>,<<"hainana">>],
* <<3,182,66,215>>}
* ```
*
* `Data` is a list. The first field `<<"\f">>` is meant to be an integer which
* tells us what type of data this is.
*
* ```erlang
* 16> $\f.
* 12
* ```
*
* If we look at our table
* (https://github.com/aeternity/protocol/blob/master/serializations.md#table-of-object-tags),
* we see that a value of `12` is a spend transaction.
*
* The second field `<<1>>` tells us the "version" of the field orderings,
* which we can ignore for now.
*
* The remaining fields are the fields of a spend transaction (https://github.com/aeternity/protocol/blob/master/serializations.md#spend-transaction)
*
* ```erlang
* [ <sender> :: id() % <<1,201,99,126,...> "=" "ak_2XhCkjzTwcq1coXSSzHJoMZkUzTwnjH88zmPGkkowUsFNTo9UE"
* , <recipient> :: id() % <<1,123,102,230,...> "=" "ak_wM8yFU8eSETXU7VSN48HMDmevGoCMiuveQZgkPuRn1nTiRqyv"
* , <amount> :: int() % <<"\n">> "=" 10
* , <fee> :: int() % <<15,38,245,97,200,0>> "=" 16_660_000_000_000
* , <ttl> :: int() % <<0>> "=" 0
* , <nonce> :: int() % <<"\t">> "=" 9
* , <payload> :: binary() % <<"hainana">> "=" "hainana"
* ]
* ```
*
* Our task here is to be able to pull apart the "tx_..." string into its fields.
*
* Converting the binaries to integers is pretty trivial. The only mildly
* annoying thing is the `id` type.
*
* `id`s have two fields: a single-byte prefix which says which type of ID it
* is. In this case, both `id`s have a prefix of `1`, which means they are both
* normal accounts (hence the `ak_` prefix on the "api-encoded" id). The other
* options are oracles (prefix `4`/`ok_`), contracts (prefix `5`/`ct_`), or
* names (prefix `2`/`nm_`)
*
* To "api-encode" the name, we first pick the appropriate prefix based on the
* first byte (in this case `1 -> "ak_"). The remaining 32 bytes are then
* double-SHA'd to get the 4-byte check suffix
*
* ```erlang
* 30> SenderBytes = lists:nth(3, Data).
* <<1,201,99,126,70,0,231,171,59,194,230,127,198,64,232,35,
* 118,68,68,244,48,85,218,93,85,120,164,154,55,...>>
* 31> <<1, SenderAddrBytes/binary>> = SenderBytes.
* <<1,201,99,126,70,0,231,171,59,194,230,127,198,64,232,35,
* 118,68,68,244,48,85,218,93,85,120,164,154,55,...>>
* 32> DoubleSha = fun(Bytes) -> <<Foo:4/binary, _/binary>> = crypto:hash(sha256, crypto:hash(sha256, Bytes)), Foo end.
* #Fun<erl_eval.44.97283095>
* 33> "ak_" ++ b58:enc(<<SenderAddrBytes/binary, (DoubleSha(SenderAddrBytes))/binary>>).
* "ak_2XhCkjzTwcq1coXSSzHJoMZkUzTwnjH88zmPGkkowUsFNTo9UE"
* 34> RecipBytes = lists:nth(4, Data).
* <<1,123,102,230,195,5,7,8,54,228,233,121,32,82,61,195,234,
* 89,203,191,216,108,88,186,7,3,234,139,205,...>>
* 35> <<1, RecipAddrBytes/binary>> = RecipBytes.
* <<1,123,102,230,195,5,7,8,54,228,233,121,32,82,61,195,234,
* 89,203,191,216,108,88,186,7,3,234,139,205,...>>
* 36> "ak_" ++ b58:enc(<<RecipAddrBytes/binary, (DoubleSha(RecipAddrBytes))/binary>>).
* "ak_wM8yFU8eSETXU7VSN48HMDmevGoCMiuveQZgkPuRn1nTiRqyv"
* ```
*
* ```js
* > anth.deconstruct("tx_+FgMAaEByWN+RgDnqzvC5n/GQOgjdkRE9DBV2l1VeKSaN1r6GNyhAXtm5sMFBwg25Ol5IFI9w+pZy7/YbFi6BwPqi80KuKdsCoYPJvVhyAAACYdoYWluYW5hA7ZC1w==")
* {tag : 'SpendTx',
* version : 1n,
* fields : {sender : "ak_2XhCkjzTwcq1coXSSzHJoMZkUzTwnjH88zmPGkkowUsFNTo9UE",
* recipient : "ak_wM8yFU8eSETXU7VSN48HMDmevGoCMiuveQZgkPuRn1nTiRqyv",
* amount : 10n,
* fee : 16660000000000n,
* ttl : 0n,
* nonce : 9n,
* payload : Uint8Array([104, 97, 105, 110, 97, 110, 97])}}
* ```
*
* @module
*/
export {
// types
tx_str,
deconstructed_tx,
// functions
deconstruct_tx
};
import * as b64 from './b64.js'
import * as bin from './bin.js'
import * as rlp from './rlp.js'
/**
* Alias type for a `tx_...` string
*/
type tx_str = string;
/**
* Alias type for a `sg_...` string
*/
type sg_str = string;
/**
* types of decoded tx we currently support
* @internal
*/
type tx_type_str
= 'SignedTx'
| 'SpendTx'
| 'ContractCreateTx'
| 'ContractCallTx';
/**
* Results of deconstruct_tx
*/
type deconstructed_tx
= {type : 'SignedTx',
version : bigint,
fields : fields_SignedTx}
| {type : 'SpendTx',
version : bigint,
fields : fields_SpendTx}
| {type : 'ContractCreateTx',
version : bigint,
fields : fields_ContractCreateTx}
| {type : 'ContractCallTx'
version : bigint,
fields : fields_ContractCallTx};
/**
* Convenient type alias
*
* @internal
*/
type rlpdata = rlp.decoded_data;
/**
* Fields types
*/
type fields
= fields_SignedTx
| fields_SpendTx
| fields_ContractCreateTx
| fields_ContractCallTx;
type fields_SignedTx
= {signatures : Array<sg_str>,
transaction : tx_str};
type fields_SpendTx
= {sender : string,
recipient : string,
amount : bigint,
fee : bigint,
ttl : bigint,
nonce : bigint,
payload : Uint8Array};
/**
* Deconstruct a Tx
*/
function
deconstruct_tx
(tx_str: tx_str)
: deconstructed_tx
{
let b64_str : string = tx_str.slice(3); // tx_[...] -> [...]
let tx_rlp_encoded : Uint8Array = b64.decode(b64_str); // [...] -> bytes
let tx_data : Array<rlpdata> = shasha_rlp_decode_list(tx_rlp_encoded); // decode data and check the double-sha thing
let tx_type : bigint = bin.bytes_to_bigint(tx_data[0]); // get a bigint
let tts : tx_type_str = tx_type_str(tx_type);
let tx_version : bigint = bin.bytes_to_bigint(tx_data[1]);
let tx_fields : fields = deconstruct_fields(tts, tx_version, tx_data.slice(2));
return {type : tts,
version : tx_version,
fields : tx_fields};
}
/**
* Data that's "api-encoded" goes through the following stages:
*
* 1. data structure -> rlp decode data (arbitrary-depth [possibly 0] list of bytestrings)
* 2. rlp decode data -> bytestring
* 3. bytestring -> <<Bytestring/binary, Hash:4/binary>>
* 4. HashedBytestring -> base64/base58 string encoding
* 5. Add string prefix
*
* This function undoes step 3 and step 2, returns back the rlp decode data
*
* FIXME: Does not check double-sha (yet); need to figure out way to handle hash failures
* FIXME: No good way to handle failure cases
*
* @internal
*/
function
shasha_rlp_decode_list
(hashed_bs : Uint8Array)
: Array<rlpdata>
{
let len = hashed_bs.length;
let bytes = hashed_bs.slice(0, len - 4);
let {decoded_data} = rlp.decode(bytes);
return (decoded_data as Array<rlpdata>);
}
/**
* Convert an object tag that's a type of transaction to the type string
*
* See: https://github.com/aeternity/protocol/blob/master/serializations.md#table-of-object-tags
*
* @internal
*/
function
tx_type_str
(tx_type_int : bigint)
: tx_type_str
{
switch (tx_type_int)
{
case 11n: return 'SignedTx';
case 12n: return 'SpendTx';
case 42n: return 'ContractCreateTx';
case 43n: return 'ContractCallTx';
default: throw new Error('invalid transaction type: ' + tx_type_int);
}
}
/**
* Given an array of data decoded from RLP, convert it to the fields, as
* appropriate as given by the tx type string and the version
*/
function
deconstruct_fields
(tx_type_str : tx_type_str,
tx_version : bigint,
tx_rawfields : Array<rlpdata>)
: fields
{
switch (tx_type_str)
{
// case 'SignedTx' : return deconstruct_fields_SignedTx(tx_rawfields);
case 'SpendTx' : return deconstruct_fields_SpendTx(tx_rawfields);
// case 'ContractCreateTx' : return deconstruct_fields_ContractCreateTx(tx_rawfields);
// case 'ContractCallTx' : return deconstruct_fields_ContractCallTx(tx_rawfields);
default : throw new Error('invalid tx type str: ' + tx_type_str);
}
}
// TODO: do all this in Erlang
function
deconstruct_fields_SpendTx
(fields: Array<rlpdata>)
: fields_SpendTx
{
let sender_bytes = fields[0];
let recip_bytes = fields[1];
let amount_bytes = fields[2];
let fee_bytes = fields[3];
let ttl_bytes = fields[4];
let nonce_bytes = fields[5];
let payload_bytes = fields[6];
return {sender : encode_id(sender_bytes),
recipient : encode_id(sender_bytes),
amount : bin.bytes_to_bigint(amount_bytes),
fee : bin.bytes_to_bigint(fee_bytes),
ttl : bin.bytes_to_bigint(ttl_bytes),
nonce : bin.bytes_to_bigint(nonce_bytes),
payload : bin.bytes_to_bigint(payload_bytes)};
}
/**
* Convert a binary account/name/etc binary id into the appropriate type of string
*
* @internal
*/
function
encode_id
(id: Uint8Array)
: string
{
throw new Error('nyi');
}
/*
FIXME:
1. work out all this in Erlang to clear conceptual goo
2. think about how i want type safety etc to work
3. think about a language to assert that the data has the correct shape to it
4. get some examples working in Erlang
5. convert erlang code back to ts
*/
-112
View File
@@ -1,112 +0,0 @@
/**
* Concatenate two bitstrings
*/
function
bits_concat
(bits1 : bits,
bits2 : bits)
: bits
{
let result_bit_length : number = bits1.bit_length + bits2.bit_length;
let bytes1 : Uint8Array = bits1.bytes;
let bytes2 : Uint8Array = bits2.bytes;
// using zeros here because of our xor trick in a minute
let result_bits : bits = bits_zeros(result_bit_length);
let result_bytes : Uint8Array = result_bits.bytes;
// alright so
// we can start by copying the first bytes into result bytes
for (let bytes1_idx0 = 0;
bytes1_idx0 < bytes1.length;
bytes1_idx0++)
{
result_bytes[bytes1_idx0] = bytes1[bytes1_idx0];
}
// next
// we need to calculate the left-shift offset
// this will be 8 - (bytes1.bit_length % 8)
let num_trailing_zeros_in_first_array : number = 8 - (bits1.bit_length % 8);
// so
// bytes1: ABCD_EF00
// bytes2: GH12_3000
// result: ABCD_EFGH 1230_0000
// ah ok, so we need to for each byte in the second array
// take the first however many bits, xor it with the existing byte
// then take the last however many bits and place them into the next byte
// this is super confusing but
// ABCD_EF00
// GH12_3456
// operation:
// ABCD_EF00
// xor 0000_00GH
// = ABCD_EFGH 1234_5600
//
// then on the next iteration
// 1234_5600
// abcd_efgh
// ->
// 1234_56ab cdef_gh00
//
// ah so there's a pattern
// however many trailing 0s there are in the first array
// say there's 2
// we take the first 2 bits of the upcoming byte
// xor that against the current byte
// take the last 6 bits of the upcoming byte
// set the next byte to that
//
// have to think about edge behavior
// this is ripe for off-by-1 errors
// but i think the general idea is right
//
// so we start the iteration
// on the last byte of the first array
let last_byte_of_first_array_idx0 : number = bytes1.length - 1;
// and we end
// on the second-to-last-byte of the result array
let second_to_last_byte_of_result_array_idx0 : number = result_bytes.length - 2;
// the reason we do that is because we're doing this is because we are
// going along, xoring against the current byte and then setting the next
// byte
//
// ok so
for (let this_result_byte_idx0 = last_byte_of_first_array_idx0;
this_result_byte_idx0 <= second_to_last_byte_of_result_array_idx0;
this_result_byte_idx0++)
{
let this_result_byte : number = result_bytes[this_result_byte_idx0];
// ok here we need to fish out the relevant byte of the second array
// gaaah
// so this will be 0 at the start of the loop
let relevant_byte_of_second_array_idx0 : number = this_result_byte_idx0 - last_byte_of_first_array_idx0;
let relevant_byte_of_second_array : number = bytes2[relevant_byte_of_second_array_idx0];
// ok so let's fish out the leading digits
// the number of leading digits is the number of trailing 0s in the first array
let num_leading_digits : number = num_trailing_zeros_in_first_array;
let num_trailing_digits : number = 8 - num_leading_digits;
// suppose there are 2 leading digits and 6 trailing digits
// ABCD_EFGH
// leading digits are
// ABCD_EFGH >> 6 = 0000_00AB
// trailing digits are
// (ABCD_EFGH << 2) % 255 = CDEF_GH00
let leading_digits : number = relevant_byte_of_second_array >> num_trailing_digits;
let trailing_digits : number = (relevant_byte_of_second_array << num_leading_digits) % 255;
// xor the current byte against the leading digits
let new_this_result_byte : number = this_result_byte ^ leading_digits;
result_bytes[this_result_byte_idx0] = new_this_result_byte;
// set the next byte to the trailing digits
result_bytes[this_result_byte_idx0 + 1] = trailing_digits;
}
// i think we're done
return {bit_length : result_bit_length,
bytes : result_bytes};
}
-159
View File
@@ -1,159 +0,0 @@
const OTAG_SIGNED_TX = 11n;
const OTAG_SPEND_TX = 12n;
const OTAG_CONTRACT_CREATE_TX = 42n;
const OTAG_CONTRACT_CALL_TX = 43n;
type otag = 11n | 12n | 42n | 43n;
const IDTAG_ACCOUNT = 1n;
const IDTAG_NAME = 2n;
const IDTAG_CONTRACT = 5n;
type idtag = 1n | 2n | 5n;
type id =
{tag : idtag,
hash : Uint8Array};
type SignedTx =
{signatures : Array<Uint8Array>,
transaction : Uint8Array};
type SpendTx =
{sender : id,
recipient : id,
amount : bigint,
fee : bigint,
ttl : bigint,
nonce : bigint,
payload : Uint8Array};
type ContractCreateTx =
{owner : id,
nonce : bigint,
code : Uint8Array,
ct_version : bigint,
fee : bigint,
ttl : bigint,
deposit : bigint,
amount : bigint,
gas : bigint,
gas_price : bigint,
call_data : Uint8Array};
type ContractCallTx =
{caller : id,
nonce : bigint,
contract : id,
abi_version : bigint,
fee : bigint,
ttl : bigint,
amount : bigint,
gas : bigint,
gas_price : bigint,
call_data : Uint8Array};
type tx = SignedTx | SpendTx | ContractCreateTx | ContractCallTx;
type decoded_tx =
{tag : otag,
version : Uint8Array,
tx : tx};
/**
* Decode a `tx_Base64` string
*/
function
decode_tx(tx_str : string): decoded_tx {
let base64_stuff : string = tx_str.slice(3); // tx_[...] -> [...]
let stuff : Uint8Array = b64.decode(base64_stuff); // <<Bin/binary, DoubleSha:4>>
let rlp_stuff : Uint8Array = stuff.slice(0, stuff.length - 4); // <<Bin/binary>>
let decoded_datas : Array<rlp.decoded_data> = rlp.decode(rlp_stuff).decoded_data as Array<rlp.decoded_data>; // decoded_data : list(rlp.decoded_data() :: binary() | list(decoded_data()))
// tag, vsn
let tag_bytes : Uint8Array = decoded_datas[0] as Uint8Array; // [tag, vsn, fields] -> tag
let tag : bigint = bytes_to_bigint(tag_bytes); // <<Tag:(byte_size(TagBytes))>> = TagBytes
let vsn : Uint8Array = decoded_datas[1] as Uint8Array;
// tx fields
let tx_fields : Array<rlp.decoded_data> = decoded_datas.slice(2);
let tx : tx = decode_fields(tag, tx_fields);
return {tag: tag as otag, version: vsn, tx: tx};
}
/**
* Decode a transaction given the raw fields
*
* @internal
*/
function
decode_fields(tag: bigint, fields: Array<rlp.decoded_data>): tx {
switch (tag) {
case 11n: return decode_fields_SignedTx(fields);
case 12n: return decode_fields_SpendTx(fields);
case 42n: return decode_fields_ContractCreateTx(fields);
case 43n: return decode_fields_ContractCallTx(fields);
default : throw new Error("invalid object tag: " + tag);
}
console.log('fields: ', fields);
throw new Error("nyi");
}
/**
* Decode a SignedTx
*
* @internal
*/
function
decode_fields_SignedTx(fields: Array<rlp.decoded_data>): SignedTx {
throw new Error('nyi');
}
/**
* Decode a SpendTx
*
* @internal
*/
function
decode_fields_SpendTx(fields: Array<rlp.decoded_data>): SpendTx {
// [<sender> :: id(),
// <recipient> :: id(),
// <amount> :: int(),
// <fee> :: int(),
// <ttl> :: int(),
// <nonce> :: int(),
// <payload> :: binary()]
let sender : id = decode_id(fields[0] as Uint8Array);
let recipient : id = decode_id(fields[1] as Uint8Array);
let amount : bigint = bytes_to_bigint(fields[2] as Uint8Array);
let fee : bigint = bytes_to_bigint(fields[3] as Uint8Array);
let ttl : bigint = bytes_to_bigint(fields[4] as Uint8Array);
let nonce : bigint = bytes_to_bigint(fields[5] as Uint8Array);
let payload : Uint8Array = fields[6] as Uint8Array;
return {sender : sender,
recipient : recipient,
amount : amount,
fee : fee,
ttl : ttl,
nonce : nonce,
payload : payload};
}
function
decode_fields_ContractCreateTx(fields: Array<rlp.decoded_data>): ContractCreateTx {
throw new Error('nyi');
}
function
decode_fields_ContractCallTx(fields: Array<rlp.decoded_data>): ContractCallTx {
throw new Error('nyi');
}
function
decode_id(id: Uint8Array): id {
let idtag : idtag = BigInt(id[0]) as idtag;
return {tag: idtag, hash: id.slice(1)};
}
-23
View File
@@ -1,23 +0,0 @@
/**
* Vanillae Seed Phrase Library
*
* Refs:
* 1. BIP 39: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki
*
* @module
*/
/**
* Get a given number of seed bits.
*
* `how_many` must be a multiple of 33.
*
* Ref: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#generating-the-mnemonic
*/
function
seed_and_check_bits
(how_many : number)
: Uint8Array
{
}