Skip to content

Commit 91fc86d

Browse files
author
Nicolas Tallar
committed
Merge branch 'fix/createSenderAcc' into phase/3/txExecution
2 parents 6b5311c + 8d816a0 commit 91fc86d

File tree

2 files changed

+34
-9
lines changed

2 files changed

+34
-9
lines changed

src/main/scala/io/iohk/ethereum/ledger/Ledger.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,22 +83,22 @@ class LedgerImpl(vm: VM, blockchainConfig: BlockchainConfig) extends Ledger with
8383
* if one of them failed
8484
*/
8585
@tailrec
86-
private def executeTransactions(signedTransactions: Seq[SignedTransaction], world: InMemoryWorldStateProxy,
86+
private[ledger] final def executeTransactions(signedTransactions: Seq[SignedTransaction], world: InMemoryWorldStateProxy,
8787
blockHeader: BlockHeader, signedTransactionValidator: SignedTransactionValidator,
8888
acumGas: BigInt = 0, acumReceipts: Seq[Receipt] = Nil): Either[TxsExecutionError, BlockResult] =
8989
signedTransactions match {
9090
case Nil =>
9191
Right(BlockResult(worldState = world, gasUsed = acumGas, receipts = acumReceipts))
9292

9393
case Seq(stx, otherStxs@_*) =>
94-
val senderAccount = world.getAccount(stx.senderAddress)
94+
val (senderAccount, worldForTx) = world.getAccount(stx.senderAddress).map(a => (a, world))
95+
.getOrElse ((Account.Empty, world.saveAccount(stx.senderAddress, Account.Empty)))
9596
val upfrontCost = calculateUpfrontCost(stx.tx)
96-
val validatedStx = senderAccount
97-
.toRight(Left(TxsExecutionError(s"Account of tx sender ${stx.senderAddress.toString} not found")))
98-
.flatMap(account => signedTransactionValidator.validate(stx, account, blockHeader, upfrontCost, acumGas))
97+
val validatedStx = signedTransactionValidator.validate(stx, senderAccount, blockHeader, upfrontCost, acumGas)
98+
9999
validatedStx match {
100100
case Right(_) =>
101-
val TxResult(newWorld, gasUsed, logs) = executeTransaction(stx, blockHeader, world)
101+
val TxResult(newWorld, gasUsed, logs) = executeTransaction(stx, blockHeader, worldForTx)
102102

103103
val receipt = Receipt(
104104
postTransactionStateHash = newWorld.stateRootHash,
@@ -254,7 +254,7 @@ class LedgerImpl(vm: VM, blockchainConfig: BlockchainConfig) extends Ledger with
254254
private[ledger] def prepareProgramContext(stx: SignedTransaction, blockHeader: BlockHeader, worldStateProxy: InMemoryWorldStateProxy, config: EvmConfig): PC =
255255
stx.tx.receivingAddress match {
256256
case None =>
257-
val address = worldStateProxy.createAddress(stx.senderAddress)
257+
val address = worldStateProxy.createAddress(creatorAddr = stx.senderAddress)
258258
val world1 = worldStateProxy.transfer(stx.senderAddress, address, UInt256(stx.tx.value))
259259
ProgramContext(stx, address, Program(stx.tx.payload), blockHeader, world1, config)
260260

src/test/scala/io/iohk/ethereum/ledger/LedgerSpec.scala

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -663,10 +663,35 @@ class LedgerSpec extends FlatSpec with PropertyChecks with Matchers {
663663
}
664664
}
665665

666+
it should "create sender account if it does not exists" in new TestSetup {
667+
668+
val inputData = ByteString("the payload")
669+
670+
val newAccountKeyPair: AsymmetricCipherKeyPair = generateKeyPair()
671+
val newAccountAddress = Address(kec256(newAccountKeyPair.getPublic.asInstanceOf[ECPublicKeyParameters].getQ.getEncoded(false).tail))
672+
673+
val mockVM = new MockVM((pc: Ledger.PC) => {
674+
pc.env.inputData shouldEqual ByteString.empty
675+
createResult(pc, defaultGasLimit, defaultGasLimit, 0, None, returnData = ByteString("contract code"))
676+
})
677+
val ledger = new LedgerImpl(mockVM, blockchainConfig)
678+
679+
val tx: Transaction = defaultTx.copy(gasPrice = 0, receivingAddress = None, payload = inputData)
680+
val stx: SignedTransaction = SignedTransaction.sign(tx, newAccountKeyPair, blockchainConfig.chainId)
681+
682+
val result: Either[BlockExecutionError.TxsExecutionError, BlockResult] = ledger.executeTransactions(
683+
Seq(stx),
684+
initialWorld,
685+
defaultBlockHeader,
686+
(new Mocks.MockValidatorsAlwaysSucceed).signedTransactionValidator)
687+
688+
result shouldBe a[Right[_, BlockResult]]
689+
result.map(br => br.worldState.getAccount(newAccountAddress)) shouldBe Right(Some(Account(nonce = 1)))
690+
}
666691

667692
trait TestSetup {
668-
val originKeyPair = generateKeyPair()
669-
val receiverKeyPair = generateKeyPair()
693+
val originKeyPair: AsymmetricCipherKeyPair = generateKeyPair()
694+
val receiverKeyPair: AsymmetricCipherKeyPair = generateKeyPair()
670695
//byte 0 of encoded ECC point indicates that it is uncompressed point, it is part of spongycastle encoding
671696
val originAddress = Address(kec256(originKeyPair.getPublic.asInstanceOf[ECPublicKeyParameters].getQ.getEncoded(false).tail))
672697
val receiverAddress = Address(kec256(receiverKeyPair.getPublic.asInstanceOf[ECPublicKeyParameters].getQ.getEncoded(false).tail))

0 commit comments

Comments
 (0)