@@ -1531,3 +1531,70 @@ func TestLogicSigMsigBothFlags(t *testing.T) {
15311531 err = verifyLogicSig ()
15321532 require .ErrorContains (t , err , "LogicSig should only have one of Sig, Msig, or LMsig but has more than one" )
15331533}
1534+
1535+ func TestAuthAddrSenderDiff (t * testing.T ) {
1536+ partitiontest .PartitionTest (t )
1537+
1538+ t .Run ("v41-disabled" , func (t * testing.T ) { testAuthAddrSenderDiff (t , protocol .ConsensusV41 , false ) })
1539+ t .Run ("future-enabled" , func (t * testing.T ) { testAuthAddrSenderDiff (t , protocol .ConsensusFuture , true ) })
1540+ }
1541+
1542+ func testAuthAddrSenderDiff (t * testing.T , consensusVer protocol.ConsensusVersion , enforceEnabled bool ) {
1543+ secrets , addrs , _ := generateAccounts (3 )
1544+ sender := addrs [0 ]
1545+ otherAddr := addrs [1 ]
1546+
1547+ blockHeader := createDummyBlockHeader (consensusVer )
1548+ proto := config .Consensus [consensusVer ]
1549+
1550+ makeTxn := func () transactions.Transaction {
1551+ return transactions.Transaction {
1552+ Type : protocol .PaymentTx ,
1553+ Header : transactions.Header {
1554+ Sender : sender ,
1555+ Fee : basics.MicroAlgos {Raw : proto .MinTxnFee },
1556+ FirstValid : 1 ,
1557+ LastValid : 100 ,
1558+ GenesisHash : blockHeader .GenesisHash ,
1559+ },
1560+ PaymentTxnFields : transactions.PaymentTxnFields {
1561+ Receiver : addrs [2 ],
1562+ Amount : basics.MicroAlgos {Raw : 1000 },
1563+ },
1564+ }
1565+ }
1566+
1567+ // Test 1: AuthAddr == Sender
1568+ tx1 := makeTxn ()
1569+ stxn := tx1 .Sign (secrets [0 ])
1570+ stxn .AuthAddr = sender
1571+ groupCtx , err := PrepareGroupContext ([]transactions.SignedTxn {stxn }, & blockHeader , nil , nil )
1572+ require .NoError (t , err )
1573+ err = verifyTxn (0 , groupCtx )
1574+ if enforceEnabled {
1575+ require .ErrorContains (t , err , "AuthAddr must be different from Sender" ,
1576+ "AuthAddr == Sender should be rejected when enforcement is enabled" )
1577+ } else {
1578+ require .NoError (t , err ,
1579+ "AuthAddr == Sender should be allowed when enforcement is disabled" )
1580+ }
1581+
1582+ // Test 2: Empty AuthAddr should always be allowed
1583+ tx2 := makeTxn ()
1584+ stxn = tx2 .Sign (secrets [0 ])
1585+ stxn .AuthAddr = basics.Address {}
1586+ groupCtx , err = PrepareGroupContext ([]transactions.SignedTxn {stxn }, & blockHeader , nil , nil )
1587+ require .NoError (t , err )
1588+ err = verifyTxn (0 , groupCtx )
1589+ require .NoError (t , err , "empty AuthAddr should always be allowed" )
1590+
1591+ // Test 3: AuthAddr != Sender should pass the check (legitimate rekeying case)
1592+ // Sign with otherAddr's key to pass signature verification
1593+ tx3 := makeTxn ()
1594+ stxn = tx3 .Sign (secrets [1 ]) // Sign with secrets[1] which corresponds to otherAddr
1595+ stxn .AuthAddr = otherAddr
1596+ groupCtx , err = PrepareGroupContext ([]transactions.SignedTxn {stxn }, & blockHeader , nil , nil )
1597+ require .NoError (t , err )
1598+ err = verifyTxn (0 , groupCtx )
1599+ require .NoError (t , err , "AuthAddr != Sender should pass verification (legitimate rekeying)" )
1600+ }
0 commit comments