Skip to content

Commit

Permalink
feat(transaction)!: allow multiple signers (#1053)
Browse files Browse the repository at this point in the history
Description
---
Allow multiple signers for a transaction

Motivation and Context
---
This enables many use cases including paying for another user's fees
(gasless) and invoking two or more components owned by different public
keys in the same transaction.

It is possible for a party to remove all signatures but one and still
have a valid transaction. In future, we'll add a final signature that
includes all signatures in the preimage.

How Has This Been Tested?
---
Manually. TODO: Multiple signer integration test 

What process can a PR reviewer use to test or verify this change?
---
Submit transactions requiring badges from multiple public keys

Breaking Changes
---

- [ ] None
- [x] Requires data directory to be deleted
- [ ] Other - Please specify

BREAKING CHANGE: wallet database changed, transaction struct changed
  • Loading branch information
sdbondi authored Jun 27, 2024
1 parent 5d25f35 commit b98b1f8
Show file tree
Hide file tree
Showing 37 changed files with 1,191 additions and 1,055 deletions.
19 changes: 12 additions & 7 deletions applications/tari_dan_app_utilities/src/transaction_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,15 @@ where TTemplateProvider: TemplateProvider<Template = LoadedTemplate>
virtual_substates: VirtualSubstates,
) -> Result<ExecutionOutput, Self::Error> {
let timer = Instant::now();
// Include ownership token for the signers of this in the auth scope
let owner_token = get_auth_token(transaction.signer_public_key());
// Include signature public key badges for all transaction signers in the initial auth scope
// NOTE: we assume all signatures have already been validated.
let initial_ownership_proofs = transaction
.signatures()
.iter()
.map(|sig| public_key_to_fungible_address(sig.public_key()))
.collect();
let auth_params = AuthParams {
initial_ownership_proofs: vec![owner_token],
initial_ownership_proofs,
};

let initial_cost = 0;
Expand Down Expand Up @@ -152,10 +157,10 @@ where TTemplateProvider: TemplateProvider<Template = LoadedTemplate>
}
}

fn get_auth_token(public_key: &PublicKey) -> NonFungibleAddress {
let public_key =
RistrettoPublicKeyBytes::from_bytes(public_key.as_bytes()).expect("Expected public key to be 32 bytes");
NonFungibleAddress::from_public_key(public_key)
fn public_key_to_fungible_address(public_key: &PublicKey) -> NonFungibleAddress {
RistrettoPublicKeyBytes::from_bytes(public_key.as_bytes())
.expect("Expected public key to be 32 bytes")
.to_non_fungible_address()
}

#[derive(Debug, thiserror::Error)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,62 +20,63 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

import { useState } from "react";
import { TableContainer, Table, TableRow, TableBody, Collapse } from "@mui/material";
import { DataTableCell, AccordionIconButton } from "../../Components/StyledComponents";
import {useState} from "react";
import {TableContainer, Table, TableRow, TableBody, Collapse} from "@mui/material";
import {DataTableCell, AccordionIconButton} from "../../Components/StyledComponents";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
import CodeBlockExpand from "../../Components/CodeBlock";
import { useTheme } from "@mui/material/styles";
import type { Instruction } from "@tariproject/typescript-bindings";
import {useTheme} from "@mui/material/styles";
import type {Instruction, TransactionSignature} from "@tariproject/typescript-bindings";

function RowData({ title, data }: { title: string; data: Instruction }, index: number) {
const [open, setOpen] = useState(false);
const theme = useTheme();
return (
<>
<TableRow key={`${index}-1`}>
<DataTableCell width={90} sx={{ borderBottom: "none", textAlign: "center" }}>
<AccordionIconButton
aria-label="expand row"
size="small"
onClick={() => {
setOpen(!open);
}}
>
{open ? <KeyboardArrowUpIcon /> : <KeyboardArrowDownIcon />}
</AccordionIconButton>
</DataTableCell>
<DataTableCell>{title}</DataTableCell>
</TableRow>
<TableRow key={`${index}-2`}>
<DataTableCell
style={{
paddingBottom: theme.spacing(1),
paddingTop: 0,
borderBottom: "none",
}}
colSpan={2}
>
<Collapse in={open} timeout="auto" unmountOnExit>
<CodeBlockExpand title={title} content={data} />
</Collapse>
</DataTableCell>
</TableRow>
</>
);
function RowData({title, data}: { title: string; data: Instruction }, index: number) {
const [open, setOpen] = useState(false);
const theme = useTheme();
return (
<>
<TableRow key={`${index}-1`}>
<DataTableCell width={90} sx={{borderBottom: "none", textAlign: "center"}}>
<AccordionIconButton
aria-label="expand row"
size="small"
onClick={() => {
setOpen(!open);
}}
>
{open ? <KeyboardArrowUpIcon/> : <KeyboardArrowDownIcon/>}
</AccordionIconButton>
</DataTableCell>
<DataTableCell>{title}</DataTableCell>
</TableRow>
<TableRow key={`${index}-2`}>
<DataTableCell
style={{
paddingBottom: theme.spacing(1),
paddingTop: 0,
borderBottom: "none",
}}
colSpan={2}
>
<Collapse in={open} timeout="auto" unmountOnExit>
<CodeBlockExpand title={title} content={data}/>
</Collapse>
</DataTableCell>
</TableRow>
</>
);
}

export default function FeeInstructions({ data }: { data: Array<Instruction> }) {
return (
<TableContainer>
<Table>
<TableBody>
{data.map((item: Instruction, index: number) => {
return <RowData key={index} title={Object.keys(item)[0]} data={item} />;
})}
</TableBody>
</Table>
</TableContainer>
);
export default function FeeInstructions({data}: { data: Array<Instruction> }) {
return (
<TableContainer>
<Table>
<TableBody>
{data.map((item: Instruction, index: number) => {
return <RowData key={index} title={Object.keys(item)[0]} data={item}/>;
})}
</TableBody>
</Table>
</TableContainer>
);
}

Loading

0 comments on commit b98b1f8

Please sign in to comment.